<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-9675303</id><updated>2012-01-22T17:12:53.975+01:00</updated><category term='Geocities'/><category term='CMake'/><category term='Bunjalloo'/><category term='Google Code'/><category term='devkitpro'/><category term='Woopsi'/><category term='Review'/><category term='ARM'/><category term='Lords Of Midnight'/><category term='Java'/><category term='Chaos'/><category term='Mercurial'/><category term='Programming'/><category term='Unit Tests'/><category term='SCons'/><category term='Vim'/><category term='Profiler'/><category term='GBA'/><category term='Git'/><category term='Nintendo DSi'/><category term='Bugs'/><category term='AndroidMarket'/><category term='Linux'/><category term='Nintendo'/><category term='Eclipse'/><category term='DSi'/><category term='Tools'/><category term='DS'/><category term='Ubuntu'/><category term='Elite'/><category term='Game Boy Advance'/><category term='Android'/><category term='Freescape'/><category term='Waf'/><category term='HOWTO'/><title type='text'>Homebrew Coding</title><subtitle type='html'>Details of what I'm wasting my time on at the moment, in particular what homebrew game or console project I'm working on.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>84</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-9675303.post-1726271273071752253</id><published>2012-01-21T22:38:00.000+01:00</published><updated>2012-01-21T22:38:59.102+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Lords Of Midnight'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><category scheme='http://www.blogger.com/atom/ns#' term='HOWTO'/><title type='text'>How to recruit on LOM</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;I've had an email about how to recruit on my Android&amp;nbsp;&lt;a href="https://market.android.com/details?id=war.of.the.solstice"&gt;Lords of Midnight remake - "the War of the Solstice"&lt;/a&gt;. That means other people are probably stuck too and haven't asked. Here are the basics.&lt;br /&gt;&lt;br /&gt;From the start of the game, go Northwest, Northwest, Northeast and you'll stand on the same spot as the Lord of Shadows. Here I've done it as Morkin, but you can use any of the starting group.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-OSJdIHuyfvc/Txsv3pOHzOI/AAAAAAAABXM/qj6TOo4vig4/s1600/lom-main.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://4.bp.blogspot.com/-OSJdIHuyfvc/Txsv3pOHzOI/AAAAAAAABXM/qj6TOo4vig4/s320/lom-main.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Now touch the name part of the text (where it says "Morkin. He stands in the Forest of Shadows, looking Northeast."). This brings up the "Think" screen.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-sCJNNVN9Tvk/Txsv2z_7NsI/AAAAAAAABXE/pXRJfqs7U0E/s1600/lom-right.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://4.bp.blogspot.com/-sCJNNVN9Tvk/Txsv2z_7NsI/AAAAAAAABXE/pXRJfqs7U0E/s320/lom-right.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;On this screen, touch the right hand part of the text. This brings up the "Seek" screen, where you can do the recruiting.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-ALkAtLb62xY/Txsv2fURnVI/AAAAAAAABW8/mBPxv8bout4/s1600/lom-recruit.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://4.bp.blogspot.com/-ALkAtLb62xY/Txsv2fURnVI/AAAAAAAABW8/mBPxv8bout4/s320/lom-recruit.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;On here, touch the option to recruit the Lord of Shadows. That's it!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-1726271273071752253?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/1726271273071752253/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2012/01/how-to-recruit-on-lom.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/1726271273071752253'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/1726271273071752253'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2012/01/how-to-recruit-on-lom.html' title='How to recruit on LOM'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-OSJdIHuyfvc/Txsv3pOHzOI/AAAAAAAABXM/qj6TOo4vig4/s72-c/lom-main.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-8681376832383293469</id><published>2012-01-13T22:28:00.000+01:00</published><updated>2012-01-13T22:28:45.297+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><title type='text'>Silly Predictions For Android Versions In 2012</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;span class="zemanta-img separator" style="clear: right;"&gt;&lt;a href="http://commons.wikipedia.org/wiki/File:Android_chart.png" style="clear: right; display: block; float: right; margin-left: 1em; margin-right: 1em;"&gt;&lt;img alt="English: The following chart presents the prev..." height="163" src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/7c/Android_chart.png/300px-Android_chart.png" style="border: none; font-size: 0.8em;" width="300" /&gt;&lt;/a&gt;&lt;span class="zemanta-img-attribution" style="clear: both; float: right; margin-left: 1em; margin-right: 1em; width: 300px;"&gt;Image via &lt;a href="http://commons.wikipedia.org/wiki/File:Android_chart.png"&gt;Wikipedia&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;Last week Google released the &lt;a href="http://developer.android.com/resources/dashboard/platform-versions.html"&gt;latest numbers with the percentage of each Android version accessing the Android Market&lt;/a&gt;. What really jumped out at me is the rise and rise of Gingerbread (2.3.x), and the fall of Froyo (2.2). In the past I've been a bit skeptical of Google's commitment to older versions of Android. Looking at the way things advance, it makes no sense for them to dedicate resources to try and make life easier for developers on older devices. Every year the release 2 versions ago more or less disappears, or that's the way things have been tending to go for the last couple of years at least.&lt;br /&gt;&lt;br /&gt;Here's a graph of how the relative percentage has changed over the last 18 months. I've occasionally jotted down the percentage numbers in a spreadsheet, and the rest I got from the &lt;a href="http://www.archive.org/web/web.php"&gt;Wayback Machine&lt;/a&gt;. I've lumped minor releases together, so 2.3.1 and 2.3.2 are in the 2.3 bucket.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-4sTicndIO_8/TxChAieQ12I/AAAAAAAABWs/GWkEPaOMklM/s1600/android-versions.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-4sTicndIO_8/TxChAieQ12I/AAAAAAAABWs/GWkEPaOMklM/s1600/android-versions.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Version 2.1 (Eclair) is slowly disappearing, despite being at 55% back in July 2010. 2.2 (Froyo) is at 30% now, though in mid 2011 it peaked at 65% of the Google-approved devices online. Right now 2.3 (Gingerbread) is on the rise. I think the poor showing of 3.0 (Honeycomb) confirms that the driving force behind these numbers is mobile phones, rather than tablets. For those not paying attention, Honeycomb is only available on tablets, you see.&lt;br /&gt;&lt;br /&gt;Given all that, here's my predict-o-graph of how things will go in 2012. The yellow area marks my completely arbitrary prediction values of how the percentages will change. I've pulled the numbers out my /dev/backside.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-YC7WUHDgllg/TxChIpKtEVI/AAAAAAAABW0/Y840lfT09ZE/s1600/android-versions-future.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-YC7WUHDgllg/TxChIpKtEVI/AAAAAAAABW0/Y840lfT09ZE/s1600/android-versions-future.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;If everything follows the same pattern as previous years, by early summer 2012 Gingerbread will have peaked at about 60% of the market. By the end of 2012, Froyo will be on fewer than 10% of devices, Gingerbread will be on the slide, and the newest Android release - Ice Cream Sandwich, version 4.0 - will be taking over. I don't think Honeycomb is going to grow much this year, and the relative percentage of devices with 3.x may even shrink. No new tablets should be released with Honeycomb this year anyway - if they are released, they won't sell very well or will be upgraded to ICS pretty quickly - and most new or new-ish phones will have or get ICS too.&lt;br /&gt;&lt;br /&gt;As for me, and the games I've put out on Android... I'll continue to target 1.6+, since I don't really do anything that warrants a newer release and 2.2. is all I've got (curse you HTC and your locked bootloaders!) I think that by the end of this year I may have to look at upgrading, by then a 2nd hand Samsung may have come down to the kind of cheapskate price I'm willing to pay :-)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-8681376832383293469?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/8681376832383293469/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2012/01/silly-predictions-for-android-versions.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/8681376832383293469'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/8681376832383293469'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2012/01/silly-predictions-for-android-versions.html' title='Silly Predictions For Android Versions In 2012'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-4sTicndIO_8/TxChAieQ12I/AAAAAAAABWs/GWkEPaOMklM/s72-c/android-versions.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-3392486392858175395</id><published>2011-11-27T21:32:00.001+01:00</published><updated>2011-11-27T21:33:06.683+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ARM'/><category scheme='http://www.blogger.com/atom/ns#' term='AndroidMarket'/><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Lords Of Midnight'/><category scheme='http://www.blogger.com/atom/ns#' term='SCons'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><title type='text'>Non-ARM Android Apps</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;I've had 2 requests now for my Lords of Midnight remake on x86-based Android devices. A while ago &lt;a href="https://github.com/richq/scons-android/commit/f86dfd159daf4b49370d769279e2fea8c2a677ed"&gt;I updated the scons-android build system I use to support multiple architectures&lt;/a&gt;, but I didn't actually upload an x86 version to the Market. I thought nobody actually owned one of these mythical devices. Turns out that times are changing.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Back in July, &lt;a href="http://android-developers.blogspot.com/2011/07/multiple-apk-support-in-android-market.html"&gt;Google added multiple APK support to the Market&lt;/a&gt;. Sadly, the multiple APK idea is a bit limited in what you can do. The APKs have to be different in one of 3 key features only. These features are Open GL texture compression type, screen size and API level. Differences in other features - such as whether the device has a touch screen or not, has a hardware keyboard or not, the type of processor it has, and so on, are all ignored. If the only differences between the APKs are in these "minor" features then they are considered identical by the Market software and will not be allowed to coexist.&lt;br /&gt;&lt;br /&gt;The explanation I've read as to why this is the case is that the Market client application on devices doesn't provide enough information to the Market server for it to make use of all the feature filters. This makes some sense, as there have only really been multiple ARM ABIs available since June 2010 with release 4b of the NDK. But the Market &lt;i&gt;does&lt;/i&gt; already know how to hide non-compatible APKs from you, so I get the feeling this is more a case of "we can't be bothered to do this" rather than "we can't do this".&lt;br /&gt;&lt;br /&gt;As it stands, in order to do an x86 version of an app that uses native code while still maintaining compatibility with the majority ARM devices, you need to provide a so-called "fat binary". This is an APK that contains a copy of the ARM version (versions) of your library and the x86 version too. I think it's a bit of a shame that users with one type of processor have to pay the download-tax due to the inclusion of its "evil twin" opposing processor library. Fortunately the Android installation tools are smart enough not to copy useless libraries onto the device for use at run-time, so it is only the increased download size that is a problem.&lt;br /&gt;&lt;br /&gt;With this in mind, I've uploaded a new version of &lt;a href="https://market.android.com/details?id=war.of.the.solstice"&gt;War of the Solstice&lt;/a&gt; and &lt;a href="https://market.android.com/details?id=chaos.app"&gt;Chaos&lt;/a&gt; that support x86 too. Since I don't own anything that I can actually test these on it is a stab in the dark - it may work, but it will likely just crash, let me know with your 1 star reviews! ;-)&lt;br /&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-OHwIRsv4IMs/TtKdELH2XqI/AAAAAAAABWQ/d5JaDMVolFw/s1600/upload-chaos-x86.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-OHwIRsv4IMs/TtKdELH2XqI/AAAAAAAABWQ/d5JaDMVolFw/s1600/upload-chaos-x86.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Screenshot of the strange Android Market upload warnings&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;One thing that worried me slightly is that when you upload an ARM/x86 dual APK to the Market it says "this apk requests 2 native platforms that will be used for filtering". That makes it sounds like you need a strange ARM &lt;i&gt;and&lt;/i&gt; x86 device to make the game work. I hope that this is just a typo, and that the final APK works on just about everything.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-3392486392858175395?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/3392486392858175395/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2011/11/ive-had-2-requests-now-for-my-lords-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/3392486392858175395'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/3392486392858175395'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2011/11/ive-had-2-requests-now-for-my-lords-of.html' title='Non-ARM Android Apps'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-OHwIRsv4IMs/TtKdELH2XqI/AAAAAAAABWQ/d5JaDMVolFw/s72-c/upload-chaos-x86.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-2790226803570511226</id><published>2011-11-01T18:00:00.001+01:00</published><updated>2011-11-01T18:32:26.933+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><category scheme='http://www.blogger.com/atom/ns#' term='Elite'/><category scheme='http://www.blogger.com/atom/ns#' term='Bugs'/><title type='text'>3D Space Game Bug Fixes</title><content type='html'>&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;Back in July &lt;a href="http://quirkygba.blogspot.com/2011/07/another-war-of-solstice-update.html"&gt;I wrote that I was working on getting rid of the bugs in 3D Space Game&lt;/a&gt;. It has certainly taken me a while to get most of them squashed, but I've just &lt;a href="https://market.android.com/details?id=elite.app"&gt;uploaded a new version to the Android Market&lt;/a&gt; that fixes many crashes (hopefully!). You can also &lt;a href="http://code.google.com/p/ds-elite/"&gt;view the source code on the googlecode site&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;One of the nasty side effects of the old version was it's battery hogging behaviour. This was caused by my dreadfully inefficient Game Boy Advance-like emulation layer that was baked into the game. Over the last few months I've also improved my &lt;a href="https://code.google.com/p/android-ndk-profiler/"&gt;android-ndk-profiler&lt;/a&gt; so it works a lot better on older devices, and I've used it here to try and get better performance. Even with that I still did most of my tuning and debugging on the SDL and Linux port - Android is still missing something like &lt;a href="http://valgrind.org/"&gt;valgrind&lt;/a&gt; for native code and &lt;a class="zem_slink" href="http://en.wikipedia.org/wiki/GNU_Debugger" rel="wikipedia" title="GNU Debugger"&gt;GDB&lt;/a&gt; doesn't work prior to 2.3.&lt;br /&gt;&lt;br /&gt;For the umpteenth time I learned the following lesson: if an (Android) application crashes, chances are it is because I am writing past the end of a buffer into something important! Let's see if the lesson sticks this time :-)&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-2790226803570511226?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/2790226803570511226/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2011/11/3d-space-game-bug-fixes.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/2790226803570511226'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/2790226803570511226'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2011/11/3d-space-game-bug-fixes.html' title='3D Space Game Bug Fixes'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-4581013198741119818</id><published>2011-08-30T23:05:00.000+02:00</published><updated>2011-08-30T23:05:25.771+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AndroidMarket'/><category scheme='http://www.blogger.com/atom/ns#' term='Lords Of Midnight'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><title type='text'>Android Upload Fail</title><content type='html'>Nobody spotted the *ahem* "deliberate" mistake I made with the &lt;a href="http://quirkygba.blogspot.com/2011/07/another-war-of-solstice-update.html"&gt;last release&lt;/a&gt; of &lt;a href="https://market.android.com/details?id=war.of.the.solstice"&gt;War of the Solstice&lt;/a&gt; - I updated the textual list of changes on the Market, but completely failed to update the APK file to 1.3! In fact, I'd uploaded it to the developer's console, but didn't press the right combination of buttons to get it to actually go live.&lt;br /&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://s3.amazonaws.com/kym-assets/entries/icons/original/000/000/554/facepalm.jpg?1282626490" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img alt="face palm" border="0" src="http://s3.amazonaws.com/kym-assets/entries/icons/original/000/000/554/facepalm.jpg?1282626490" title="2007 called, they want their meme back" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;This is the danger of testing via side-loading - I never check that the actual version on the market is what I expect. It's all too much like hard work. Fixed it now though.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-4581013198741119818?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/4581013198741119818/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2011/08/android-upload-fail.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/4581013198741119818'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/4581013198741119818'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2011/08/android-upload-fail.html' title='Android Upload Fail'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-4200308850184849590</id><published>2011-07-25T20:48:00.001+02:00</published><updated>2011-07-25T20:49:27.427+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AndroidMarket'/><category scheme='http://www.blogger.com/atom/ns#' term='Lords Of Midnight'/><category scheme='http://www.blogger.com/atom/ns#' term='Unit Tests'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><category scheme='http://www.blogger.com/atom/ns#' term='Bugs'/><title type='text'>Another War of the Solstice update</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-7UPwSLu3pTA/Ti26Dkook4I/AAAAAAAABVw/MVcQ4C616pg/s1600/htc-desire-wos.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-7UPwSLu3pTA/Ti26Dkook4I/AAAAAAAABVw/MVcQ4C616pg/s1600/htc-desire-wos.png" /&gt;&lt;/a&gt;&lt;/div&gt;Despite &lt;a href="http://quirkygba.blogspot.com/2011/06/lords-of-midnight-remake-for-android.html"&gt;my prediction&lt;/a&gt;, it actually took 2 comments to get the infamous "this game crashes my HTC Desire". The good news is that I've uploaded a new version that may fix the problem.&lt;br /&gt;&lt;br /&gt;You can read about the fixes on the Market, the biggy was a couple of buffer overflows that caused random crashes. Once again, valgrind and some carefully crafted unit tests to the rescue. The trick to embedded coding is to get the code running on a real PC :-)&lt;br /&gt;&lt;br /&gt;There's a new feature that's inspired by a pretty novel feature in the original Lords of Midnight - a screen shot record! On the original LOM, you could print out the current screen. I bet nobody actually did that though, as you needed a Speccy printer which were rarer than hens' teeth. Anyway, on this Android version pressing volume up or down at any time captures the current screen and saves it to the SD card. Then you can view the screens in your "Gallery" application.&lt;br /&gt;&lt;br /&gt;I've also been practicing and finally beat the game with a carefully planned "Ultimate Victory", defeating Doomdark by taking Ushgarak and destroying the Ice Crown in the same game! To celebrate I added in the text for this, which was never contemplated in the original game. It's probably a bit of a let down after an epic 90-day war of attrition, so don't get too excited.&lt;br /&gt;&lt;br /&gt;Next up, summer hols permitting, I'm working on "3D Space Game" to fix the crashes there too. I've got it crashing on my phone now, which is half the battle. I get the feeling I'm making some nasty assumptions about video ram because the crashes are inexplicable and "trace-less".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-4200308850184849590?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/4200308850184849590/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2011/07/another-war-of-solstice-update.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/4200308850184849590'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/4200308850184849590'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2011/07/another-war-of-solstice-update.html' title='Another War of the Solstice update'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-7UPwSLu3pTA/Ti26Dkook4I/AAAAAAAABVw/MVcQ4C616pg/s72-c/htc-desire-wos.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-7403357716903540768</id><published>2011-07-06T22:09:00.000+02:00</published><updated>2011-07-06T22:09:08.353+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Lords Of Midnight'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><category scheme='http://www.blogger.com/atom/ns#' term='Bugs'/><title type='text'>Updates to The War of the Solstice</title><content type='html'>I've uploaded a bug fix version of &lt;a href="https://market.android.com/details?id=war.of.the.solstice"&gt;The War of the Solstice&lt;/a&gt; (my remake of "The Lords of Midnight") to the Android Market. This adds a way to exit the game, both returning to the title screen and from there actually quitting the game completely so it no longer runs. There are also a bunch of bug fixes.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Fix minor Lord-under-control bug when Luxor is killed and the Moonring lost. Previously if Luxor was killed at night while you controlled another lord, you would still be able to control that lord the next day despite the loss of the moonring. This bug may actually have been in the Speccy original too, seems that way from looking at the z80 code.&lt;/li&gt;&lt;li&gt;Added fading transition between some screens - this was always in the GBA version, but I never got round to implementing it on Android&lt;/li&gt;&lt;li&gt;There was no way to just "think" before on the Android version, so I've changed touch-text-on-look-view to "think". Think is really just when you want to get a more detailed view of what is at a location without using up the location's seekable object/event. So if you're at a town, you don't rest if you just hit the text, whereas before you would use up the town's ability to let you rest if you first used "seek".&lt;/li&gt;&lt;li&gt;Fix sometimes corrupt gfx on the left side of the screen when panning left/right. This was a hangover from the GBA port, I miscalculated the offset for the screen scrolling by one block.&lt;/li&gt;&lt;li&gt;Better screen repaint for less CPU use. Now it does less work if you stay in the same place, only using CPU when it has to. It still isn't the lowest it can go, but it is much better now.&lt;/li&gt;&lt;li&gt;Fixed textual representation of all numeric values. This was a real mess up. Let's just say I wasn't careful enough with my use of C preprocessor macros and leave it at that. This meant that before instead of 10 saying "ten" it said "no". As in "Luxur has no warriors". All other numbers were a factor of 100 out. The actual values were correct though, it was just the representation that was messed up.&lt;/li&gt;&lt;li&gt;Fixed white rectangle shield bug after pause/resume. This is an Android platform thing and had been the bane of my Androidy coding existence. I'm not sure I've really fixed it 100%, but it does seem to work on my phone (so you can all come round and use that... yeah right)&lt;/li&gt;&lt;li&gt;Added Exit Game option, Back on title screen quits. Now you don't have to use an app-killer (which are pointless anyway, but whatever). Also if you get completely stuck, or are going for a Morkin win and he gets himself killed it's much easier to restart.&lt;/li&gt;&lt;/ul&gt;There's also hardware keyboard support in this version. It mimics the Spectrum setup 100%, so now all those letters and numbers on the menus make sense. I've only tested this on an emulator though, so expect it to break horribly on the real deal. For the record, as well as the aforementioned menu shortcuts here are the keyboard controls:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;Q - move forwards&lt;br /&gt;R - think&lt;br /&gt;T - choose&lt;br /&gt;E - look&lt;br /&gt;U - night&lt;br /&gt;S - save&lt;br /&gt;D - load&lt;br /&gt;1-8  - change to face direction 1:N,2:NE,3:E,4:SE,5:S,6:SW,7:W,8:NW &lt;/code&gt;&lt;/pre&gt;That is all, hope you like it. I've been playing this one quite a bit and despite knowing all there is to know about the game, I'm still crap at it! :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-7403357716903540768?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/7403357716903540768/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2011/07/updates-to-war-of-solstice.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/7403357716903540768'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/7403357716903540768'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2011/07/updates-to-war-of-solstice.html' title='Updates to The War of the Solstice'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-8041964699860637575</id><published>2011-06-27T22:22:00.007+02:00</published><updated>2011-06-27T22:22:00.192+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><category scheme='http://www.blogger.com/atom/ns#' term='Profiler'/><title type='text'>NDK Profiler Improvements</title><content type='html'>I've uploaded a new version of my &lt;a href="http://code.google.com/p/android-ndk-profiler/"&gt;Android NDK profiler&lt;/a&gt; library. The major change in this version is much better timing accuracy through the use of &lt;a href="http://en.wikipedia.org/wiki/Ptrace"&gt;ptrace&lt;/a&gt;. This &lt;a href="http://groups.google.com/group/android-ndk/msg/bd44fee7cf400c97"&gt;requires Android 2.3 aka Gingerbread to work properly&lt;/a&gt;, so if like me you're sporting Froyo it's time to upgrade (&lt;a href="http://twitter.com/richq/status/82123117610283008"&gt;if you can&lt;/a&gt;...)&lt;br /&gt;&lt;br /&gt;If you do use Froyo or earlier then you will get timing information, but it will not be precise. In particular it will give too much time to functions called from other functions, time that is not attributed to the calling function. The actual call counts are still accurate, and it can still give you an idea of bottlenecks.&lt;br /&gt;&lt;br /&gt;I've also added a new minimal example that is included in the source release. It's a silly example with 3 buttons and is pretty fragile, but should give you an idea of what you need to do to add profiling. There's also a new snippet of Make code that you can include to avoid copy-pasting all those &lt;code&gt;TARGET_thumb_release_CFLAGS&lt;/code&gt; lines.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-8041964699860637575?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/8041964699860637575/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2011/06/ndk-profiler-improvements.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/8041964699860637575'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/8041964699860637575'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2011/06/ndk-profiler-improvements.html' title='NDK Profiler Improvements'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-2696642242681976952</id><published>2011-06-26T18:56:00.000+02:00</published><updated>2011-06-26T18:56:03.573+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AndroidMarket'/><category scheme='http://www.blogger.com/atom/ns#' term='Game Boy Advance'/><category scheme='http://www.blogger.com/atom/ns#' term='Lords Of Midnight'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><title type='text'>The Lords of Midnight remake for Android</title><content type='html'>I've released another Android game, this time &lt;a href="https://market.android.com/details?id=war.of.the.solstice"&gt;The Lords of Midnight gets the remake treatment&lt;/a&gt;. Once more it's a port from a Nintendo platform, this time the GBA as I never got round to updating it for the DS. It's so close to the Spectrum original that you can almost smell the rubber keyboard. Check out that colour clash.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-5wghXS3-8E8/Tgdje1-_CiI/AAAAAAAABU8/cocaLEmBXpc/s1600/shadows.png" imageanchor="1"&gt;&lt;img border="0" height="213" src="http://4.bp.blogspot.com/-5wghXS3-8E8/Tgdje1-_CiI/AAAAAAAABU8/cocaLEmBXpc/s320/shadows.png" width="320" /&gt;&lt;/a&gt;&lt;a href="http://3.bp.blogspot.com/-uXiOzrqHZVI/TgdjhvysE8I/AAAAAAAABVA/BJmXo0BeTLc/s1600/classic.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="213" src="http://3.bp.blogspot.com/-uXiOzrqHZVI/TgdjhvysE8I/AAAAAAAABVA/BJmXo0BeTLc/s320/classic.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;I've called the remake "&lt;a href="https://market.android.com/details?id=war.of.the.solstice"&gt;The War of the Solstice&lt;/a&gt;", as it looks like &lt;a href="https://secure.wikimedia.org/wikipedia/en/wiki/Mike_Singleton"&gt;Mike Singleton&lt;/a&gt; together with &lt;a href="http://www.icemark.com/"&gt;Chris Wild&lt;/a&gt; may be making an official game for iPod and possibly Android at some point. Rumours have been &lt;a href="http://www.icemark.com/blog/archives/2011/03/08/lords-of-midnight-ios/"&gt;going on for several months now&lt;/a&gt; with nothing actually released, so it may come to nothing. They are concentrating on the iPlatforms first too, so hopefully my remake will not have any impact on their sales. I can't blame them for doing iPhone first; if you were to charge people for games on Android it'd be a support nightmare. There are too many devices with too many random reasons to crash or &lt;a href="http://mikamobile.blogspot.com/2011/06/android.html"&gt;otherwise go wrong&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;That's why this is yet another freemake. Hurrah! No adverts either (I'd edit /etc/hosts to block the advert networks myself if I actually used my Android phone for anything). I bet the first comment on the Market for this is going to be "this crashes on my HTC Desire".&lt;br /&gt;&lt;br /&gt;Anyway, this remake fixes at least 1 major bug in the AI that was in my original remake (but not in the original game, oh man!), as well as adding touch controls throughout. I've learned my lesson from Elite: people want touch controls. The only exceptions here are back (for obvious back-like things) and the menu button, which is need to save the game. Everything else is fat finger friendly. &lt;a href="https://market.android.com/details?id=war.of.the.solstice"&gt;Go get it&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-2696642242681976952?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/2696642242681976952/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2011/06/lords-of-midnight-remake-for-android.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/2696642242681976952'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/2696642242681976952'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2011/06/lords-of-midnight-remake-for-android.html' title='The Lords of Midnight remake for Android'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-5wghXS3-8E8/Tgdje1-_CiI/AAAAAAAABU8/cocaLEmBXpc/s72-c/shadows.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-3600870366453674216</id><published>2011-06-13T00:05:00.000+02:00</published><updated>2011-06-13T00:05:44.671+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DS'/><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Game Boy Advance'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><category scheme='http://www.blogger.com/atom/ns#' term='Elite'/><title type='text'>3D Space Game Source Code Release</title><content type='html'>I've received a few emails recently asking about the source code for the &lt;i&gt;ahem&lt;/i&gt; Elite port that's in the &lt;a href="https://market.android.com/details?id=elite.app"&gt;Android Market&lt;/a&gt;. The TL;DR summary: the source is &lt;a href="http://code.google.com/p/ds-elite/"&gt;now available&lt;/a&gt; and it includes updates to the &lt;a href="http://code.google.com/p/ds-elite/downloads/detail?name=eliteagb-ds-1.4.zip"&gt;DS&lt;/a&gt; and &lt;a href="http://code.google.com/p/ds-elite/downloads/detail?name=eliteagb-gba-1.4.zip"&gt;GBA&lt;/a&gt; versions with all core bug fixes that have gone into the Android version too.&lt;br /&gt;&lt;br /&gt;The game began life on the Game Boy Advance and the source was always available in tar-ball form from my now-defunct Geocities remakes site (later moved to a &lt;a href="http://sites.google.com/site/gbaremakes/home"&gt;new home&lt;/a&gt;). From there I ported the same code to the DS, though I didn't really make the most of the platform. There was no touch input and no use of the 2nd screen at all. The source was in a svn repository now though, on &lt;a href="http://code.google.com/p/ds-elite/"&gt;Google Code&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;When I ported to the DS I did it the wrong way really: I ripped out the GBA parts and added in the DS bits instead. This meant that the Android port had to at least rip out the DS bits. I knew I didn't want to abandon the DS and GBA just yet, so as well as taking out the platform-specific code in the core part of the game, I added in hooks that each platform would have to implement in its own way. At first I only did the Android, Linux/SDL and DS parts of these hooks, but in the end I've re-done the GBA part too.&lt;br /&gt;&lt;br /&gt;There's not a lot of documentation on building the source yet, I'll update that later this week &lt;i&gt;if I get time&lt;/i&gt;. If you're interested in compiling all this, you'll need the Android development kits as well as devkitARM. The devkitARM dependency is for grit, so if you get that some other way and don't want to build the DS/GBA versions then you can do that too. Run "scons --help-variables" from the top level directory to see what things you can alter about the build. Or you can just &lt;a href="http://code.google.com/p/ds-elite/source/browse/#svn%2Ftrunk"&gt;browse the source code&lt;/a&gt; and marvel at the hideousness of it all.&lt;br /&gt;&lt;br /&gt;As I've pretty much moved on from DS and GBA coding these versions are probably not as well tested as they ought to be. Let me know of any problems you encounter and I'll see what I can do. Patches are welcome :-) Also: saves are, sadly, not backwards compatible with previous releases. This is due to the addition of a new flag that stores the type of game - "Classic" or "Elite-A" mode. Elite-A is also know as "difficultly turned up to 11 mode".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-3600870366453674216?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/3600870366453674216/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2011/06/3d-space-game-source-code-release.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/3600870366453674216'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/3600870366453674216'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2011/06/3d-space-game-source-code-release.html' title='3D Space Game Source Code Release'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-4856434556710621032</id><published>2011-05-22T22:55:00.000+02:00</published><updated>2011-05-22T22:55:13.350+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ARM'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><category scheme='http://www.blogger.com/atom/ns#' term='Profiler'/><title type='text'>Bug Fixes in Android NDK Profiler</title><content type='html'>One of the biggest outstanding bugs in my &lt;a href="https://code.google.com/p/android-ndk-profiler"&gt;Android NDK profiler&lt;/a&gt; library was that it would produce the gmon.out file but when you ran it through gprof you would see "no accumulate time" and the timing information was nowhere to be found. Now you can thank Justin Wick for debugging the root cause of the problem and providing a fix.&lt;br /&gt;&lt;br /&gt;The library size I was using was too small to trigger the problem. It turned out that on larger libraries the calculation that inserted the addresses into the hystogram buckets had an overflow bug that caused the information to be lost. This was a left over from using the profiling code from Visual Boy Advance, since on the GBA the address space tends to be much smaller especially as it doesn't use &lt;a href="http://en.wikipedia.org/wiki/Address_space_layout_randomization"&gt;random address layouts&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;I tested this out using the Android port of &lt;a href="https://code.google.com/p/freeciv-android/"&gt;FreeCiv&lt;/a&gt;, which prior to the change didn't show timing information, and with the change it now shows the times for each call. Once again, thanks to Justin for debugging the problem and figuring this out.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;Using armeabi-v7a&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The other problem you may have seen mentioned in the comments was with armeabi-v7a. In theory you can combine armeabi and armeabi-v7a together and things just work. Sadly I've had reports that doing this causes code compiled as armeabi-v7a to crash.&lt;br /&gt;&lt;br /&gt;I finally got round to looking at what gcc spits out when you use the &lt;code&gt;APP_ABI&lt;/code&gt; variable and set it to &lt;code&gt;armeabi-v7a&lt;/code&gt;. There was a slight surprise in store for me that would explain the crashes. In a nutshell, when I said in my &lt;a href="http://quirkygba.blogspot.com/2011/03/profiling-android-ndk-code.html"&gt;original post&lt;/a&gt; that I had to save &lt;i&gt;all&lt;/i&gt; the registers in the profiling glue code, I had made an assumption that the link register (lr) did not have to be saved. With Thumb2 it looks like I do have to save that one as well, since gcc forgets that calling &lt;code&gt;__gnu_mcount_nc&lt;/code&gt; (the profiling glue) is a function call that wrecks lr.&lt;br /&gt;&lt;br /&gt;Look at this bit of C code:&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-color: black; color: white; font-weight: bold;"&gt;&lt;span style="font-family: monospace;"&gt;&lt;span style="color: lime;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt;&amp;nbsp;foo(&lt;span style="color: lime;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt;&amp;nbsp;x)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: yellow;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt;&amp;nbsp;x * &lt;span style="color: #ff40ff;"&gt;&lt;b&gt;3&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;When I compile it with &lt;code&gt;-Os -mthumb --save-temps&lt;/code&gt; it gives the following:&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-color: black; color: white; font-weight: bold;"&gt;&lt;span style="font-family: monospace;"&gt;&lt;span style="color: yellow;"&gt;&lt;b&gt;foo&lt;/b&gt;&lt;/span&gt;:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: yellow;"&gt;&lt;b&gt;lsl&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: lime;"&gt;&lt;b&gt;r3&lt;/b&gt;&lt;/span&gt;, &lt;span style="color: lime;"&gt;&lt;b&gt;r0&lt;/b&gt;&lt;/span&gt;, #&lt;span style="color: #ff40ff;"&gt;&lt;b&gt;1&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: yellow;"&gt;&lt;b&gt;add&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: lime;"&gt;&lt;b&gt;r0&lt;/b&gt;&lt;/span&gt;, &lt;span style="color: lime;"&gt;&lt;b&gt;r3&lt;/b&gt;&lt;/span&gt;, &lt;span style="color: lime;"&gt;&lt;b&gt;r0&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: yellow;"&gt;&lt;b&gt;bx&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: lime;"&gt;&lt;b&gt;lr&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Now if I add in &lt;code&gt;-pg&lt;/code&gt; to get the profiling calls I get this:&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-color: black; color: white; font-weight: bold;"&gt;&lt;span style="font-family: monospace;"&gt;&lt;span style="color: yellow;"&gt;&lt;b&gt;foo&lt;/b&gt;&lt;/span&gt;:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: yellow;"&gt;&lt;b&gt;push&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;span style="color: lime;"&gt;&lt;b&gt;r4&lt;/b&gt;&lt;/span&gt;, &lt;span style="color: lime;"&gt;&lt;b&gt;lr&lt;/b&gt;&lt;/span&gt;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: yellow;"&gt;&lt;b&gt;push&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;span style="color: lime;"&gt;&lt;b&gt;lr&lt;/b&gt;&lt;/span&gt;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: yellow;"&gt;&lt;b&gt;bl&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: cyan;"&gt;&lt;b&gt;__gnu_mcount_nc&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: yellow;"&gt;&lt;b&gt;lsl&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: lime;"&gt;&lt;b&gt;r3&lt;/b&gt;&lt;/span&gt;, &lt;span style="color: lime;"&gt;&lt;b&gt;r0&lt;/b&gt;&lt;/span&gt;, #&lt;span style="color: #ff40ff;"&gt;&lt;b&gt;1&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: yellow;"&gt;&lt;b&gt;add&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: lime;"&gt;&lt;b&gt;r0&lt;/b&gt;&lt;/span&gt;, &lt;span style="color: lime;"&gt;&lt;b&gt;r3&lt;/b&gt;&lt;/span&gt;, &lt;span style="color: lime;"&gt;&lt;b&gt;r0&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: yellow;"&gt;&lt;b&gt;pop&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;span style="color: lime;"&gt;&lt;b&gt;r4&lt;/b&gt;&lt;/span&gt;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: yellow;"&gt;&lt;b&gt;pop&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;span style="color: lime;"&gt;&lt;b&gt;r1&lt;/b&gt;&lt;/span&gt;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: yellow;"&gt;&lt;b&gt;bx&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: lime;"&gt;&lt;b&gt;r1&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;You can see it pushes lr twice - once for the use in the actual function, and a second time for &lt;code&gt;__gnu_mcount_nc&lt;/code&gt; to do what it likes with it. Now if I compile for thumb2 using &lt;code&gt;-march=armv7-a -mthumb&lt;/code&gt; I get this:&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-color: black; color: white; font-weight: bold;"&gt;&lt;span style="font-family: monospace;"&gt;&lt;span style="color: yellow;"&gt;&lt;b&gt;foo&lt;/b&gt;&lt;/span&gt;:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: cyan;"&gt;&lt;b&gt;@ link register save eliminated.&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: yellow;"&gt;&lt;b&gt;push&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;span style="color: lime;"&gt;&lt;b&gt;lr&lt;/b&gt;&lt;/span&gt;}&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: yellow;"&gt;&lt;b&gt;bl&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: cyan;"&gt;&lt;b&gt;__gnu_mcount_nc&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: yellow;"&gt;&lt;b&gt;movs&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: lime;"&gt;&lt;b&gt;r3&lt;/b&gt;&lt;/span&gt;, #&lt;span style="color: #ff40ff;"&gt;&lt;b&gt;3&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: yellow;"&gt;&lt;b&gt;mul&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color: lime;"&gt;&lt;b&gt;r0&lt;/b&gt;&lt;/span&gt;, &lt;span style="color: lime;"&gt;&lt;b&gt;r3&lt;/b&gt;&lt;/span&gt;, &lt;span style="color: lime;"&gt;&lt;b&gt;r0&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: yellow;"&gt;&lt;b&gt;bx&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: lime;"&gt;&lt;b&gt;lr&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;That comment is quite interesting. If you squint a bit it almost looks like a subtle compiler bug, since when you add profiling it should consider the call to __gnu_mcount_nc just like another function call and save lr. But as I haven't been able to test this on a real device yet, I'm not 100% sure that it's the only problem with using armeabi-v7a in combination with the profiling library. Plus once I saw what was going on I've been able to work around it anyway. If you get the chance to try this out, and are using armeabi-v7a let me know how the &lt;a href="https://code.google.com/p/android-ndk-profiler/downloads/list"&gt;latest release&lt;/a&gt; works out for you.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-4856434556710621032?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/4856434556710621032/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2011/05/bug-fixes-in-android-ndk-profiler.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/4856434556710621032'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/4856434556710621032'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2011/05/bug-fixes-in-android-ndk-profiler.html' title='Bug Fixes in Android NDK Profiler'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-7340017293537047373</id><published>2011-05-20T18:30:00.000+02:00</published><updated>2011-05-20T18:30:30.059+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AndroidMarket'/><category scheme='http://www.blogger.com/atom/ns#' term='Chaos'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><category scheme='http://www.blogger.com/atom/ns#' term='Elite'/><category scheme='http://www.blogger.com/atom/ns#' term='Bugs'/><title type='text'>Black screen of death on HTC Desire</title><content type='html'>It seems that my &lt;a href="https://market.android.com/details?id=elite.app"&gt;version of Elite&lt;/a&gt; on Android is not behaving very well on the HTC Desire. The comments speak for themselves:&lt;br /&gt;&lt;blockquote&gt;Black screen on start up, freezes phone, have to remove battery on HTC desire. I loved this game back in the day too.&lt;br /&gt;&lt;b&gt;by starbuck (May 20, 2011)&lt;/b&gt; &lt;/blockquote&gt;&lt;blockquote&gt;Don't download this app, this app has crashed my f*cking htc desire&lt;br /&gt;&lt;b&gt;by Marco (May 19, 2011)&lt;/b&gt; &lt;/blockquote&gt;&lt;blockquote&gt;I am giving it a 4 , but it has crashed a few times and clearer instructions would help. Desire hd&lt;br /&gt;&lt;b&gt;by Thomas (May 7, 2011)&lt;/b&gt; &lt;/blockquote&gt;&lt;blockquote&gt;Intro music played but black screen and phone locked. Had to remove battery. Desire&lt;br /&gt;&lt;b&gt;by Robert (May 6, 2011)&lt;/b&gt; &lt;/blockquote&gt;&lt;blockquote&gt;Black screen lock-up on starting. Had to remove battery to recover. Not good. Desire.&lt;br /&gt;&lt;b&gt;by Grampian (April 26, 2011)&lt;/b&gt;&lt;/blockquote&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-w9HxX-7b-D4/TdaUe4Z_saI/AAAAAAAABU4/pU6m6_rYles/s1600/one-star-troll.png" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-w9HxX-7b-D4/TdaUe4Z_saI/AAAAAAAABU4/pU6m6_rYles/s1600/one-star-troll.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;If there are any HTC Desire owners who want to help fix this problem then please get in touch. I'm obviously doing something wrong, but the platform shouldn't crash to such an extent that you have to take the battery out! Especially when the game does run on some HTC Desires as well as on many other types of phone.&lt;br /&gt;&lt;br /&gt;I don't know which is more frustrating: the crashes themselves or the attitude of the people leaving these drive-by 1 star reviews. Writing such a comment may make them feel better (hey! my free stuff doesn't work!) but in the long term it doesn't help anybody.&lt;br /&gt;&lt;br /&gt;So if you have a Desire and are experiencing crashes, please, please try and send me a "logcat" of the crash so I can work out what's going on and fix it. There's an application in the Market called &lt;a href="https://market.android.com/details?id=org.jtb.alogcat"&gt;aLogcat&lt;/a&gt; that lets you capture the log and email it out. Check that no personal information is in there (there shouldn't be any) and send me the info if you can. Otherwise there is &lt;i&gt;nothing&lt;/i&gt; I can do, short of blacklisting Desires.&lt;br /&gt;&lt;br /&gt;On a happier note: A new version of &lt;a href="https://market.android.com/details?id=chaos.app"&gt;Chaos&lt;/a&gt; is out that fixes all the bugs that were reported, except one. The &lt;a href="https://sites.google.com/site/chaosbattleofwizards/download"&gt;Nintendo DS and GBA&lt;/a&gt; versions are based on this same code. Fixes on all platforms are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Make sound fx volume more consistent&lt;/li&gt;&lt;li&gt;Fix dismount wizard bug&lt;/li&gt;&lt;li&gt;Speed up magic bolt&lt;/li&gt;&lt;li&gt;Add a message when Meditate's side effect kicks in (it freezes the wizard)&lt;/li&gt;&lt;/ul&gt;The one bug that I can't reproduce is (surprise) Android only, and seems like another "Android hates me" oddity:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;black screen after pause/resume&lt;/li&gt;&lt;/ul&gt;I've made a change that may help, but who can tell. Interestingly, a lot of commercial games seem to just kill the activity when you move away from it instead of dealing with this issue.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-7340017293537047373?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/7340017293537047373/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2011/05/black-screen-of-death-on-htc-desire.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/7340017293537047373'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/7340017293537047373'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2011/05/black-screen-of-death-on-htc-desire.html' title='Black screen of death on HTC Desire'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-w9HxX-7b-D4/TdaUe4Z_saI/AAAAAAAABU4/pU6m6_rYles/s72-c/one-star-troll.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-6460748187678956105</id><published>2011-04-30T20:29:00.000+02:00</published><updated>2011-04-30T20:29:15.957+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><category scheme='http://www.blogger.com/atom/ns#' term='Profiler'/><category scheme='http://www.blogger.com/atom/ns#' term='HOWTO'/><category scheme='http://www.blogger.com/atom/ns#' term='Google Code'/><title type='text'>Android NDK Profiler Example</title><content type='html'>I've added an example to the &lt;a href="http://code.google.com/p/android-ndk-profiler/"&gt;android-ndk-profiler project&lt;/a&gt; based on the native-activity from Google's Android SDK. As Google Code doesn't let you mix'n'match licences, and importing a bunch of random code into my SVN seemed a bit crap, I've not included the original source in the repository.&lt;br /&gt;&lt;br /&gt;What I have done is supply a patch and a script to copy the code from your NDK installation, patch it up to use profiling, update the build scripts and then build the example. You'll need to have the "patch" program installed to get this working, or apply the changes manually.&lt;br /&gt;&lt;br /&gt;Since this is Android 2.3 only, I've only been able to test it on the emulator. Also the emulator doesn't like armeabi-v7a, so that remains completely untested - I'd stick to using &lt;code&gt;APP_ABI := armeabi&lt;/code&gt; for profiling for now.&lt;br /&gt;&lt;br /&gt;Hopefully this'll clear up any misunderstandings like those mentioned in the comments on the &lt;a href="http://quirkygba.blogspot.com/2011/03/profiling-android-ndk-code.html"&gt;last post I made on the subject&lt;/a&gt;. Full details are on this &lt;a href="http://code.google.com/p/android-ndk-profiler/wiki/Example"&gt;wiki page&lt;/a&gt; about getting the example working.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-6460748187678956105?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/6460748187678956105/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2011/04/android-ndk-profiler-example.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/6460748187678956105'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/6460748187678956105'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2011/04/android-ndk-profiler-example.html' title='Android NDK Profiler Example'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-8359398118844380810</id><published>2011-04-09T18:11:00.000+02:00</published><updated>2011-04-09T18:11:38.191+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><category scheme='http://www.blogger.com/atom/ns#' term='Elite'/><title type='text'>Why are my textures not showing up on Android?</title><content type='html'>What a disaster the initial week of "&lt;a href="https://market.android.com/details?id=elite.app"&gt;3D Space Game&lt;/a&gt;" has been! I recieved lots of 1 star reviews with vague hints about what the problem was - "doesn't work", "goofed up". When I realised there was a problem and added a note on the market asking people to email their problems before "down voting" I got a couple of very helpful bug reports.&lt;br /&gt;&lt;br /&gt;It turns out that on the Galaxy S and other larger-screened devices all of the textures I created from PNG images were not showing up. This meant that the control buttons and menu icons just show as white rectangles, completely unusable.&lt;br /&gt;&lt;br /&gt;The usual reason for the white rectangle effect is that the size of the texture you're trying to use is not a power of 2. Textures have to be 32x32, 64x32, 128x512, etc - you can't have a 257x123 sized texture (unless it's on the Android emulator, which doesn't care about texture size). I even mentioned this in my "&lt;a href="http://quirkygba.blogspot.com/2011/01/lessons-learned-with-android.html"&gt;lessons learned&lt;/a&gt;" post in January. The code I use creates a texture straight from the PNG like this:&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-color: black; color: white; font-weight: bold;"&gt;&lt;span style="font-family: monospace;"&gt;Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.my_image);&lt;br /&gt;GLUtils.texImage2D(GL10.GL_TEXTURE_2D, &lt;span style="color: #ff40ff;"&gt;&lt;b&gt;0&lt;/b&gt;&lt;/span&gt;, bmp, &lt;span style="color: #ff40ff;"&gt;&lt;b&gt;0&lt;/b&gt;&lt;/span&gt;);&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;The size of the texture is taken from the PNG, which I had carefully made sure was a power of 2. On my HTC Magic the textures show up fine, so I thought everything was working correctly.&lt;br /&gt;&lt;br /&gt;Well, it turns out that the BitmapFactory uses a default set of options that includes a "resize" flag. The flag is by default set to true, or "resize the image to screw up Open GL textures", as it should be known. The fix for this was to create my own set of Options and set the flag to false like this:&lt;br /&gt;&lt;br /&gt;&lt;pre style="background-color: black; color: white; font-weight: bold;"&gt;&lt;span style="font-family: monospace;"&gt;BitmapFactory.Options opts = &lt;span style="color: yellow;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt;&amp;nbsp;BitmapFactory.Options();&lt;br /&gt;opts.inScaled = &lt;span style="color: #ff40ff;"&gt;&lt;b&gt;false&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;Bitmap bmp = BitmapFactory.decodeResource(getResources(),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;R.drawable.my_image, opts); &lt;span style="color: cyan;"&gt;&lt;b&gt;/* pass in opts */&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;GLUtils.texImage2D(GL10.GL_TEXTURE_2D, &lt;span style="color: #ff40ff;"&gt;&lt;b&gt;0&lt;/b&gt;&lt;/span&gt;, bmp, &lt;span style="color: #ff40ff;"&gt;&lt;b&gt;0&lt;/b&gt;&lt;/span&gt;);&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Problem solved. Let's hope for a reversal of the 1-star trend, eh readers?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-8359398118844380810?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/8359398118844380810/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2011/04/why-are-my-textures-not-showing-up-on.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/8359398118844380810'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/8359398118844380810'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2011/04/why-are-my-textures-not-showing-up-on.html' title='Why are my textures not showing up on Android?'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-4232464328392960141</id><published>2011-04-02T11:39:00.001+02:00</published><updated>2011-04-30T20:30:47.687+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AndroidMarket'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><category scheme='http://www.blogger.com/atom/ns#' term='Elite'/><title type='text'>3D Space Game for Android</title><content type='html'>This is pretty much "&lt;a href="https://market.android.com/details?id=elite.app"&gt;Elite for Android&lt;/a&gt;". It's a port of a port of a remake of a fan-tweaked version of Elite. I first wrote this as a remake of Angus Duggans's Elite A for the GBA (Elite A being a tweaked version of the original Elite on the BBC Micro), ported that to the DS and now here it is on Android. It's not been without problems due to a severe lack of buttons on a phone. This version adds in "classic mode" to play the game without the Elite A modifications.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-B69u7SxycPY/TZbt66XicvI/AAAAAAAABU0/R2OgSk3WHtQ/s1600/elite-splash.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-B69u7SxycPY/TZbt66XicvI/AAAAAAAABU0/R2OgSk3WHtQ/s1600/elite-splash.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-JeJktq6thAo/TZbt3nFmLEI/AAAAAAAABUw/_taE1xGOvRY/s1600/elite-vector.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-JeJktq6thAo/TZbt3nFmLEI/AAAAAAAABUw/_taE1xGOvRY/s1600/elite-vector.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;I started the Android port back in October 2010 and it was more or less complete by December 2010. I've spent the months since then squashing bugs and refining the controls. Hopefully it will work on a lot of devices - I've been testing on 2009 vintage hardware - but there's no way to know for sure. Try it and let me know. In particular Samsung really threw a spanner in the works by not supplying a d-pad or trackball on the Galaxy S.&lt;br /&gt;&lt;br /&gt;There are still some known problems in this first release:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Yellow line under title is not always shown&lt;/li&gt;&lt;li&gt;Sprite text still shown on panels&lt;/li&gt;&lt;li&gt;Long press should show route to planet (bit flakey, ditto Galactic Hyperspace)&lt;/li&gt;&lt;li&gt;Text occasionally does not update&lt;/li&gt;&lt;/ul&gt;Most of these are due to the GBA/DS heritage, but none are show stoppers. I'll be updating with fixes as people complain :-) Also, the Nintendo DS and GBA "backports" of this code are not ready, so this is Android-only for now. There are still some outstanding problems that I need to fix on the DS, and the GBA code is further off, but I'm starting to get project fatigue here and need a change.&lt;br /&gt;&lt;br /&gt;This video shows the gameplay, it's a little choppy - if anyone knows a good way to video off an Android device I'd love to know. I used &lt;a href="http://blog.ribomation.com/2010/01/droidscreen/"&gt;droid@screen&lt;/a&gt; for this, which seems to be the best option out there, but it doesn't record video. I had to record the X11 window separately using xvidcap and this made things slightly worse. Anyway, on with the show:&lt;br /&gt;&lt;br /&gt;&lt;iframe allowfullscreen="" frameborder="0" height="390" src="http://www.youtube.com/embed/89UJkOhqurA" title="YouTube video player" width="480"&gt;&lt;/iframe&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-4232464328392960141?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/4232464328392960141/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2011/04/3d-space-game-for-android.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/4232464328392960141'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/4232464328392960141'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2011/04/3d-space-game-for-android.html' title='3D Space Game for Android'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-B69u7SxycPY/TZbt66XicvI/AAAAAAAABU0/R2OgSk3WHtQ/s72-c/elite-splash.png' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-521501662170664527</id><published>2011-03-27T01:27:00.001+01:00</published><updated>2011-04-30T20:30:09.149+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><category scheme='http://www.blogger.com/atom/ns#' term='Profiler'/><category scheme='http://www.blogger.com/atom/ns#' term='HOWTO'/><category scheme='http://www.blogger.com/atom/ns#' term='Google Code'/><title type='text'>Profiling Android NDK Code</title><content type='html'>Profiling code on embedded systems is tricky. The Google tools for profiling Android applications only &lt;a href="http://developer.android.com/guide/developing/debugging/debugging-tracing.html"&gt;cover Java code&lt;/a&gt;, not native C code. So I've created a &lt;a href="http://code.google.com/p/android-ndk-profiler/"&gt;new project on Google Code for profiling Android NDK shared libraries&lt;/a&gt;. I had the idea when reading &lt;a href="http://forum.gbadev.org/viewtopic.php?t=17497"&gt;this post&lt;/a&gt; on the GBAdev.org forum - there coder "sverx" asked how to profile code, and I remembered Visual Boy Advance did it pretty well on the GBA, but there was no way to do so on the DS - nor on Android. Well, the Android situation just improved :-)&lt;br /&gt;&lt;br /&gt;I read the VBA source, lifted the relevant chunks of gprof-inspired code, hacked in some timing information, and added a touch of assembly to tie together what &lt;code&gt;gcc -pg&lt;/code&gt; does and what the profile-creating code does. If you look at a chunk of the output from gcc with &lt;code&gt;-pg&lt;/code&gt;, it looks like this:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;&amp;nbsp;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;0001184c &amp;lt;do_raisedead_cast&amp;gt;:&lt;br /&gt;   1184c:   b5f8        push    {r3, r4, r5, r6, r7, lr}&lt;br /&gt;   1184e:   b500        push    {lr}&lt;br /&gt;   11850:   f004 f830   bl  158b4 &amp;lt;__gnu_mcount_nc&amp;gt;&lt;br /&gt;   ...&lt;br /&gt;   1189c:   3a01        subs    r2, #1&lt;br /&gt;   1189e:   701a        strb    r2, [r3, #0]&lt;br /&gt;   118a0:   bdf8        pop {r3, r4, r5, r6, r7, pc}&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;So the compiler pushes the link register (lr) and the &lt;code&gt;__gnu_mcount_nc&lt;/code&gt; function has to pop it off the stack. This isn't a normal calling convention - usually each function uses the stack symmetrically, pushing and popping the same number of times. Also I learned that the mcount function must preserve &lt;i&gt;all&lt;/i&gt; the registers. You can't smush a single one or Bad Things happen (I've seen a lot of weird crashes lately, I can tell you). This little conundrum took me quite some time to figure out. It can probably be done better, but the implementation I came up with was this:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;&amp;nbsp;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;        push {r0-r3}&lt;br /&gt;        push {lr}&lt;br /&gt;        ldr r0, [sp, #20]  @ r0 = lr pushed by calling routine&lt;br /&gt;        mov r1, lr    @ address of calling routine&lt;br /&gt;        bl profCount&lt;br /&gt;        pop {r0}&lt;br /&gt;        mov lr, r0&lt;br /&gt;        pop {r0-r3}&lt;br /&gt;        @ pop previous address&lt;br /&gt;        add sp, #4&lt;br /&gt;        bx lr&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Since registers r4+ must be preserved by the called function, I can ignore those when the code calls out to &lt;code&gt;profCount&lt;/code&gt;. Keeping r0-r3 clean was the problem, as usually these are "scratch" registers and you're free to mess them up. The function &lt;code&gt;profCount&lt;/code&gt; takes the C function-just-called and its caller addresses as arguments for use in generating the profile. Anyway, the results are pretty good for the code I've tested it on - you get the usual call counts and timing information that gprof provides. Here's a bit of the information from Chaos...&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;&amp;nbsp;&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;Flat profile:&lt;br /&gt;&lt;br /&gt;Each sample counts as 0.01 seconds.&lt;br /&gt;  %   cumulative   self              self     total           &lt;br /&gt; time   seconds   seconds    calls  ms/call  ms/call  name    &lt;br /&gt; 65.31      0.32     0.32      288     1.11     1.11  android_render_screen&lt;br /&gt; 18.37      0.41     0.09      450     0.20     0.20  clear_square&lt;br /&gt;  4.08      0.43     0.02        3     6.67     6.67  clear_bg&lt;br /&gt;  2.04      0.44     0.01       25     0.40     0.40  print_text16&lt;br /&gt;  2.04      0.45     0.01        3     3.33     3.33  draw_decor_border_internal&lt;br /&gt;  2.04      0.46     0.01        2     5.00    33.00  splash_touch&lt;br /&gt;  2.04      0.47     0.01        1    10.00    52.00  options_back&lt;br /&gt;  2.04      0.48     0.01        1    10.00    54.80  show_options&lt;br /&gt;  2.04      0.49     0.01                             chaos_start&lt;br /&gt;  0.00      0.49     0.00   442368     0.00     0.00  draw_8x8_tile&lt;br /&gt;  0.00      0.49     0.00    28800     0.00     0.00  platform_set_tile_entry&lt;br /&gt;  0.00      0.49     0.00     3646     0.00     0.00  platform_set_text_map_entry&lt;br /&gt;  0.00      0.49     0.00     2671     0.00     0.00  platform_key_pressed&lt;br /&gt;  0.00      0.49     0.00     1186     0.00     0.00  platform_set_palette_entry&lt;br /&gt;&lt;br /&gt;index % time    self  children    called     name&lt;br /&gt;                0.32    0.00     288/288         chaos_gl_render [2]&lt;br /&gt;[1]     65.3    0.32    0.00     288         android_render_screen [1]&lt;br /&gt;                0.00    0.00  442368/442368      draw_8x8_tile [22]&lt;br /&gt;                0.00    0.00     286/286         InterruptProcess [30]&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Functions with no "calls", "self" or "total" are because they got called via JNI. The "draw_8x8_tile" call count there is accurate - it is called for each 8x8 tile on the screen in each frame. There are 32 x 24 tiles, and 2 layers of tiles. &lt;code&gt;32 * 24 * 2 * 288 = 442368&lt;/code&gt;, as expected. And the android_render_screen count is correct, since at 30 fps that is around 9 seconds of use and I only ran the game for a few seconds to check.&lt;br /&gt;&lt;br /&gt;More details on the &lt;a href="http://code.google.com/p/android-ndk-profiler/"&gt;android-ndk-profiler&lt;/a&gt; page, including a &lt;a href="http://code.google.com/p/android-ndk-profiler/wiki/Usage"&gt;guide on how to use the library&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-521501662170664527?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/521501662170664527/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2011/03/profiling-android-ndk-code.html#comment-form' title='36 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/521501662170664527'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/521501662170664527'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2011/03/profiling-android-ndk-code.html' title='Profiling Android NDK Code'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>36</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-616494411295208437</id><published>2011-02-13T17:55:00.000+01:00</published><updated>2011-10-03T20:35:00.653+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Git'/><category scheme='http://www.blogger.com/atom/ns#' term='HOWTO'/><category scheme='http://www.blogger.com/atom/ns#' term='Mercurial'/><title type='text'>How to use Bitbucket's free private Mercurial repositories with Git</title><content type='html'>&lt;b&gt;Update: &lt;/b&gt;Since I wrote this post, &lt;a href="http://blog.bitbucket.org/2011/10/03/bitbucket-now-rocks-git/"&gt;bitbucket has added native Git support&lt;/a&gt;. Are you &lt;a href="http://quirkygba.blogspot.com/2007/10/using-git-with-google-code-hosting.html"&gt;spotting a pattern&lt;/a&gt; here? Anyway, I'll leave the rest of the post here for the historians.&lt;br /&gt;&lt;br /&gt;When Atlassian bought &lt;a href="https://bitbucket.org/"&gt;bitbucket&lt;/a&gt; in September 2010 one of the first things they did was to allow single users an unlimited amount of private repositories for free. If you want to create an backup of your own code without making the source available this seems like a difficult offer to beat. I've been using it for some months to do exactly this.&lt;br /&gt;&amp;nbsp; &lt;br /&gt;The only problem is that bitbucket uses Mercurial, what if you prefer git as your day to day version control? &lt;a href="http://en.wikipedia.org/wiki/No_worries"&gt;No worries&lt;/a&gt; as the Atlassians might say, you can bridge from Git to Mercurial using hg-git and a bit of fiddling. Here's what I did to set this all up, in case I forget later.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-CdQnVcdHFA8/TVgMCk3BMnI/AAAAAAAABTw/Be437_oBSkU/s1600/kk.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-CdQnVcdHFA8/TVgMCk3BMnI/AAAAAAAABTw/Be437_oBSkU/s1600/kk.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;I use Ubuntu 10.04 and although hg-git is in the repositories it is an older version. Instead I installed python-dulwich via &lt;code&gt;apt-get install python-dulwich&lt;/code&gt;, cloned the repository at https://bitbucket.org/durin42/hg-git and then added a suitable entry to my &lt;code&gt;~/.hgrc&lt;/code&gt; file:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;hggit = /path/to/hg-git/hggit&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;The first gotcha is that hg-git can't clone a local &lt;code&gt;file://&lt;/code&gt; repository. When you try it, you get an error like this:&lt;br /&gt;&lt;pre&gt;&lt;div&gt;&lt;br /&gt;&lt;span style="font-family: monospace;"&gt;/tmp$ hg clone file:///home/rich/projects/test&lt;br /&gt;destination directory: test&lt;br /&gt;importing Hg objects into Git&lt;br /&gt;fatal: 'file:///home/rich/projects/test' does not appear to be a git repository&lt;br /&gt;abort: the remote end hung up unexpectedly&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;/pre&gt;The workaround is to serve the repositories using the git-daemon and then clone them using the default git network protocol. I have the code I want to back-up in a directory &lt;code&gt;~/projects&lt;/code&gt;, so I start the git daemon to export all of them:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;git daemon --verbose --export-all --base-path=~/projects/ --export-all&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;That is not particularly secure, but it isn't available outside my home network and means I can clone each repository using hg with the hg-git plugin enabled:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;hg clone git://localhost/name name-hg&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Once I have a local Mercurial clone, it is easy to set up the push to bitbucket. That is just vanilla Mercurial configuration. In &lt;code&gt;name-hg/.hg/hgrc&lt;/code&gt; I added the bitbucket path so the full configuration looks like this:&lt;br /&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;[paths]&lt;br /&gt;default = git://localhost/name&lt;br /&gt;bb = http://user:password@bitbucket.org/user/project&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Now &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;project&lt;/code&gt; depend on the local name and the remote bitbucket project name, but hopefully you get the idea. I push this out to the server with &lt;code&gt;hg push bb&lt;/code&gt;. Next time I want to copy all the changes I've made in the git repository since the last backup, I fire up the git-daemon, sync up the mercurial repository then push out the changes. I have a script that does all this, which boils down to the following:&lt;br /&gt;&lt;pre&gt;&lt;div&gt;&lt;br /&gt;&lt;span style="font-family: monospace;"&gt;&lt;span style="color: #8080ff;"&gt;#!/bin/sh&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #8080ff;"&gt;# backup git repos to bitbucket private repos...&lt;/span&gt;&lt;br /&gt;&lt;span style="color: yellow;"&gt;cd&lt;/span&gt;&amp;nbsp;~/projects&lt;br /&gt;git daemon &lt;span style="color: #ff40ff;"&gt;--verbose&lt;/span&gt;&amp;nbsp;&amp;nbsp;&lt;span style="color: #ff40ff;"&gt;--export-all&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff40ff;"&gt;--base-path=~/projects/&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff40ff;"&gt;--export-all&lt;/span&gt;&amp;nbsp;&amp;amp;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: yellow;"&gt;for &lt;/span&gt;name &lt;span style="color: yellow;"&gt;in&lt;/span&gt;&amp;nbsp;project1 project2 ; &lt;span style="color: yellow;"&gt;do&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #8080ff;"&gt;# echo "did this once... not needed again"&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #8080ff;"&gt;# hg clone git://localhost/${name} ${name}-hg&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: yellow;"&gt;cd&lt;/span&gt;&amp;nbsp;~/projects/&lt;span style="color: #ff40ff;"&gt;${&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;name&lt;/span&gt;&lt;span style="color: #ff40ff;"&gt;}&lt;/span&gt;-hg &lt;span style="color: yellow;"&gt;||&lt;/span&gt;&amp;nbsp;&lt;span style="color: yellow;"&gt;exit&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff6060;"&gt;1&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hg pull &lt;span style="color: yellow;"&gt;||&lt;/span&gt;&amp;nbsp;&lt;span style="color: yellow;"&gt;exit&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff6060;"&gt;1&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hg update &lt;span style="color: yellow;"&gt;||&lt;/span&gt;&amp;nbsp;&lt;span style="color: yellow;"&gt;exit&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff6060;"&gt;1&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hg push bb &lt;span style="color: yellow;"&gt;||&lt;/span&gt;&amp;nbsp;&lt;span style="color: yellow;"&gt;exit&lt;/span&gt;&amp;nbsp;&lt;span style="color: #ff6060;"&gt;1&lt;/span&gt;&lt;br /&gt;&lt;span style="color: yellow;"&gt;done&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;/pre&gt;This way I can use git for day to day hacking, and have a secure backup on a server somewhere for if the worst happens.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-616494411295208437?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/616494411295208437/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2011/02/how-to-use-bitbuckets-free-private.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/616494411295208437'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/616494411295208437'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2011/02/how-to-use-bitbuckets-free-private.html' title='How to use Bitbucket&apos;s free private Mercurial repositories with Git'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-CdQnVcdHFA8/TVgMCk3BMnI/AAAAAAAABTw/Be437_oBSkU/s72-c/kk.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-1274323604306441748</id><published>2011-02-05T21:52:00.000+01:00</published><updated>2011-02-05T21:52:54.887+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AndroidMarket'/><category scheme='http://www.blogger.com/atom/ns#' term='Nintendo DSi'/><category scheme='http://www.blogger.com/atom/ns#' term='Game Boy Advance'/><category scheme='http://www.blogger.com/atom/ns#' term='Chaos'/><title type='text'>Chaos 1.7 and Android Market on the web</title><content type='html'>I added &lt;a href="https://market.android.com/details?id=chaos.app"&gt;Chaos 1.7 to the Android Market&lt;/a&gt; the other day. It's now passed 3000 downloads and I've had several emails and 5 star reviews from Chaos fans, so I'm pretty pleased that it's gone down that well. The only downer is that it really is for fans only, I just don't have any idea how to teach anyone brought up on modern games how to fight their way through an 8-bit world. Patience is needed, I guess.&lt;br /&gt;&lt;br /&gt;This release was the first time I'd linked to the brand new &lt;a href="https://market.android.com/"&gt;web-based Android Market&lt;/a&gt;. Until now I've always pointed to &lt;a href="https://www.appbrain.com/"&gt;Appbrain&lt;/a&gt;. I think Appbrain has been struggling to keep up with the new additions that Google have made - like bigger icons, more screenshots and promo graphics. Appbrain has also had some down time and synchronisation issues, with comments being out of date or not appearing. I'm not sure what will happen to the 'brain. They have done a great service for Android users and it would be sad to see them disappear, but their business model was the classic &lt;a href="http://www.joelonsoftware.com/items/2009/06/10c.html"&gt;snatching nickels from the path of an oncoming steamroller&lt;/a&gt;. I do hope they stick around, if only to keep Google on their toes.&lt;br /&gt;&lt;br /&gt;Anyway, back to Chaos. The changes in this release are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Remember preferences&lt;/li&gt;&lt;li&gt;Several performance improvements for better battery life&lt;/li&gt;&lt;li&gt;More consistent frame rate on newer Android devices&lt;/li&gt;&lt;li&gt;Attack sound no longer plays when sound is disabled in the options&lt;/li&gt;&lt;/ul&gt;Saving the preferences was suggested in the comments on the Market. I hadn't added it before because I didn't know how to save stuff on Android. Turns out it is really easy and doesn't even need extra permissions. Actually, I'd already learned how to save for the next game I'm doing so a nice bit of "copy paste" later and it was done. Ah, good old copy and paste. The best form of code re-use.&lt;br /&gt;&lt;br /&gt;The performance improvements included not redrawing every single square every single frame, which for some reason I was doing before. If you spot any odd graphical artefacts because of this, do let me know.&lt;br /&gt;&lt;br /&gt;The frame rate fixes were due to my &lt;a href="http://quirkygba.blogspot.com/2011/01/lessons-learned-with-android.html"&gt;recent discovery&lt;/a&gt; that newer Android devices are locked to a maximum of 30 frames-per-second. Hopefully Chaos now runs at the same speed across the board. If anyone wants to buy me a 2nd generation Android phone to check this on, please get in touch ;-)&lt;br /&gt;&lt;br /&gt;The attack sound fix was a silly non-interesting bug. I fixed it ages ago but also got a prod by email to actually release a version with the fix in place.&lt;br /&gt;&lt;br /&gt;I've updated the &lt;a href="https://sites.google.com/site/chaosbattleofwizards/download"&gt;Nintendo DS and GBA versions&lt;/a&gt; too. These don't save the preferences, and I haven't tested them on hardware so let me know if they do not work at all. Apart from that, the DS and GBA are compiled with optimizations now (somehow this got lost in the last GBA/DS release) and should go faster. The GBA version was particularly sluggish last time round.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-1274323604306441748?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/1274323604306441748/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2011/02/chaos-17-and-android-market-on-web.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/1274323604306441748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/1274323604306441748'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2011/02/chaos-17-and-android-market-on-web.html' title='Chaos 1.7 and Android Market on the web'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-8337981639703210820</id><published>2011-01-16T19:38:00.002+01:00</published><updated>2011-01-16T19:38:00.107+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><title type='text'>Lessons Learned with Android</title><content type='html'>Around the summer of 2010 I decided to switch from hacking around on the Nintendo DS to hacking around on Android.&lt;br /&gt;&lt;br /&gt;Android piqued my interest for the reaons I outlined at the time, but also because it has been changing at a breakneck pace especially if you compare it to the DS. I bought a &lt;a class="zem_slink" href="http://en.wikipedia.org/wiki/HTC_Magic" rel="wikipedia" title="HTC Magic"&gt;HTC Magic&lt;/a&gt; off of ebay to test out my code. At the time the Magic had been out for a year or so, yet it was already considered out of date! To everyone's surprise Google updated the version of Android running on the phone to the very recent Froyo 2.2.1 at the end of December 2010. Meanwhile, Nintendo only updated the firmware on the DS to block flash cartridges that allow homebrew. From a fun-filled hacking point of view Android is a more entertaining prospect.&lt;br /&gt;&lt;br /&gt;The distribution method - upload to the Market, and users are automatically notified of updates - is really great. As a user it's always nice to see applications that have been updated and to read the "recent changes" section to see what's new. As a developer, there's no need to advise people that you've released a bug fix. You just upload a new apk file, update the &lt;b&gt;recent changes&lt;/b&gt; section, and you're done.&lt;br /&gt;&lt;br /&gt;Here are notes on some of the things I've learned while coding for Android.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;The emulator is not great for games&lt;/h2&gt;&lt;br /&gt;When I wrote about my switch to Android I said "coding for Android feels like cheating. The emulator is highly accurate". I must have been viewing the new (to me) platform through rose tinted glasses there. The reality is that the emulator became useless as soon as I started using OpenGL to render Chaos. On hardware I was getting close to 60 frames per second (FPS), but on the emulator I was lucky to get above 10 FPS. This made testing on anything but hardware impossibly slow.&lt;br /&gt;&lt;br /&gt;Fortunately I had my experience with emulators from my DS days and I knew that the best way to test embedded code is to get that code running natively on desktop Linux. The majority of the time I compile and test the Linux build, only occasionally switching to Android to check things still work. All the real gameplay testing I do is on hardware though, as the feel of using a touch screen is nothing like the feel of clicking things with a mouse.&lt;br /&gt;&lt;br /&gt;There is an inaccuracy in the OpenGL emulation that could catch you out if you never tested on hardware. On the emulator you don't need to call glTexParameterf and set &lt;code&gt;GL_TEXTURE_MIN_FILTER&lt;/code&gt; and &lt;code&gt;GL_TEXTURE_MAG_FILTER&lt;/code&gt; to &lt;code&gt;GL_LINEAR&lt;/code&gt; or similar, which sets up the texture "mip maps". If you fail to do this on a real device, your textures will only show up as white polygons.&lt;br /&gt;&lt;br /&gt;I think Android should use an approach more akin to the iPhone or Windows Phone, where you compile to a native simulation of the application. Instead of emulating a full Android phone and running your app, you have the Android APIs call into native code directly. It's probably too late for Google to change this now and I have my own workarounds. Hey, at least if your game runs fast on the emulator, it will run &lt;i&gt;very&lt;/i&gt; well on the real deal :-)&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Each Android device is a precious snowflake&lt;/h2&gt;&lt;br /&gt;A game can run well on the phone you have tested with, but this doesn't guarantee anything. Soon after you put the game on the Market, you can be sure someone will post a 1-star review stating that the game doesn't run on their particular Android device. The Market dashboard for developers has a tab for "Error reports" that never shows anything, but it would be nice if it somehow gave a logcat dump of crashes and force closes.&lt;br /&gt;&lt;br /&gt;If you want people to get in touch with you instead of posting a 1-star review, you really need to explicitly state that on your game's description. Otherwise you will never get to the bottom of errors. I think the instant gratification of giving a free game 1 star trumps the hassle of getting in touch with the author. It's perfectly understandable really and something other people have noticed with free app users vs paying customers - people using free things actually have higher expectations!&lt;br /&gt;&lt;br /&gt;The SoundPool class, which is used to play back sampled sounds and seems ideal for games, will randomly crash on some hardware platforms and some versions of Android if you use MP3. MP3 is one of the supported media formats, but there are some weird issues on some phones. For example Chaos crashed on an HTC Hero, which has almost identical hardware to a Magic, running similar versions of Android (2.2.1 "official" vs 2.2.1 cyanogen mod). Random internet forum posts show that OGG files work better, but that WAV files can crash if looped. When I switched from using MP3 to OGG the crash reports I was seeing dried up.&lt;br /&gt;&lt;br /&gt;When managing the life-cycle of a native application, strange things can happen with your OpenGL context. According to the documentation all you need to do is call the "onPause()" and "onResume()" methods of your GLSurfaceView when the user switches away and then returns to the game. However, on Android 1.6 at least you can get in a state were the "onSurfaceChanged()" method is not called again, so you don't have a hook to setting up the correct GL state. This seems to have gone away with Android 2.2, or at least the game's already set-up context is not ruined in the same way. On 1.6 I'd seen Chaos have a wrecked graphical display after the phone went to sleep, but since the 2.2 update this hasn't happened to me.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;You should use 30 FPS as a baseline&lt;/h2&gt;&lt;br /&gt;A few weeks ago I wrote about &lt;a href="http://quirkygba.blogspot.com/2010/10/android-native-coding-in-c.html"&gt;getting a good frame rate&lt;/a&gt; on Android using the NDK. On my HTC Magic I was getting nearly 60 FPS with that approach. Well, it turns out that new devices are &lt;a href="http://www.google.com/events/io/2010/sessions/writing-real-time-games-android.html"&gt;limited to 30 fps&lt;/a&gt;. So if I assume a 60 fps rate (as seen on the DS), I would make everything run half as fast. The solution is to limit the frame rate to 30 fps even on "faster" (older!) hardware.&lt;br /&gt;&lt;br /&gt;An advantage to running at a lower frame rate is that it saves the battery, but it still seems a bit backwards to me.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_nzN39P0Ykuk/TTMg6OAUkKI/AAAAAAAABTQ/f0Giid06Vmg/s1600/rtg.png" imageanchor="1"&gt;&lt;img border="0" height="246" src="http://2.bp.blogspot.com/_nzN39P0Ykuk/TTMg6OAUkKI/AAAAAAAABTQ/f0Giid06Vmg/s320/rtg.png" width="320" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;More ratings after an update&lt;/h2&gt;&lt;br /&gt;Almost every time I've posted a new version of Chaos it has received a few new ratings on the Market. I imagine that this is because people download the game then go off and play it, but forget to go back to the Market and rate it. When a new version appears, they return to the Market and now they know it's amazing (!) so rate it 5 stars and install the update.&lt;br /&gt;&lt;br /&gt;Don't abuse this phenomenon though. If you upload lots of minor versions with no user-visible changes, people will quickly tire and start rating your game &lt;i&gt;worse&lt;/i&gt;. I saw this effect in a few comments for the game "My Paper Plane 2", which had dozens of minor updates with no new features. One reviewer said "Minus 2 stars for frequency of updates and no explanation."&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Eclipse is not great&lt;/h2&gt;&lt;br /&gt;I don't know if the issues I've had are related to the ADT plugin, communication with the emulator or Eclipse itself, but the integration of the whole &lt;a class="zem_slink" href="http://code.google.com/android/" rel="homepage" title="Android"&gt;Android SDK&lt;/a&gt; + &lt;a class="zem_slink" href="http://www.eclipse.org/" rel="homepage" title="Eclipse (software)"&gt;Eclipse IDE&lt;/a&gt; is flaky. Often the text editing GUI hangs for 30+ seconds when you type a "." and auto-complete kicks in, with the CPU grinding away at 100%.&lt;br /&gt;&lt;br /&gt;Other times Eclipse fails to connect to the emulator to debug or upload new apk files, and you have to restart the emulator. The emulator takes &lt;i&gt;minutes&lt;/i&gt; to restart, it is slower to boot than even the hardware phone. Then there's the built in logcat view that will miss messages if they pass by too quickly. The command line &lt;code&gt;adb logcat&lt;/code&gt; equivalent will show you what you missed.&lt;br /&gt;I haven't tried the GUI builder nor XML editor, so cannot comment. At least in the last ADT version opening the XML layout files no longer causes a NullPointerException.&lt;br /&gt;&lt;br /&gt;As a result of all of this, I continue to do all my development using Vim. For auto-complete I use CTags and Vim's omni completion. This is enough for C code. When editing Java I just write out all my imports the old fashioned way, like we did back before IDEs hid this crufty aspect from us all. I can always say it is helping me learn the API...&lt;br /&gt;&lt;br /&gt;I have a Vim command &lt;code&gt;:AdbReinstall&lt;/code&gt; that loads the APK file onto the emulator or device. I can build using :make. It's great that the Android SDK is flexible enough to allow me to do this, there are even instructions on how to set parts of it up in the official documentation. I doubt it is as easy to do for iPhone or Windows development.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Filtering based on the hardware used&lt;/h2&gt;&lt;br /&gt;One interesting characteristic of the Android Market that has matured a lot in the last few months is the way applications are filtered based on the hardware features they use.&lt;br /&gt;&lt;br /&gt;As an example, Chaos uses the touch screen and is compiled for arm-eabi. The touch controls are actually optional - if you want you can just about get by with the trackball or d-pad and the buttons - but originally I didn't state that in the manifest. This meant that Chaos would not be seen on x86 Android devices (are there any?) nor on devices without a touch screen (examples?). This information was all auto-detected by the Market server - I didn't have to mention anything anywhere.&lt;br /&gt;&lt;br /&gt;Once I decided that Chaos was usable without a touch screen, I added a "uses-feature" section to the manifest stating that the touch screen was optional.&lt;br /&gt;&lt;br /&gt;There may be hardware fragmentation, but this part at least is handled in a quite developer-friendly way.&lt;br /&gt;&lt;br /&gt;The next game I'm doing will use the compass and accelerometer for tilt controls. As far as I can tell, I won't have to state anything in the manifest to avoid disappointing folk with phones without these features, the Market will add the filters automatically (we'll see!).&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Touch screen is bad for controls&lt;/h2&gt;&lt;br /&gt;The lack of physical buttons on Android means that several genres of games are not really possible, or you need to add a virtual d-pad and buttons on screen that react to touch. Unfortunately there seems to be a horrible bug in the way Android processes events when the user leaves their finger on the touch screen. When you hold your finger on the screen it leads to the touch input completely swamping the CPU to the detriment of the game's frame rate. The &lt;code&gt;onTouchEvent&lt;/code&gt; method is called every 10 milliseconds with what amount to non-events, such as subtle changes in pressure detected by the screen's sensor. Even if all you do in the event handler is store the touch position and type, to later process in the main thread, the application will lose out on framerate as the touch event thread is given priority.&lt;br /&gt;&lt;br /&gt;Now I may be doing something wrong here, but &lt;a href="http://stackoverflow.com/questions/792185/why-are-touch-events-destroying-my-android-framerate"&gt;several&lt;/a&gt; &lt;a href="http://stackoverflow.com/questions/4342464/android-touch-seriously-slowing-my-application"&gt;similar&lt;/a&gt;-&lt;a href="http://stackoverflow.com/questions/3597250/2d-game-on-android-surfaceview-runs-slowly-on-touch"&gt;looking&lt;/a&gt; &lt;a href="http://stackoverflow.com/questions/2345471/excessive-number-of-touch-events-slows-down-android-app"&gt;questions&lt;/a&gt; on stackoverflow.com seem to agree with my experience. There's a &lt;a href="http://code.google.com/p/android/issues/detail?id=7836"&gt;bug report on the Android project&lt;/a&gt; that has been fixed in Gingerbread. Sadly the lower-end devices that really need this fix will never see Android 2.3, at least not officially. Meanwhile, all the "sleep" workarounds proposed don't seem to make things any better.&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;There we are then. Android has some issues when compared to a closed hardware platform like the DS. You can't be 100% sure that what runs on your device will run on everyone else's. This is scary, but then there's a good chance your game will work OK. And it will probably work fine with different Android versions, screen resolutions, types of processor and hardware features. I think for free games, or if you have a free demo for people to try before they buy, then this is an acceptable compromise.&lt;br /&gt;&lt;br /&gt;After my albeit limited experience with this, I understand now why a limited hardware platform is going to be more popular for games. If you compare the amount and variety of games released on the Apple hardware (iP*d/iPhone) to Android, the difference is huge. Giving stuff away for free is obviously not too cost effective (having embedded adverts can mitigate this, but adverts are only viable on huge hits) and creating a free demo takes time away from creating the core game. So given the choice, developers would rather have people pay for the game, right? If you expect people to pay for your game, then you'd like to think it works on their device. When you write for a platform with a limited range of hardware devices, you only have to test on those devices. With the DS, the DSi and DSiXL are identical platforms - Nintendo is very careful about backwards compatibility. You don't need need to test GBA games on a DS to check they run correctly, for example. These things just work.&lt;br /&gt;&lt;br /&gt;Now if we consider Android, there's no way any regular developer could test all possible devices. The best you could hope for is to test on maybe some representative devices. If you support old versions of Android, a first generation HTC phone. Then maybe something like a Nexus One, then a Sony phone as they seem to have quite different Open GL hardware, maybe a Motorola and a Samsung due to their popularity. Factor the tablet-sized Android devices and we're talking quite an investment.&lt;br /&gt;&lt;br /&gt;This doesn't include the various Android versions that may run on these devices - you probably have to target a lower API level and hope not to slip up and include newer Java API calls. Those would result in run time errors on older versions than your target API. When you write a game primarily in C it's harder to slip up like this, but still possible. For example, getting the name of the SD card directory to write to changed a lot in Froyo. Given all of this, the openness of Android is definitely off-putting if you're only in it for the money. As a tinkerer into this stuff, it certainly keeps me on my toes. Maybe the new Gingerbread SDK with its "look ma! no Java!" C-only Activities and touch screen bug fixes will lead to more Android 2.3-only (paid) games. Especially if the Sony Play-not-station phone runs this version and has any kind of popularity.&lt;br /&gt;&lt;br /&gt;Who am I kidding? It's more likely that the iP*s will continue their rise in popularity with gamers, while Android becomes the new N-Gage. Hey I wonder if the 3DS will be hackable? :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-8337981639703210820?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/8337981639703210820/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2011/01/lessons-learned-with-android.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/8337981639703210820'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/8337981639703210820'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2011/01/lessons-learned-with-android.html' title='Lessons Learned with Android'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_nzN39P0Ykuk/TTMg6OAUkKI/AAAAAAAABTQ/f0Giid06Vmg/s72-c/rtg.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-3830493572250019418</id><published>2010-12-19T23:06:00.001+01:00</published><updated>2011-01-16T17:22:38.086+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nintendo DSi'/><category scheme='http://www.blogger.com/atom/ns#' term='Game Boy Advance'/><category scheme='http://www.blogger.com/atom/ns#' term='Chaos'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><title type='text'>Changes in Chaos 1.4</title><content type='html'>I've uploaded another version of &lt;a href="http://www.appbrain.com/app/chaos-the-battle-of-wizards/chaos.app"&gt;Chaos to the Market&lt;/a&gt;. 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.&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;&lt;img border="0" height="400" width="300" src="http://1.bp.blogspot.com/_nzN39P0Ykuk/TTMUsTtu5SI/AAAAAAAABTA/8ROw03gf1HU/s400/7ZMel.png" /&gt;&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;I fixed a minor bug that caused the game to show the meditate spell incorrectly on the "examine spell" screen. No biggie there.&lt;br /&gt;&lt;br /&gt;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 &lt;a href="http://thedailywtf.com/Articles/The-Speedup-Loop.aspx"&gt;about the software company that added a pointless loop in the code&lt;/a&gt; that they reduced by an order of magnitude every now and again for an "amazing speedup".&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;I've created a new site with the &lt;a href="https://sites.google.com/site/chaosbattleofwizards/download"&gt;Nintendo DS and Game Boy Advance downloads&lt;/a&gt; as well as &lt;a href="https://sites.google.com/site/chaosbattleofwizards/"&gt;some instructions on how to play on Android&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;img alt="My own computer museum" src="http://2.bp.blogspot.com/_nzN39P0Ykuk/TTMaa08VG6I/AAAAAAAABTI/-Sf9AIIZnuI/s400/dgNeD.jpg" title="My own computer museum" /&gt;&lt;br /&gt;&lt;br /&gt;The photo was taken using a DSi of course :-) Suffice to say my dear wife was not impressed. I was accused of being like &lt;a href="http://phobos.express.ge/ZoneF/17/performer//Jean%20Michel%20Jarre/.photo/jean-michel-jarre.jpg"&gt;Jean Michel Jarre, surrounded by gadgets&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-3830493572250019418?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/3830493572250019418/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2010/12/changes-in-chaos-14.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/3830493572250019418'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/3830493572250019418'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2010/12/changes-in-chaos-14.html' title='Changes in Chaos 1.4'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_nzN39P0Ykuk/TTMUsTtu5SI/AAAAAAAABTA/8ROw03gf1HU/s72-c/7ZMel.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-1482966966693806592</id><published>2010-12-05T01:17:00.001+01:00</published><updated>2010-12-05T01:19:37.796+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Chaos'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><category scheme='http://www.blogger.com/atom/ns#' term='Google Code'/><title type='text'>Chaos 1.3</title><content type='html'>&amp;nbsp;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.&lt;br /&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_nzN39P0Ykuk/TPrZ4ykLeFI/AAAAAAAABSg/ra4YQ2zJ-2I/s1600/device.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="266" src="http://2.bp.blogspot.com/_nzN39P0Ykuk/TPrZ4ykLeFI/AAAAAAAABSg/ra4YQ2zJ-2I/s400/device.png" width="400" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Spell select screen&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;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 &lt;a href="http://www.google.com/codesearch?q=android%3AminSdkVersion+lang%3Axml"&gt;API strings on Google Code Search&lt;/a&gt; turns up real world uses of the features and the correct implementation.&lt;br /&gt;&lt;br /&gt;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 &lt;i&gt;doesn't&lt;/i&gt; include different headers, etc. for API levels 6 or 7.&lt;br /&gt;&lt;br /&gt;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&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-1482966966693806592?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/1482966966693806592/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2010/12/chaos-13.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/1482966966693806592'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/1482966966693806592'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2010/12/chaos-13.html' title='Chaos 1.3'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_nzN39P0Ykuk/TPrZ4ykLeFI/AAAAAAAABSg/ra4YQ2zJ-2I/s72-c/device.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-6677814992664076304</id><published>2010-12-01T23:08:00.003+01:00</published><updated>2011-04-30T20:31:24.461+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='AndroidMarket'/><category scheme='http://www.blogger.com/atom/ns#' term='Chaos'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><title type='text'>Responding to Android Market Comments</title><content type='html'>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 &lt;a href="http://www.appbrain.com/app/chaos-the-battle-of-wizards/chaos.app"&gt;Chaos&lt;/a&gt;...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;by Neko_Noskire (November 28, 2010) &lt;span style="color: #ff9900;"&gt;★★★★&lt;/span&gt;☆&lt;br /&gt;This is what trading card games should have been like. A way to get out of the game would be nice.&lt;/blockquote&gt;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 &lt;a href="http://developer.android.com/guide/topics/fundamentals.html#actlife"&gt;Android Activity lifecycle&lt;/a&gt; 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.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;by Peter (November 21, 2010) &lt;span style="color: #ff9900;"&gt;★★★&lt;/span&gt;☆☆&lt;br /&gt;Pretty good, but needs landscape mode &amp;amp; speeding up; missing "attack" sound&lt;/blockquote&gt;I wonder if Peter uses an EVO 4G? Rumour has it that the frame rate is &lt;a href="http://www.engadget.com/2010/06/10/htc-evo-4gs-graphics-capped-at-30fps/"&gt;capped at 30 frames per second&lt;/a&gt;, 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.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;by Jon (November 20, 2010) &lt;span style="color: #ff9900;"&gt;★★★★★&lt;/span&gt;&lt;br /&gt;I now no longer need any other game. Awesome retro fun!&lt;/blockquote&gt;Thanks Jon! :-)&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;by Martin (November 1, 2010) &lt;span style="color: #ff9900;"&gt;★&lt;/span&gt;☆☆☆☆&lt;br /&gt;Naja, schwaches Game. Keine gescheite Steuerung :(&lt;/blockquote&gt;Translation: &lt;span style="font-style: italic;"&gt;Well, weak game. No intelligent control.&lt;/span&gt; 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.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;by Kieron (October 31, 2010) &lt;span style="color: #ff9900;"&gt;★★★★★&lt;/span&gt;&lt;br /&gt;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&lt;/blockquote&gt;This is why I wrote the GBA version originally too - I could play Chaos on &lt;a href="http://sourceforge.net/projects/foon/"&gt;FooN&lt;/a&gt;, but the controls were unwieldy. Almost a remake of a remake then.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;by darren (October 31, 2010) &lt;span style="color: #ff9900;"&gt;★★★★★&lt;/span&gt;&lt;br /&gt;Amazing cool sexy fun ! Hint ! Kill the warlock on level seven by using your blood diamond in his water&lt;/blockquote&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-6677814992664076304?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/6677814992664076304/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2010/12/responding-to-android-market-comments.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/6677814992664076304'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/6677814992664076304'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2010/12/responding-to-android-market-comments.html' title='Responding to Android Market Comments'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-6489378961851275145</id><published>2010-11-07T20:06:00.003+01:00</published><updated>2010-11-07T20:12:57.492+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Chaos'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><title type='text'>Changes in Chaos 1.1</title><content type='html'>&lt;p&gt;I've updated version &lt;a href="http://www.appbrain.com/app/chaos-the-battle-of-wizards/chaos.app"&gt;1.1 of Chaos in the Android Market&lt;/a&gt;. This version contains 2 bug fixes:&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Computer opponents could never move again after casting Meditate&lt;/li&gt;&lt;li&gt;2 sources of random crashes fixed&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;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.&lt;/p&gt;&lt;p&gt;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 &lt;a href="http://valgrind.org/"&gt;valgrind&lt;/a&gt;. 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.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-6489378961851275145?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/6489378961851275145/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2010/11/changes-in-chaos-11.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/6489378961851275145'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/6489378961851275145'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2010/11/changes-in-chaos-11.html' title='Changes in Chaos 1.1'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-6309558501120320581</id><published>2010-10-31T18:06:00.002+01:00</published><updated>2010-10-31T18:09:15.229+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Chaos'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><title type='text'>Chaos on Android!</title><content type='html'>&lt;p&gt;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 &lt;a href="market://search?q=pname:chaos.app"&gt;market://search?q=pname:chaos.app&lt;/a&gt; or you can &lt;a href="http://www.appbrain.com/app/chaos.app?install"&gt;download via appbrain.com here&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;img alt="Spell selection screen" src="http://i.imgur.com/WK8UT.png" /&gt;&lt;br /&gt;&lt;img alt="Movement round screen" src="http://i.imgur.com/kE4Xe.png" /&gt;&lt;/p&gt;This is pretty much a straight port of the &lt;a href="https://sites.google.com/site/gbaremakes/home/games/chaos/screens"&gt;GBA version of Chaos&lt;/a&gt; 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.&lt;p&gt;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.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-6309558501120320581?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/6309558501120320581/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2010/10/chaos-on-android.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/6309558501120320581'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/6309558501120320581'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2010/10/chaos-on-android.html' title='Chaos on Android!'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-924867619720852034</id><published>2010-10-13T02:00:00.001+02:00</published><updated>2010-11-13T11:50:01.561+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Chaos'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><category scheme='http://www.blogger.com/atom/ns#' term='HOWTO'/><title type='text'>Android Native Coding in C</title><content type='html'>&lt;p&gt;When I read questions like &lt;a href="http://stackoverflow.com/questions/3665386/"&gt;"How to do code sharing between Android and iOS"&lt;/a&gt; on stackoverflow.com, 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.&lt;/p&gt;&lt;p&gt;&lt;img alt="Chaos running on the HTC Magic" src="http://i.imgur.com/huASy.png" title="Chaos Battle of Wizards" /&gt;&lt;/p&gt;&lt;p&gt;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 &lt;a href="http://developer.android.com/reference/android/opengl/GLSurfaceView.html"&gt;GLSurfaceView&lt;/a&gt;. Then you use the Java Native Interface (JNI) to call from Java into your C code. You compile your C code using the &lt;a href="http://developer.android.com/sdk/ndk/index.html"&gt;Android Native Development Kit&lt;/a&gt;. The remaining problem is then: how can I draw pixels?&lt;/p&gt;&lt;p&gt;You have 2 options (3 if you are willing to target Android 2.2+): drawing pixels to a &lt;a href="http://developer.android.com/reference/android/graphics/Canvas.html#drawBitmap%28int[],%20int,%20int,%20int,%20int,%20int,%20int,%20boolean,%20android.graphics.Paint%29"&gt;Canvas&lt;/a&gt;, drawing to an OpenGL ES texture, or drawing directly to the pixel buffer of a &lt;a href="http://developer.android.com/reference/android/graphics/Bitmap.html"&gt;Bitmap&lt;/a&gt;. This last option is similar to option 1, but is faster and available on Android 2.2 "Froyo" only.&lt;/p&gt;&lt;p&gt;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 &lt;code&gt;gl.&lt;/code&gt; to all the GL function calls (&lt;code&gt;gl.glActiveTexture&lt;/code&gt; for example, where &lt;code&gt;gl&lt;/code&gt; 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.&lt;/p&gt;&lt;p&gt;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".&lt;/p&gt;&lt;p&gt;The main loop can be the classic &lt;code&gt;while (1) { update_state(); wait_vsync();}&lt;/code&gt;. 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.&lt;/p&gt;&lt;p&gt;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:&lt;/p&gt;&lt;pre&gt;&lt;div style="background-color: rgb(0, 0, 0); color: rgb(255, 255, 255); font-weight: bold;"&gt;&lt;span style="font-family:monospace;"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt; &lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt; &lt;span style="color: rgb(128, 128, 255);"&gt;&lt;b&gt;native&lt;/b&gt;&lt;/span&gt; &lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/span&gt; native_start();&lt;br /&gt;&lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt; &lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt; &lt;span style="color: rgb(128, 128, 255);"&gt;&lt;b&gt;native&lt;/b&gt;&lt;/span&gt; &lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/span&gt; native_gl_resize(&lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; w, &lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; h);&lt;br /&gt;&lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt; &lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt; &lt;span style="color: rgb(128, 128, 255);"&gt;&lt;b&gt;native&lt;/b&gt;&lt;/span&gt; &lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/span&gt; native_gl_render();&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt; {&lt;br /&gt;       System.loadLibrary(&lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;"mybuffer"&lt;/b&gt;&lt;/span&gt;);&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;p&gt;Now you have to write these in C and somehow register them with the &lt;a href="http://en.wikipedia.org/wiki/Dalvik_%28software%29"&gt;Dalvik&lt;/a&gt; VM (or "&lt;a href="http://en.wikipedia.org/wiki/Dalek"&gt;Dalek&lt;/a&gt; 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 &lt;code&gt;dlopen()&lt;/code&gt; and looks for the symbol &lt;code&gt;JNI_OnLoad&lt;/code&gt; and functions with "mangled" names that match the native declarations. The library loaded here will be "libmybuffer.so". You can either implement your functions with the mangled names or using a call to "RegisterNatives" in the &lt;code&gt;JNI_OnLoad&lt;/code&gt; function. There are many &lt;a href="http://java.sun.com/docs/books/jni/html/start.html#769"&gt;JNI tutorials&lt;/a&gt; on the net, I won't rewrite how to do that here. Whichever way you choose, you still need to have the &lt;code&gt;native&lt;/code&gt; declarations in your Java source code. My examples are using RegisterNatives, as it gives cleaner C function names.&lt;/p&gt;&lt;p&gt;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.&lt;/p&gt;&lt;pre&gt;&lt;div style="background-color: rgb(0, 0, 0); color: rgb(255, 255, 255); font-weight: bold;"&gt;&lt;span style="font-family:monospace;"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; GlBufferView(Context context, AttributeSet attrs) {&lt;br /&gt;       &lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;super&lt;/b&gt;&lt;/span&gt;(context, attrs);&lt;br /&gt;       (&lt;span style="color: rgb(255, 255, 0);"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt; Thread() {&lt;br /&gt;               &lt;span style="color: rgb(128, 128, 255);"&gt;&lt;b&gt;@Override&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;               &lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/span&gt; run() {&lt;br /&gt;                       native_start();&lt;br /&gt;               }&lt;br /&gt;       }).start();&lt;br /&gt;       setRenderer(&lt;span style="color: rgb(255, 255, 0);"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt; MyRenderer());&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;p&gt;The implementation of your GLSurfaceView.Renderer class simply delegates to the native functions and should look like this:&lt;/p&gt;&lt;pre&gt;&lt;div style="background-color: rgb(0, 0, 0); color: rgb(255, 255, 255); font-weight: bold;"&gt;&lt;span style="font-family:monospace;"&gt;&lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt; MyRenderer &lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;implements&lt;/b&gt;&lt;/span&gt; GLSurfaceView.Renderer {&lt;br /&gt;       &lt;span style="color: rgb(128, 128, 255);"&gt;&lt;b&gt;@Override&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;       &lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/span&gt; onSurfaceCreated(GL10 gl, EGLConfig c) { &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;/* do nothing */&lt;/b&gt;&lt;/span&gt; }&lt;br /&gt;&lt;br /&gt;       &lt;span style="color: rgb(128, 128, 255);"&gt;&lt;b&gt;@Override&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;       &lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/span&gt; onSurfaceChanged(GL10 gl, &lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; w, &lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; h) {&lt;br /&gt;               native_gl_resize(w, h);&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       &lt;span style="color: rgb(128, 128, 255);"&gt;&lt;b&gt;@Override&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;       &lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/span&gt; onDrawFrame(GL10 gl) {&lt;br /&gt;               native_gl_render();&lt;br /&gt;       }&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;onSurfaceCreated&lt;/code&gt; method is not used, the &lt;code&gt;onSurfaceChanged&lt;/code&gt; method is what the OpenGL implementation really uses to indicate a screen should be set up properly. The method &lt;code&gt;onDrawFrame&lt;/code&gt; is called once per frame, at a rate of between 30-60 FPS (if you're lucky).&lt;/p&gt;&lt;p&gt;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 &lt;code&gt;native_gl_resize&lt;/code&gt; method should grab a texture and set up the simplest rendering scenario it can. Experimentation has shown that this is not too shabby:&lt;/p&gt;&lt;pre&gt;&lt;div style="background-color: rgb(0, 0, 0); color: rgb(255, 255, 255); font-weight: bold;"&gt;&lt;span style="font-family:monospace;"&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 255);"&gt;&lt;b&gt;#define TEXTURE_WIDTH  &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;512&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 255);"&gt;&lt;b&gt;#define TEXTURE_HEIGHT &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;256&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 255);"&gt;&lt;b&gt;#define MY_SCREEN_WIDTH  &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;272&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 255);"&gt;&lt;b&gt;#define MY_SCREEN_HEIGHT &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;208&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt; &lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; s_w;&lt;br /&gt;&lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt; &lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; s_h;&lt;br /&gt;&lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt; GLuint s_texture;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/span&gt; JNICALL native_gl_resize(JNIEnv *env, jclass clazz, jint w, jint h)&lt;br /&gt;{&lt;br /&gt;       glEnable(GL_TEXTURE_2D);&lt;br /&gt;       glGenTextures(&lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;1&lt;/b&gt;&lt;/span&gt;, &amp;amp;s_texture);&lt;br /&gt;       glBindTexture(GL_TEXTURE_2D, s_texture);&lt;br /&gt;       glTexParameterf(GL_TEXTURE_2D,&lt;br /&gt;                       GL_TEXTURE_MIN_FILTER, GL_LINEAR);&lt;br /&gt;       glTexParameterf(GL_TEXTURE_2D,&lt;br /&gt;                       GL_TEXTURE_MAG_FILTER, GL_LINEAR);&lt;br /&gt;       glShadeModel(GL_FLAT);&lt;br /&gt;       glColor4x(&lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;0x10000&lt;/b&gt;&lt;/span&gt;, &lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;0x10000&lt;/b&gt;&lt;/span&gt;, &lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;0x10000&lt;/b&gt;&lt;/span&gt;, &lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;0x10000&lt;/b&gt;&lt;/span&gt;);&lt;br /&gt;       &lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; rect[&lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;4&lt;/b&gt;&lt;/span&gt;] = {&lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;0&lt;/b&gt;&lt;/span&gt;, MY_SCREEN_HEIGHT, MY_SCREEN_WIDTH, -MY_SCREEN_HEIGHT};&lt;br /&gt;       glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, rect);&lt;br /&gt;       glTexImage2D(GL_TEXTURE_2D,             &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;/*&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt; target &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;*/&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;                       &lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;0&lt;/b&gt;&lt;/span&gt;,                      &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;/*&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt; level &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;*/&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;                       GL_RGB,                 &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;/*&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt; internal format &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;*/&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;                       TEXTURE_WIDTH,          &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;/*&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt; width &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;*/&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;                       TEXTURE_HEIGHT,         &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;/*&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt; height &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;*/&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;                       &lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;0&lt;/b&gt;&lt;/span&gt;,                      &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;/*&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt; border &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;*/&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;                       GL_RGB,                 &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;/*&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt; format &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;*/&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;                       GL_UNSIGNED_SHORT_5_6_5,&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;/*&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt; type &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;*/&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;                       &lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;NULL&lt;/b&gt;&lt;/span&gt;);                  &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;/*&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt; pixels &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;*/&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;       &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;/*&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt; store the actual width of the screen &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;*/&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;       s_w = w;&lt;br /&gt;       s_h = h;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;p&gt;You can also call &lt;code&gt;glDisable&lt;/code&gt; to turn off fog, depth, and other 3D functions, but it doesn't seem to make too much difference. The &lt;code&gt;glEnable(GL_TEXTURE_2D);&lt;/code&gt; call enables textures. You need this as you'll be drawing your pixels into a texture. &lt;code&gt;glGenTextures&lt;/code&gt; and &lt;code&gt;glBindTexture&lt;/code&gt; get a handle to a texture and set it as the currently used one. The 2 &lt;code&gt;glTexParameterf&lt;/code&gt; 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 &lt;code&gt;glShadeModel&lt;/code&gt; and &lt;code&gt;glColor4x&lt;/code&gt; 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.&lt;/p&gt;&lt;p&gt;The &lt;code&gt;rect[4]&lt;/code&gt; array and associated &lt;code&gt;glTexParameteriv&lt;/code&gt; 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 &lt;code&gt;glTexImage2D&lt;/code&gt; 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.&lt;/p&gt;&lt;p&gt;Now the render code. This uses the &lt;code&gt;glDrawTexiOES&lt;/code&gt; 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.&lt;/p&gt;&lt;pre&gt;&lt;div style="background-color: rgb(0, 0, 0); color: rgb(255, 255, 255); font-weight: bold;"&gt;&lt;span style="font-family:monospace;"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/span&gt; JNICALL native_gl_render(JNIEnv *env UNUSED, jclass clazz UNUSED)&lt;br /&gt;{&lt;br /&gt;       memset(s_pixels, &lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;0&lt;/b&gt;&lt;/span&gt;, S_PIXELS_SIZE);&lt;br /&gt;       render_pixels(s_pixels);&lt;br /&gt;       glClear(GL_COLOR_BUFFER_BIT);&lt;br /&gt;       glTexSubImage2D(GL_TEXTURE_2D,          &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;/*&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt; target &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;*/&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;                       &lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;0&lt;/b&gt;&lt;/span&gt;,                      &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;/*&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt; level &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;*/&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;                       &lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;0&lt;/b&gt;&lt;/span&gt;,                      &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;/*&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt; xoffset &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;*/&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;                       &lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;0&lt;/b&gt;&lt;/span&gt;,                      &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;/*&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt; yoffset &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;*/&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;                       MY_SCREEN_WIDTH,        &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;/*&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt; width &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;*/&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;                       MY_SCREEN_HEIGHT,       &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;/*&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt; height &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;*/&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;                       GL_RGB,                 &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;/*&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt; format &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;*/&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;                       GL_UNSIGNED_SHORT_5_6_5, &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;/*&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt; type &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;*/&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;                       s_pixels);              &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;/*&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt; pixels &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;*/&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;       glDrawTexiOES(&lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;0&lt;/b&gt;&lt;/span&gt;, &lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;0&lt;/b&gt;&lt;/span&gt;, &lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;0&lt;/b&gt;&lt;/span&gt;, s_w, s_h);&lt;br /&gt;       &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;/*&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt; tell the other thread to carry on &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;*/&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;       pthread_cond_signal(&amp;amp;s_vsync_cond);&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;memset&lt;/code&gt; 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 &lt;code&gt;render_pixels&lt;/code&gt; routine does whatever it takes to draw your game's pixels into the &lt;code&gt;s_pixels&lt;/code&gt; array in the RGB565 format. The &lt;code&gt;glClear&lt;/code&gt; 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 &lt;code&gt;glTexSubImage2D&lt;/code&gt; call will copy the &lt;code&gt;s_pixels&lt;/code&gt; data into video memory, only updating the area indicated rather than the whole thing. If you &lt;em&gt;do&lt;/em&gt; update the whole texture it is actually faster to call &lt;code&gt;glTexImage2D&lt;/code&gt;. Finally, &lt;code&gt;glDrawTexiOES&lt;/code&gt; will draw the texture to the screen, scaled to the screen size.&lt;/p&gt;&lt;p&gt;The final &lt;code&gt;pthread_cond_signal&lt;/code&gt; 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 &lt;em&gt;experience&lt;/em&gt;, 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.&lt;/p&gt;&lt;pre&gt;&lt;div style="background-color: rgb(0, 0, 0); color: rgb(255, 255, 255); font-weight: bold;"&gt;&lt;span style="font-family:monospace;"&gt;&lt;span style="color: rgb(128, 128, 255);"&gt;&lt;b&gt;#define UNUSED  __attribute__((unused))&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt; &lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/span&gt; wait_vsync()&lt;br /&gt;{&lt;br /&gt;       pthread_mutex_lock(&amp;amp;s_vsync_mutex);&lt;br /&gt;       pthread_cond_wait(&amp;amp;s_vsync_cond, &amp;amp;s_vsync_mutex);&lt;br /&gt;       pthread_mutex_unlock(&amp;amp;s_vsync_mutex);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;void&lt;/b&gt;&lt;/span&gt; JNICALL native_start(JNIEnv *env UNUSED, jclass clazz UNUSED)&lt;br /&gt;{&lt;br /&gt;       &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;/*&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt; init conditions &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;*/&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;       pthread_cond_init(&amp;amp;s_vsync_cond, &lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;NULL&lt;/b&gt;&lt;/span&gt;);&lt;br /&gt;       pthread_mutex_init(&amp;amp;s_vsync_mutex, &lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;NULL&lt;/b&gt;&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;       &lt;span style="color: rgb(255, 255, 0);"&gt;&lt;b&gt;while&lt;/b&gt;&lt;/span&gt; (&lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt;1&lt;/b&gt;&lt;/span&gt;) {&lt;br /&gt;               &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;/*&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt; game code goes here &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;*/&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;               wait_vsync();&lt;br /&gt;       }&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;p&gt;That ensures that main loop can wait on screen redraws, which avoids tearing.&lt;/p&gt;&lt;p&gt;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 :-)&lt;/p&gt;&lt;p&gt;I've made a compilable example of this code available on &lt;a href="https://github.com/richq/glbuffer/tree/"&gt;github here&lt;/a&gt;.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-924867619720852034?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/924867619720852034/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2010/10/android-native-coding-in-c.html#comment-form' title='16 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/924867619720852034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/924867619720852034'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2010/10/android-native-coding-in-c.html' title='Android Native Coding in C'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>16</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-2247573188940691210</id><published>2010-10-01T23:45:00.001+02:00</published><updated>2010-10-04T09:44:43.902+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nintendo DSi'/><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><category scheme='http://www.blogger.com/atom/ns#' term='Nintendo'/><title type='text'>A new era?</title><content type='html'>&lt;p&gt;&lt;span style="font-weight: bold;"&gt;TL;DL&lt;/span&gt; I've bought an Android phone and will probably stop writing DS stuff.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;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.&lt;/p&gt;&lt;p&gt;Want some more reasons?  How about Nintendo's &lt;a href="http://www.afterdawn.com/news/article.cfm/2010/07/29/uk_court_rules_r4_carts_for_ds_illegal"&gt;action against flash cards in the UK?&lt;/a&gt; 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.&lt;/p&gt;&lt;p&gt;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.&lt;/p&gt;&lt;p&gt;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!&lt;/p&gt;&lt;p&gt;I bought a &lt;a class="zem_slink" href="http://en.wikipedia.org/wiki/Nintendo_DSi" title="Nintendo DSi" rel="wikipedia"&gt;DSi&lt;/a&gt; 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.&lt;/p&gt;&lt;p&gt;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 &lt;a href="http://davejmurphy.com/dsi-mode-homebrew-anyone/"&gt;latest exploit&lt;/a&gt; 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.&lt;/p&gt;&lt;p&gt;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).&lt;/p&gt;&lt;p&gt;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 &lt;a href="http://shop.ebay.com/?_nkw=htc+magic"&gt;2nd hand&lt;/a&gt; &lt;a class="zem_slink" href="http://code.google.com/android/" title="Android" rel="homepage"&gt;Android phone&lt;/a&gt; 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.&lt;/p&gt;&lt;p&gt;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.&lt;/p&gt;&lt;p&gt;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 &lt;em&gt;huge&lt;/em&gt; and you can use all of the standard Java libraries... what's not to like? Well, Java is a bit tedious, but the &lt;a href="http://developer.android.com/sdk/ndk/index.html#overview"&gt;NDK&lt;/a&gt; leaves the door open for writing good old C or even ARM assembly.&lt;/p&gt;&lt;p&gt;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).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-2247573188940691210?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/2247573188940691210/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2010/10/new-era.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/2247573188940691210'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/2247573188940691210'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2010/10/new-era.html' title='A new era?'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-1939799549627773306</id><published>2010-01-04T04:00:00.000+01:00</published><updated>2010-01-04T04:00:01.067+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DS'/><category scheme='http://www.blogger.com/atom/ns#' term='DSi'/><category scheme='http://www.blogger.com/atom/ns#' term='Bunjalloo'/><category scheme='http://www.blogger.com/atom/ns#' term='HOWTO'/><title type='text'>Wi-Fi on the Nintendo DS</title><content type='html'>&lt;p&gt;I've had a couple of people ask me about which &lt;a href="http://en.wikipedia.org/wiki/Nintendo_ds#Nintendo_Wi-Fi_Connection"&gt;Wi-Fi settings&lt;/a&gt; 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.&lt;/p&gt;&lt;p&gt;The original Nintendo DS or DS lite has 3 different ways to connect to a wireless network:&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Connect to an unencrypted Wi-Fi access point&lt;/li&gt;&lt;li&gt;Connect to a Wi-Fi access point encrypted with &lt;a href="http://en.wikipedia.org/wiki/Wired_Equivalent_Privacy"&gt;WEP&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Connect to a &lt;a href="http://en.wikipedia.org/wiki/Nintendo_Wi-Fi_USB_Connector"&gt;Nintendo USB Wi-Fi Connection&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The Nintendo DSi adds an Advanced Settings with the following feature:&lt;br /&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Connect to a Wi-Fi access point encrypted with &lt;a href="http://en.wikipedia.org/wiki/Wi-Fi_Protected_Access"&gt;WPA&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Bunjalloo will only work with unencrypted or WEP encrypted Wi-Fi settings. It does not work with the DSi &lt;em&gt;Advanced Settings&lt;/em&gt; options (WPA), nor does it work with the Nintendo USB Wi-Fi Connection.&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;These limitations are partly due to the &lt;a href="http://sourceforge.net/projects/devkitpro/files/dswifi/"&gt;dswifi library&lt;/a&gt;, which &lt;a href="http://www.akkit.org/dswifi/"&gt;sgstair&lt;/a&gt; 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.&lt;/p&gt;&lt;p&gt;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.&lt;/p&gt;&lt;p&gt;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):&lt;/p&gt;&lt;p&gt;&lt;img alt="System Settings" src="http://i.imgur.com/AMOdNl.jpg" /&gt; &lt;img alt="Internet" src="http://i.imgur.com/X5YS7l.jpg" /&gt;&lt;/p&gt;&lt;p&gt;From the internet screen, tap Connection Settings then tap a connection to configure it:&lt;/p&gt;&lt;p&gt;&lt;img alt="Connection Settings" src="http://i.imgur.com/W8aIcl.jpg" /&gt; &lt;img alt="Configure Connection" src="http://i.imgur.com/xDFt3l.jpg" /&gt;&lt;/p&gt;&lt;p&gt;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.&lt;/p&gt;&lt;p&gt;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".&lt;/p&gt;&lt;p&gt;&lt;img alt="WPA Connection" src="http://i.imgur.com/GUYf2l.jpg" /&gt;&lt;/p&gt;&lt;p&gt;Here's what it says if you click on a grey padlock from the regular DSi Internet settings screen:&lt;/p&gt;&lt;p&gt;&lt;img alt="Unable To Connect" src="http://i.imgur.com/pC2Bkl.jpg" /&gt;&lt;br /&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;"Unable to connect to this access point using the current settings. To connect to this access point, use Advanced Setup"&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;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:&lt;/p&gt;&lt;p&gt;&lt;img alt="Advanced Connection" src="http://i.imgur.com/k0iojl.jpg" /&gt;&lt;br /&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;"Allows use of high-security proxy settings. Cannot be used with Nintendo DS-compatible functions."&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;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 &lt;a href="http://www.nintendo.com/ds/dsiware"&gt;DSiWare&lt;/a&gt; store, and other DSi-only titles.&lt;/p&gt;&lt;p&gt;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 &lt;a href="http://www.nintendo.com/consumer/wfc/en_na/ds/wrWEPkeyHelp.jsp"&gt;Nintendo Customer Service&lt;/a&gt; site.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-1939799549627773306?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/1939799549627773306/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2010/01/wi-fi-on-nintendo-ds.html#comment-form' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/1939799549627773306'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/1939799549627773306'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2010/01/wi-fi-on-nintendo-ds.html' title='Wi-Fi on the Nintendo DS'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-6010832401884849064</id><published>2009-12-30T18:29:00.004+01:00</published><updated>2009-12-30T18:33:13.951+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DS'/><title type='text'>Unofficial 2009 in Review</title><content type='html'>&lt;h2&gt;Intro&lt;/h2&gt;&lt;p&gt;Shortly we will be entering the Space Year 2010, so here is my unofficial review of this last year from the point of view of a DS fan and part-time homebrew coder. Please don't feel offended if I've left out your game or application. There's been a lot to get through.&lt;/p&gt;&lt;p&gt;This roundup was partly done from my recollections of homebrew in the last 12 months, and partly from trawling through my Google Reader feeds. I haven't been able to try out all of the releases this year so let me know in the comments if you feel particularly hard done by.&lt;/p&gt;&lt;p&gt;While creating this post, &lt;a href="http://pdroms.de/"&gt;PDRoms&lt;/a&gt; has been very useful. This site does a really great job of keeping the whole scene ticking over. Kojote has consistently posted interesting stuff, especially when you consider that he also covers a load of other portable platforms. Keep up the good work dude!&lt;/p&gt;&lt;p&gt;Other sites of note are &lt;a href="http://drunkencoders.com/"&gt;Drunken Coders&lt;/a&gt; and &lt;a href="http://www.nintendomax.com/phpBB2/rss.php?f=19"&gt;NintendoMax&lt;/a&gt; (That's their DS RSS feed). Writing your own DS programs seems to be all the rage in France and NintendoMax's site has had the scoop on the latest news most of the year. &lt;a href="http://www.wehackdsi.com/"&gt;We Hack DSi&lt;/a&gt; has also been an interesting read, though their posts are rather less frequent and tend to mix in some of the less salubrious aspects of the scene.&lt;/p&gt;&lt;p&gt;I've tried to link to the latest release for each game or application where I can. This way you don't end up downloading an initial, buggier release if there is a newer one available. This does mean that the text of the link ("Version 0.9" or whatever) doesn't always match up with the latest release on the target page, so keep that in mind if you are a history weeny.&lt;/p&gt;&lt;h2&gt;January&lt;/h2&gt;&lt;p&gt;&lt;img alt="DSi image" src="http://imgur.com/mB5io.jpg" title="Nintendo DSi" /&gt; The year began with news reports on the latest revision of the DS hardware, the DSi, which was already out in Japan. With 2 cameras and better wifi, it promised to be an interesting (if rather conservative) upgrade and everyone was looking forward to the releases in Europe and the US.&lt;/p&gt;&lt;p&gt;The homebrew scene started the year off with the arrival of the deadline for the &lt;a href="http://www.thepernproject.com/compo"&gt;Winter 2008 Compo&lt;/a&gt;. Nyarla's Snowride shoot 'em up came in first place, with the judges being particularly impressed by its graphics, music and Christmassy theme. It is a great game too, definitely download it if you haven't had the change to play it yet. Damn those penguins! It has the added advantage of being seasonal if you play it now. Bonus.&lt;/p&gt;&lt;p&gt;Around the middle of January &lt;a href="http://okiwi.blogspot.com/2009/01/y-fin-de-la-historia.html"&gt;Okiwi was officially abandoned&lt;/a&gt;, marking the end of the DS browser wars. Writing a web browser for a console with just 4MB of memory and a TCP library that is not as battle hardened as its big-brother PC counterparts is an exercise in frustration, so I know exactly where Pedro was coming from. I've abandoned Bunjalloo several times already, but keep coming back for more punishment.&lt;/p&gt;&lt;p&gt;Towards the end of the month the &lt;a href="http://moonbooks.info/"&gt;moonbooks project&lt;/a&gt; resurfaced after having the website hacked the previous year. In a strange homage to Geocities (perhaps) it still shows "under construction".&lt;/p&gt;&lt;p&gt;There were lots of homebrew releases in January. Some that stood out for me were:&lt;/p&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.zincland.com/powder/index.php?pagename=release&amp;amp;maxentries=4"&gt;Powder 110&lt;/a&gt; - Jeff continued to improve his fantastic rogue-like throughout 2009, albeit at a slower rate than in previous years.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Moonshell 2.0 - several beta releases marked the return of the ubiquitous menu/launcher/mp3/video player&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.portabledev.com/pages/ds/jeuxdev.-perso/aemioda.php"&gt;AemioDA&lt;/a&gt; - vector graphics emulator with an unpronouncable name, but it lets you play classics like Tempest, Asteroids and Lunar Lander. Lunar Lander sadly seems to ignore all my attempts to control the craft. Bummer.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.boive.fr/Jeux/Homebrews-DS/Brix-DS.html"&gt;Brix&lt;/a&gt; - ace physics game where you have to make towers topple over while carefully balanced sticks of dynamite land in the right place. Plays much better than my description, luckily.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://forum.gbadev.org/viewtopic.php?t=16312"&gt;maketens&lt;/a&gt; - mathsy fun with the numbers 1 to 5. An original puzzler that is fully playable, but lacks that last little bit of polish to make it a real classic. Still good though.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;p&gt;&lt;img alt="Powder" src="http://imgur.com/nbPBa.png" title="Powder screenshot" /&gt;&lt;/p&gt;&lt;p&gt;I did want to say &lt;a href="http://www.dev-fr.org/index.php?topic=4032/0/"&gt;DS1942&lt;/a&gt; at this point too, which is an emulator for the arcade classic 1942. I have been completely unable to get this to run though, with the emulator complaining about a missing "srb-03.m3" despite it being right there. Ho hum. You might have more luck. It did mark the start of a 2009 trend; stand alone emulators for individual arcade games, or sets of games. More later.&lt;/p&gt;&lt;h2&gt;February&lt;/h2&gt;&lt;p&gt;No hardware news for February, but the NDS homebrew scene was in full swing. Several of the games released in January got more updates.&lt;/p&gt;&lt;p&gt;&lt;img alt="Tetrominout" src="http://imgur.com/pJ7HN.png" /&gt;&lt;/p&gt;&lt;p&gt;I have fond memories of playing through &lt;a href="http://www.pdroms.de/files/1991/"&gt;Tetrominout&lt;/a&gt;, which is an amusing cross between Tetris and Breakout. Certainly it was a surprising twist on the usual "hello world" titles that new game coders often cut their teeth on.  Also out this month was a new version of the &lt;a href="http://www.devkitpro.org/devkitarm/"&gt;devkitARM toolchain and libraries.&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Other homebrew of note in February were:&lt;/p&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://ands-pdf.blogspot.com/"&gt;And's PDF reader&lt;/a&gt;, which bent the laws of computer science to squeeze the rather bloated PDF format onto the DS.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.glubiesplanet.com/en/index.html"&gt;Glubies Planet&lt;/a&gt;. We don't often see 3D homebrew games on the DS, so this one stood out from the crowd. The puzzley gameplay isn't bad either.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;h2&gt;March&lt;/h2&gt;&lt;p&gt;March was a slow month, with only a few updates to already released programs including And's PDF reader.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.tehskeen.com/viewarticle.php?articleid=3668"&gt;QuirkDS&lt;/a&gt; wasn't really new but it did get a big update right at the end of March. It's a remake of the old Game Boy title Kwirk and plays a bit like Sokoban (a bit, not really much). I'm completely hopeless at it, so good job it has a level skip. If anyone knows how you're supposed to move the yellow blocks that appear from about level 3 onwards, then please let me know in the comments.&lt;/p&gt;&lt;p&gt;News began to trickle through of a great looking remake of the Commodore 64 shooter Warhawk.&lt;/p&gt;&lt;h2&gt;April&lt;/h2&gt;&lt;p&gt;The big news as we entered the second quarter of the year was the launch of the Nintendo DSi in Europe and the US. Almost right away we received confirmation of our worst fears: the current generation of flash devices didn't work on the new console!&lt;/p&gt;&lt;p&gt;It wasn't really &lt;em&gt;that&lt;/em&gt; much of a shock of course, as Nintendo had threatened this already. In Japan there had already been confirmation of the bad news too. Still, it hit home when the console was finally out over here.&lt;/p&gt;&lt;p&gt;The Acekard had a working flash card that they had not-so-secretly been developing since the Japanese launch. Soon after this, R4 and EZ Flash released new flash cards that bypassed the DSi's stricter security. Homebrew was back on the cards.&lt;/p&gt;&lt;p&gt;Sadly all of these devices only gave (and still give) access only to the DS hardware, not the new DSi features. Although there would later be exploits to get small programs running in DSi mode, at the end of the year we are still in the dark when it comes to details about the DSi hardware from an unofficial developer's point of view. This means that there is still no solution for connecting to the net with the DSi's faster network hardware, nor can we use secure WPA Wifi connections, nor can we slurp out all those photos and all that data that is stored on the built in RAM.&lt;/p&gt;&lt;p&gt;&lt;img alt="Twitter" src="http://imgur.com/ieGe6.png" /&gt;&lt;/p&gt;&lt;p&gt;Homebrew out this month included an update to &lt;a href="http://twitter.com/gentakojima"&gt;@gentakojima&lt;/a&gt;'s &lt;a href="http://www.tehskeen.com/viewarticle.php?articleid=3789"&gt;DSTwitter app&lt;/a&gt;. Pretty cool, even if the jury is still out on the usefulness of Twitter. You should follow me on twitter &lt;a href="http://twitter.com/richq"&gt;here&lt;/a&gt;, if that's your bag. I don't say much though, mostly just complain about Dr Who. Don't try and visit gentakojima's old Acdrtux site though, you just get Rick Roll'd.&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.dev-fr.org/index.php/topic,4004.0.html"&gt;DSPack&lt;/a&gt; added to the growing list of arcade emulators released this year, this time emulating Pac-Man and derivatives from the MAME collection. Finding ROMS for these emulators proved to be a bit trickier - not everyone has the, er, technical know-how to back up the collection of arcade games that they keep in their spare room. Yes. Ahem.&lt;/p&gt;&lt;p&gt;The emulation is excellent. That just leaves the limitations of the DS screen to contend with. It would've been nice if there had been an option to keep the sceen fixed in one spot, losing the top banner that takes up about a third of the top screen. As it is, not all of the screen fits on at once, and the play area scrolls to show Pac on the bottom screen at all times. I suppose a fixed screen would have meant the yellow one traversing the area in the middle of the 2 screens, which could have been quite confusing. Oh well. Good games, great emulator, worth checking out.&lt;/p&gt;&lt;h2&gt;May&lt;/h2&gt;&lt;p&gt;In May we got another update to devkitARM and its support libraries. There were no major additions this time round, but it was a solid maintenance release.&lt;/p&gt;&lt;p&gt;Powder had its &lt;a href="http://en.wikipedia.org/wiki/111_%28number%29#Nelson"&gt;Nelson&lt;/a&gt; release in May. And I suppose it was quite unlucky for us Powder fans; we wouldn't get another update until well into November.&lt;/p&gt;&lt;h2&gt;June&lt;/h2&gt;&lt;p&gt;After more than 6 months of silence, &lt;a href="http://freescifistories.wordpress.com/category/nintendo-ds/"&gt;Wee Basic&lt;/a&gt; made a come back. This novel application lets you code in BASIC directly on your DS. Perhaps it is about as far from the cutting edge of computer science as you can get, but I found it a nostalgic amusement. You know what would make something like this even cooler? Auto-completion and some online help. You should see my .vim directory though, so perhaps my expectations are a bit far fetched.&lt;/p&gt;&lt;p&gt;&lt;img alt="Atmos" src="http://imgur.com/UKt45.png" /&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.pdroms.de/files/2181/"&gt;Atmos&lt;/a&gt; was another cool-looking DS puzzle game that came out in June. The initial releases were multiplayer only, but the idea seemed original. The game could be described as a cross between othello and one of those colour matching games like Columns. Sadly the only record of its existence now is that page on PDRoms. Let this be a lesson for would-be coders: whatever you do, don't just post your game exclusively to some random forum! Especially if it requires log-in to download the title. You have probably spent a great deal of time writing your game, the least you can do is to take a few more minutes to create a more permanent home for your work on &lt;a href="http://sites.google.com/"&gt;Google Sites&lt;/a&gt; or some other free web hosting service (yeah, like Geocities. Ha.)&lt;/p&gt;&lt;p&gt;Speaking of downloads, &lt;a href="http://gameup.supercard.fr/index.php?lang=eng"&gt;GameUp&lt;/a&gt; looks like a really great way to keep up to date with the latest DS homebrew. I've only discovered it recently, and it hasn't been updated since July, but the idea is a winner. It's a front end to a web site where you can download and rate homebrew titles, so no need to faff around with flash cards and swapping them between the PC and the DS. A bit like an unofficial "AppStore" application, I suppose. The only real problem is that it depends on the GameUp website being active and people updating the database with new homebrew. Sadly it seems that new programs have not been posted for quite some time.&lt;/p&gt;&lt;h2&gt;July&lt;/h2&gt;&lt;p&gt;The &lt;a href="http://www.wehackdsi.com/2009/07/dsi-mode-homebrew.html"&gt;first rumours of DSi homebrew&lt;/a&gt; started to appear this month. It would be a while before more details were released, and all we got to see at this point was a video. Skeptics everywhere battled wits on the YouTube comments thread.&lt;/p&gt;&lt;p&gt;&lt;img alt="Warhawk" src="http://imgur.com/OhIJE.png" title="Warhawk by headsoft" /&gt;&lt;/p&gt;&lt;p&gt;If we want to talking about games we could actually play, then the amazingly good &lt;a href="http://headsoft.com.au/index.php?category=warhawk"&gt;Warhawk&lt;/a&gt; was finally released in July. Based on the C64 classic and coded entirely in ARM assembly, it was one of the best pieces of homebrew to come out all year. In fact for my money it was only topped by the group's second release later in the year...&lt;/p&gt;&lt;p&gt;&lt;img alt="Line Wars" src="http://imgur.com/NG9Le.png" title="Line Wars DS" /&gt;&lt;/p&gt;&lt;p&gt;The release of &lt;a href="http://linewars.patrickaalto.com/"&gt;Line Wars DS&lt;/a&gt; added to the underrepresented 3D space game genre on the DS. Its author, Patrick Aalto, ported the game from the original x86 assembly code to C for the DS. He cheated by having the original source code, I bet ;-) The fact that he wrote that original code is not to be sneezed at, of course. Line Wars runs at a really smooth frame rate, making use of the DS's hardware 3D and lighting effects. Unlike Elite, in LW you take part in single "missions" that get progressively more difficult, with the focus here being on the action, the shootin' and the blastin'. Well worth the download either way.&lt;/p&gt;&lt;h2&gt;August&lt;/h2&gt;&lt;p&gt;&lt;img alt="facebook DSi" src="http://imgur.com/GHNnm.jpg" title="Facebook logo" /&gt;&lt;/p&gt;&lt;p&gt;One of the highlights of the month of August, at least for us DSi owners, was the release of a new system menu. This upgrade, version 1.4, added &lt;a href="http://facebook.com/" title="As if you didn't know the url"&gt;Facebook&lt;/a&gt; support to the built in camera program. By connecting to a local Wifi network and then entering your Facebook account details to the DSi, you could upload any of the really terrible quality photos you'd taken. The DSi browser was also updated to a new minor version. Though details on the exact changes are non-existent, I suspect one of the changes was to make logging in on web-sites a lot more difficult; the updated browser seems to forget cookies almost instantly.&lt;/p&gt;&lt;p&gt;However, this was not the most dramatic feature of System Menu 1.4. Oh no. What really caught the eye was the new "blocks all DSi flash cards" feature that nobody asked for. And so began the next step in the cat-and-mouse game that card manufacturers and Nintendo were playing. Thanks to good design and forethought most of these next-gen flash cards had a way to update the firmware. They managed to patch their way out of the 1.4 straight jacket within a few days, but it did look pretty bleak for a while back there.&lt;/p&gt;&lt;p&gt;Other news in August came from WinterMute, who released his &lt;a href="http://github.com/WinterMute/ClassicHack/"&gt;hack for DSi Classic Word Games&lt;/a&gt;. This hack allows a small amount of assembly code to run on the DSi in actual DSi mode. It exploits an error in the save game handling of a commercial title, which means that its viability for running DSi code in a more mainstream way is a tad limited - you have to own Classic Word Games and the hardware to upload save games to the cartridge to make use of the exploit. Cool nonetheless.&lt;/p&gt;&lt;p&gt;Regular DS homebrew releases continued in August. There were quite a few demos and unfinished early releases of games, but also updates to some old favourites, including &lt;a href="http://n00bey.bplaced.net/?cat=4"&gt;DronDS&lt;/a&gt;. DronDS is a Tron light-cycles game that takes place in full 3D (on a 2D plane of course, you can't start riding up the walls). In the latest releases you can even play online against other Dronners. I've never coincided with anyone, but then I'm antisocial. If you have friends on IRC or even on Twitter (hey look, a use for Twitter!) then maybe you could gather a posse and have a game.&lt;/p&gt;&lt;h2&gt;September&lt;/h2&gt;&lt;p&gt;From the makers of Warhawk, a sneak preview video of another remake "Manic Miner - The Lost Levels" had us pining for its release back in September.&lt;/p&gt;&lt;p&gt;&lt;a href="http://nanolua.u7n.org/nanolua/indexe.php?page=downloadNanoLua"&gt;Nano Lua&lt;/a&gt; caused a flurry of activity as well this month. Lua is a great little language (even if it does have its warts. 1-indexed arrays, I am looking at you) and Nano Lua enabled people to write games for their DSes without getting their hand dirty with C or C++. I've not had chance to check Nano Lua out in detail - it seems to be a bit lacking on documentation, natch - but people have released more things with it than with the previous DS-Lua efforts, so it must be doing something right.&lt;/p&gt;&lt;h2&gt;October&lt;/h2&gt;&lt;p&gt;&lt;img alt="Blockman Gets Screenshot" src="http://imgur.com/IGhXr.png" title="Blockman Gets" /&gt;&lt;/p&gt;&lt;p&gt;The floodgates opened again in October.  &lt;a href="http://agameaweek.com/?p=248"&gt;Blockman Gets&lt;/a&gt;, a pacman/puzzle game, combined 2 genres (classic arcade and puzzle) to produce an infuriatingly difficult mind bender. No ghosts on the first level, and yet it's &lt;em&gt;more&lt;/em&gt; difficult than the original!&lt;/p&gt;&lt;p&gt;For novelty value, &lt;a href="http://www.nintendomax.com/index.php?topic_id=10617&amp;amp;format=news"&gt;Mario Bros Lemmings DS&lt;/a&gt; was pretty hard to beat. These are Mario themed levels for Lemmings DS, complete with Koopers, Goombas, Bowser, and Mario, all rendered in their full 8-bit NES glory. I suspect some sort of automatic process was used, as the levels don't really stand out as brilliant Lemmings puzzles (too many ∞ abilities, some levels cause the game to hang, unbalanced requirements), but the amusement factor is high and all the SMB1 levels seem to be in there.&lt;/p&gt;&lt;p&gt;Now I'm not a big fan of Pang, but &lt;a href="http://www.pdroms.de/news/20082/"&gt;Pang DS&lt;/a&gt; does a good job of emulating the arcade game. Once more, make sure you only use carefully created backups of those Pang bootleg arcade boards you have next to the washing machine. Don't just Google "Pang MAME ROMs" or anything, okay?&lt;/p&gt;&lt;p&gt;GBA veteran coder FluBBa ported his SEGA Master System/Game Gear emulator over to the DS. It's called &lt;a href="http://www.ndsretro.com/"&gt;S8DS&lt;/a&gt; and is very good, as you might expect. The DS has a large enough screen that the squashed graphics from the GBA version are a thing of the past. S8DS uses the usual DLDI/libFAT features, so there's no need to inject the MS/GG games into the NDS ROM - you can just read them from your flash card. There are loads of great MS games out there, which of course you er, back up from the original cartridges you own (this is getting silly). I spent many a happy hour wasting batteries playing &lt;a href="http://www.mobygames.com/game/sega-master-system/fantastic-adventures-of-dizzy/screenshots"&gt;Fantastic Dizzy&lt;/a&gt; on the Game Gear.&lt;/p&gt;&lt;p&gt;&lt;img alt="Red gameplay" src="http://img136.imageshack.us/img136/6800/redgameplay.jpg" /&gt;&lt;/p&gt;&lt;p&gt;I didn't see many people mention &lt;a href="http://forum.gbadev.org/viewtopic.php?t=16925"&gt;Red&lt;/a&gt; when it came out in October, but it is really good. Although it is a quasi-official conversion of a Flash game, it feels at home on the DS. Using the stylus, you control the defences of a base at the bottom of the screen. This base appears to be some sort of last stand against an onslaught of meteors on a red planet somewhere. Story be damned! The base is armed with a cannon, and by shooting balls that look like a deadly paper/spit combination at the oncoming rocks, you can deflect them away from the base. By charging up the cannon, you can shoot bigger wads at the meteors, giving you a better chance of deflecting them. There are some power-ups in there as well to mix things up a bit. It plays like a faster, more &lt;em&gt;physicsy&lt;/em&gt; version of Missile Command. You have no excuses, go and play this one.&lt;/p&gt;&lt;p&gt;&lt;img alt="Manic Miner in the Lost Level Bouncy-Bouncy" src="http://imgur.com/CYyCn.png" title="Manic Miner in the Lost Levels" /&gt;&lt;/p&gt;&lt;p&gt;Last, but by no means least, is the epic &lt;a href="http://headsoft.com.au/index.php?category=mmll"&gt;Manic Miner in the Lost Levels&lt;/a&gt;. Created by the same chaps that created Warhawk earlier in the year, together with input from Amiga Power's Stuart Campbell, MMLL gathers all the best bits from the myriad of Manic Miner ports and packages it up with all the pazzazz of a first-party Nintendo game. You get first class graphics and sound, snazzy menus, unlockable bonuses, hidden levels, high scores, time attacks, historical notes, insider jokes, 80s film references, sly digs at the C64... it's all there. It is impossible to imagine how they could have done more justice to good ol' miner Willy. And I'm not even especially fond of the original Manic Miner! (&lt;em&gt;ducks the pick-axe thrown from the back row&lt;/em&gt;), but the way it is presented here, with its skippable levels and modern day graphics make it much more accessible. All this without compromising the classic pixel-perfect, difficulty-turned-up-to-11 gameplay. In a word: "stunning".&lt;/p&gt;&lt;h2&gt;November&lt;/h2&gt;&lt;p&gt;&lt;img alt="Woopsi 0.43" src="http://imgur.com/vQSf9.png" title="Woopsi 0.43" /&gt;&lt;/p&gt;&lt;p&gt;&lt;a href="http://www.sourceforge.net/projects/woopsi"&gt;Woopsi&lt;/a&gt; had many updates throughout the year, and it's good to see Ant updating his GUI library. I still haven't completely ruled out a port to the Woopsi library for Bunjalloo - maybe in 2010? For me all it's really lacking is some way to support UTF-8, which is a tricky problem when you don't want to support STL collections.&lt;/p&gt;&lt;p&gt;Another teaser was released from the team behind the Manic Miner remake in November. This time they are were going to have a crack at The Detective. I'll admit now that I had not heard of the game before, and that despite being an ex-Commodore 64 owner. Still, with their pedigree even if the original was pants I'm looking forward to this one.&lt;/p&gt;&lt;p&gt;&lt;img alt="Munky Blocks screenshot" src="http://imgur.com/uLXnC.png" title="Munky Blocks" /&gt;&lt;/p&gt;&lt;p&gt;From the creator of retro-platform/puzzler Platdude, &lt;a href="http://socoder.net/jstuff/GameList.php?ShowJust=172"&gt;Munky Blocks&lt;/a&gt; also came out in November. I would describe the gameplay as somewhere between Sokoban and Columns, with a bit of Yoshi thrown in. Though the gameplay is simple to grasp and has only a few concepts, the levels start to get fiendish quite quickly. Viewed in side-on 2D, you control a Monkey/Cat thing that can swallow blocks and climb up platforms. The idea is to place like-coloured blocks next to one another in groups of 3 or more so that they disappear. When you have swallowed a block, you can then walk around with it in your gut, but you can only climb up a single floor level when you're this full. After regurgitating the block you can move freely again. Later levels mix things up with switches that open doors, keys you can collect to unlock other doors, and so on. A very good game, and strangely claustrophobic I found.&lt;/p&gt;&lt;p&gt;In other, non-playable news, &lt;a href="http://www.wehackdsi.com/2009/11/first-dsi-mode-game.html"&gt;the first DSi-mode game&lt;/a&gt; was announced, although it is only in &lt;a href="http://www.youtube.com/watch?v=HCq7CUVfWAA"&gt;video form&lt;/a&gt;. Perhaps 2010 will see this taken to the next level? Let's hope so.&lt;/p&gt;&lt;p&gt;A new emulator was announced by Patrick Aalto (of Line Wars fame) back at the start of November. This time the emulation target was the x86! Specifically, the 80286 with MCGA graphics and SoundBlaster audio. Quite an achievement. Full details of &lt;a href="http://dsx86.patrickaalto.com/"&gt;DSx86 are on Patrick's site&lt;/a&gt;. The current tech demo includes the DOS version of Line Wars, though his blog also shows screenshots of other programs and games running, including SYSINFO and Paratrooper. Hopefully 2010 will see more improvements and news.&lt;/p&gt;&lt;h2&gt;December&lt;/h2&gt;&lt;p&gt;I'm writing this in December. Past tense confusion overload.&lt;/p&gt;&lt;p&gt;Another great puzzle game appeared at the start of December, called &lt;a href="http://www.cogitods.fr/"&gt;Cogito&lt;/a&gt;. This has nothing to do with &lt;a href="http://en.wikipedia.org/wiki/Cogito_%28software%29"&gt;version control&lt;/a&gt;, but is a tricky sliding block puzzle game. It is somewhere between a Rubik's cube and those &lt;a href="http://en.wikipedia.org/wiki/Sliding_puzzle"&gt;plastic sliding block puzzles&lt;/a&gt;. You have to align rows of coloured blocks on the bottom screen in the way that they are shown on the top screen. The trick is that you can only move entire rows at once. It is simple, but much more complicated to do than you first expect. Another great game.&lt;/p&gt;&lt;p&gt;&lt;a href="http://sacredpotion.blogspot.com/"&gt;Red Temple&lt;/a&gt; probably came out at the end of November, but it got renamed and had a new release right at the start of December too, so here it is. Besides, it's my blog so I'll put it where I like :-) Now I really quite liked Red Temple. The game starts off with a few effects on the start screen, then you are taken away to the world overview screen to select your start level. Once chosen, the game proper starts off. It is a straight forward collect-'em-up where you play a snake/worm thing that goes around eating a load of fruit. As snakes and worms often do, I imagine.&lt;/p&gt;&lt;p&gt;The art work is a colourful enough tile-based 2D affair (described rather unfairly as "crap" by the author, they aren't that bad! At least they are original, which counts for a lot IMO), and the sounds are made up of some quality coder-generated-sounds and grunts. At least that's what it sounded like - the "level win" and "you're dead" sounds being especially amusing. It has a nice Amiga PD game feel to it, the sounds reminding me of the credits files that occasionally described how the authors went about making each sound ("falling in water - dropping an orange in a mug of coffee", that sort of thing). Not bad, not bad at all. There are a few &lt;a href="http://www.youtube.com/watch?v=A4EJkUONNAQ"&gt;videos&lt;/a&gt; &lt;a href="http://www.youtube.com/watch?v=v44hZGboplw"&gt;on&lt;/a&gt; &lt;a href="http://www.youtube.com/watch?v=IiOxg1ug0jY"&gt;youtube&lt;/a&gt; if you don't fancy downloading the game to try it. But you should.&lt;/p&gt;&lt;p&gt;&lt;img alt="Ripholes in Rubbish" src="http://imgur.com/v5hWg.jpg" /&gt;&lt;/p&gt;&lt;p&gt;The great-looking &lt;a href="http://www.ripholes.com/index.php"&gt;Ripholes in Rubbish&lt;/a&gt; was a surprise release. It came out of nowhere pretty much completed. The game is a simple platform game, with an added twist that on some screens you can interact with the background. The "rip" in the name comes from this idea - you can rip holes in the background and go through to the other side. The later levels use this technique as part of the puzzles to get past otherwise impossible sections. Other puzzles involve capturing and moving clouds. The graphics use a distinctive hand-drawn look and the sound is varied and original. Sadly the game has a few bugs that cause it to either hang or do strange things, such as all objects on levels disappearing suddenly. Still, there have been further updates improving the stability, and as it is the game is a playable work of art.&lt;/p&gt;&lt;p&gt;&lt;img alt="The Detective Game" src="http://imgur.com/ZPYMH.png" title="The Detective Game" /&gt;&lt;/p&gt;&lt;p&gt;The last big release of the year was headsoft's &lt;a href="http://headsoft.com.au/index.php?category=tdg"&gt;The Detective Game&lt;/a&gt;. I'd not even heard of the original game, so this was something of an unknown. The graphics are great (Cook's bouncing chest aside) and the game is classic 8-bit "WTF do I have to do?!". It is an admirable remake. Sadly without the heritage of Manic Miner it doesn't have that elusive &lt;em&gt;wow-factor&lt;/em&gt;, as they say on TV. I must say that Ben (AKA headcaze) has been great in fixing a few glitches that made the game unplayable on the EZ Flash cartridges, so extra kudos there.&lt;/p&gt;&lt;h2&gt;Outro&lt;/h2&gt;&lt;p&gt;Barring any last minute surprises, my game of the year award would go to &lt;em&gt;Manic Miner in the Lost Levels&lt;/em&gt;. Not an easy choice, there have been a lot of fine chunks of code running on my DS this year.&lt;/p&gt;&lt;p&gt;I hope the 2010 has as good a crop of games as this year has had. I know a lot of DS coders bemoan the death of the system, saying that everyone has moved on to smart phones, but I'm sure the ol' DS still has a few years left in her yet. Happy holidays, and happy homebrewing!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-6010832401884849064?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/6010832401884849064/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2009/12/unofficial-2009-in-review.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/6010832401884849064'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/6010832401884849064'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2009/12/unofficial-2009-in-review.html' title='Unofficial 2009 in Review'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-9207131429576255761</id><published>2009-12-23T22:16:00.000+01:00</published><updated>2011-04-30T20:31:49.953+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DS'/><category scheme='http://www.blogger.com/atom/ns#' term='Bunjalloo'/><title type='text'>Bunjalloo release v0.8</title><content type='html'>&lt;p&gt;I've just uploaded a new release of Bunjalloo. This contains all the performance improvements I've been working on recently as well as a few other changes. Full details are in the &lt;a href="http://code.google.com/p/quirkysoft/wiki/BunjallooChangelog"&gt;changelog&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;One of the changes is a fix to the updater. Sadly I broke it in the last release. This means you will have to update manually by downloading the zip file and unpacking it to your flash card. I've added some automated tests during this release to make sure I don't mess it up again.&lt;/p&gt;&lt;p&gt;You can download the latest version &lt;a href="http://code.google.com/p/quirkysoft/downloads/detail?name=bunjalloo-0.8.zip"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-9207131429576255761?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/9207131429576255761/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2009/12/bunjalloo-release-v08.html#comment-form' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/9207131429576255761'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/9207131429576255761'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2009/12/bunjalloo-release-v08.html' title='Bunjalloo release v0.8'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-3154189616689193802</id><published>2009-11-19T19:00:00.000+01:00</published><updated>2009-11-19T19:00:02.993+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='HOWTO'/><title type='text'>Setting environment variables in Java</title><content type='html'>&lt;p&gt;Have you ever noticed that the &lt;a href="http://java.sun.com/javase/6/docs/api/java/lang/System.html"&gt;Java System class&lt;/a&gt; doesn't let you set environment variables? You can retrieve them using &lt;code&gt;getenv()&lt;/code&gt; but there is no equivalent &lt;code&gt;setenv()&lt;/code&gt; function.&lt;/p&gt;&lt;p&gt;First off, what is the environment? The manual entry for &lt;a href="http://www.kernel.org/doc/man-pages/online/pages/man7/environ.7.html"&gt;environ(7)&lt;/a&gt; describes the environment as:&lt;br /&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;an array of strings [that] have the form &lt;code&gt;name=value&lt;/code&gt;. Common examples are USER (the name of the logged-in user), HOME (A user's login directory) and PATH (the sequence of directory prefixes that many programs use to search for a file known by an incomplete pathname).&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;It turns out that when you start up the &lt;a href="http://en.wikipedia.org/wiki/Java_Virtual_Machine"&gt;JVM&lt;/a&gt;, it copies this environment into its own &lt;a href="http://java.sun.com/javase/6/docs/api/java/util/Map.html"&gt;Map&lt;/a&gt; of Strings. The actual container it uses is an &lt;a href="http://java.sun.com/javase/6/docs/api/java/util/Collections.html#unmodifiableMap%28java.util.Map%29"&gt;unmodifiable map&lt;/a&gt;, probably to be extra safe.&lt;/p&gt;&lt;p&gt;So in a running Java application we have 2 environments: the JVM copy that you can read via &lt;code&gt;System.getenv()&lt;/code&gt; and the underlying environment that lives in the C library.&lt;/p&gt;&lt;p&gt;If we want to change the JVM's copy, we can do so using &lt;a href="http://java.sun.com/javase/6/docs/api/java/lang/reflect/package-summary.html#package_description"&gt;reflection&lt;/a&gt;. Or at least we should be able to, just as long as our code is not running in a sandbox. In that case you'd be right out of luck. Anyway, the code to fetch a modifiable copy of the environment could look like this:&lt;/p&gt;&lt;pre&gt;&lt;div style="background-color: rgb(0, 0, 0); color: rgb(255, 255, 255); font-weight: bold;"&gt;&lt;span style="font-family:monospace;"&gt;&lt;span style="color:#8080ff;"&gt;&lt;b&gt;import&lt;/b&gt;&lt;/span&gt; java.lang.reflect.Field;&lt;br /&gt;&lt;span style="color:#8080ff;"&gt;&lt;b&gt;import&lt;/b&gt;&lt;/span&gt; java.util.Map;&lt;br /&gt;&lt;span style="color:#8080ff;"&gt;&lt;b&gt;import&lt;/b&gt;&lt;/span&gt; java.util.HashMap;&lt;br /&gt;&lt;span style="color:#00ff00;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt; Environment {&lt;br /&gt;  &lt;span style="color:#8080ff;"&gt;&lt;b&gt;@SuppressWarnings&lt;/b&gt;&lt;/span&gt;(&lt;span style="color:#ff40ff;"&gt;&lt;b&gt;"unchecked"&lt;/b&gt;&lt;/span&gt;)&lt;br /&gt;  &lt;span style="color:#00ff00;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt; Map&amp;lt;String, String&amp;gt; getenv() {&lt;br /&gt;    &lt;span style="color:#ffff00;"&gt;&lt;b&gt;try&lt;/b&gt;&lt;/span&gt; {&lt;br /&gt;      Map&amp;lt;String, String&amp;gt; unomdifiable = System.getenv();&lt;br /&gt;      Class&amp;lt;?&amp;gt; cu = unomdifiable.getClass();&lt;br /&gt;      Field m = cu.getDeclaredField(&lt;span style="color:#ff40ff;"&gt;&lt;b&gt;"m"&lt;/b&gt;&lt;/span&gt;);&lt;br /&gt;      m.setAccessible(&lt;span style="color:#ff40ff;"&gt;&lt;b&gt;true&lt;/b&gt;&lt;/span&gt;);&lt;br /&gt;      &lt;span style="color:#ffff00;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; (Map&amp;lt;String, String&amp;gt;)m.get(unomdifiable);&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color:#ffff00;"&gt;&lt;b&gt;catch&lt;/b&gt;&lt;/span&gt; (Exception e) { }&lt;br /&gt;    &lt;span style="color:#ffff00;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#ffff00;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt; HashMap&amp;lt;String, String&amp;gt;();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;p&gt;Calling &lt;code&gt;System.getenv()&lt;/code&gt; returns us an UnmodifiableMap of Strings containing the copy of the C environment. In order to get to its squishy modifiable heart, we access the &lt;code&gt;m&lt;/code&gt; member variable which &lt;em&gt;is&lt;/em&gt; modifiable. This is because UnmodifiableMap uses the proxy pattern - it implements the Map interface, but delegates all calls for retrieving values off to a member variable Map that contains the values and does all the real work. The set methods throw UnsupportedOperation exceptions. By accessing that &lt;code&gt;m&lt;/code&gt; we can change the JVM's copy of the environment from under its very nose. Heh heh.&lt;/p&gt;&lt;p&gt;Not so fast. On Windows this is slightly different. The environment there contains a different Map that allows you to search for variables in a case-insensitive way. &lt;code&gt;System.getenv()&lt;/code&gt; returns one Map (the unmodifiable one, same as Linux) whereas &lt;code&gt;System.getenv("value")&lt;/code&gt; looks up the value in the case-insensitive Map. In order to create a robust update-env implementation we should update &lt;em&gt;both&lt;/em&gt; of these Maps. This needs some more reflection to get the Map in question out of the ProcessEnvironment, probably like this:&lt;/p&gt;&lt;pre&gt;&lt;div style="background-color: rgb(0, 0, 0); color: rgb(255, 255, 255); font-weight: bold;"&gt;&lt;span style="font-family:monospace;"&gt;&lt;span style="color:#8080ff;"&gt;&lt;b&gt;@SuppressWarnings&lt;/b&gt;&lt;/span&gt;(&lt;span style="color:#ff40ff;"&gt;&lt;b&gt;"unchecked"&lt;/b&gt;&lt;/span&gt;)&lt;br /&gt;&lt;span style="color:#00ff00;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt; Map&amp;lt;String, String&amp;gt; getwinenv() {&lt;br /&gt;  &lt;span style="color:#ffff00;"&gt;&lt;b&gt;try&lt;/b&gt;&lt;/span&gt; {&lt;br /&gt;    Class&amp;lt;?&amp;gt; sc = Class.forName(&lt;span style="color:#ff40ff;"&gt;&lt;b&gt;"java.lang.ProcessEnvironment"&lt;/b&gt;&lt;/span&gt;);&lt;br /&gt;    Field caseinsensitive =&lt;br /&gt;      sc.getDeclaredField(&lt;span style="color:#ff40ff;"&gt;&lt;b&gt;"theCaseInsensitiveEnvironment"&lt;/b&gt;&lt;/span&gt;);&lt;br /&gt;    caseinsensitive.setAccessible(&lt;span style="color:#ff40ff;"&gt;&lt;b&gt;true&lt;/b&gt;&lt;/span&gt;);&lt;br /&gt;    &lt;span style="color:#ffff00;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; (Map&amp;lt;String, String&amp;gt;)caseinsensitive.get(&lt;span style="color:#ff40ff;"&gt;&lt;b&gt;null&lt;/b&gt;&lt;/span&gt;);&lt;br /&gt;  }&lt;br /&gt;  &lt;span style="color:#ffff00;"&gt;&lt;b&gt;catch&lt;/b&gt;&lt;/span&gt; (Exception e) {&lt;br /&gt;  }&lt;br /&gt;  &lt;span style="color:#ffff00;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#ffff00;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt; HashMap&amp;lt;String, String&amp;gt;();&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;p&gt;An example of how this may be useful without going any further would be if you have the DISPLAY environment variable set but you cannot use it (for example you connect via ssh -X, start a background process, then disconnect closing the X session connection too). In this situation even if you tell java.awt to run headless it may see that DISPLAY is set, try to use it and throw an exception. By clearing DISPLAY we can use headless methods to create off-screen graphics, to send them to a printer or to save a fake screen shot to file maybe for automated testing.&lt;/p&gt;&lt;p&gt;However this is not enough to affect the environment for any child processes. They will still only see the original, unmodified environment that the JVM craftily made a copy of at start-up. The comment in &lt;code&gt;java.lang.ProcessEnvironment&lt;/code&gt; &lt;a href="http://www.google.com/codesearch/p?hl=en&amp;amp;sa=N&amp;amp;cd=1&amp;amp;ct=rc#BvPXXZ4E3f8/src/solaris/classes/java/lang/ProcessEnvironment.java&amp;amp;q=%22We%20cache%20the%20C%20environment%22%20lang:java"&gt;says it all&lt;/a&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;// We cache the C environment.  This means that subsequent calls&lt;br /&gt;// to putenv/setenv from C will not be visible from Java code.&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Grrrr! By far the easiest approach here is to just use the &lt;a href="http://java.sun.com/javase/7/docs/api/java/lang/ProcessBuilder.html"&gt;ProcessBuilder&lt;/a&gt;. This lets you change the environment before launching the child process. Win. End of post.&lt;/p&gt;&lt;p&gt;No! I really want to change the underlying C environment for no good reason!&lt;/p&gt;&lt;p&gt;In order to change &lt;em&gt;that&lt;/em&gt; we have to resort to either &lt;a href="http://java.sun.com/docs/books/jni/html/jniTOC.html"&gt;JNI&lt;/a&gt; or &lt;a href="https://jna.dev.java.net/"&gt;JNA&lt;/a&gt;. Lets start with JNA, it is the easier of the two and needs less tools. Just download a jar file and with the Java Compiler you're good to hack.&lt;/p&gt;&lt;p&gt;In case you have not heard of it, JNA is to Java what ctypes is to Python - a byte-code library that lets you open native, compiled, shared libraries and call the C routines within directly from Java code. JNI on the other hand requires you to create C++ functions, compile these, then call them from Java.&lt;/p&gt;&lt;p&gt;Armed with the JNA classes we can wrap the standard &lt;code&gt;setenv()&lt;/code&gt; and &lt;code&gt;unsetenv()&lt;/code&gt; functions from the C library.&lt;/p&gt;&lt;pre&gt;&lt;div style="background-color: rgb(0, 0, 0); color: rgb(255, 255, 255); font-weight: bold;"&gt;&lt;span style="font-family:monospace;"&gt;&lt;span style="color:#8080ff;"&gt;&lt;b&gt;import&lt;/b&gt;&lt;/span&gt; com.sun.jna.Library;&lt;br /&gt;&lt;span style="color:#8080ff;"&gt;&lt;b&gt;import&lt;/b&gt;&lt;/span&gt; com.sun.jna.Native;&lt;br /&gt;&lt;span style="color:#00ff00;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt; Environment {&lt;br /&gt;  &lt;span style="color:#00ff00;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;interface&lt;/b&gt;&lt;/span&gt; LibC &lt;span style="color:#00ff00;"&gt;&lt;b&gt;extends&lt;/b&gt;&lt;/span&gt; Library {&lt;br /&gt;    &lt;span style="color:#00ff00;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; setenv(String name, String value, &lt;span style="color:#00ff00;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; overwrite);&lt;br /&gt;    &lt;span style="color:#00ff00;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; unsetenv(String name);&lt;br /&gt;  }&lt;br /&gt;  &lt;span style="color:#00ff00;"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt; LibC libc = (LibC) Native.loadLibrary(&lt;span style="color:#ff40ff;"&gt;&lt;b&gt;"c"&lt;/b&gt;&lt;/span&gt;, LibC.&lt;span style="color:#00ff00;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;);&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;p&gt;That works fine on Linux, but on Windows we have to take a different approach. There neither &lt;code&gt;setenv&lt;/code&gt; nor &lt;code&gt;unsetenv&lt;/code&gt; exist, instead we have to call &lt;code&gt;_putenv&lt;/code&gt;. This function accepts a "name=value" string, and if we pass "name=" we can delete a variable from the environment. Unfortunately this multi-platform approach messes up the code a fair amount. Here is one way to do it:&lt;/p&gt;&lt;pre&gt;&lt;div style="background-color: rgb(0, 0, 0); color: rgb(255, 255, 255); font-weight: bold;"&gt;&lt;span style="font-family:monospace;"&gt;&lt;span style="color:#00ffff;"&gt;&lt;b&gt;// Inside the Environment class...&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#00ff00;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;interface&lt;/b&gt;&lt;/span&gt; WinLibC &lt;span style="color:#00ff00;"&gt;&lt;b&gt;extends&lt;/b&gt;&lt;/span&gt; Library {&lt;br /&gt;  &lt;span style="color:#00ff00;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; _putenv(String name);&lt;br /&gt;}&lt;br /&gt;&lt;span style="color:#00ff00;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;interface&lt;/b&gt;&lt;/span&gt; LinuxLibC &lt;span style="color:#00ff00;"&gt;&lt;b&gt;extends&lt;/b&gt;&lt;/span&gt; Library {&lt;br /&gt;  &lt;span style="color:#00ff00;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; setenv(String name, String value, &lt;span style="color:#00ff00;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; overwrite);&lt;br /&gt;  &lt;span style="color:#00ff00;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; unsetenv(String name);&lt;br /&gt;}&lt;br /&gt;&lt;span style="color:#00ff00;"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt; POSIX {&lt;br /&gt;  &lt;span style="color:#00ff00;"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt; Object libc;&lt;br /&gt;  &lt;span style="color:#00ff00;"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt; {&lt;br /&gt;    &lt;span style="color:#ffff00;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (System.getProperty(&lt;span style="color:#ff40ff;"&gt;&lt;b&gt;"os.name"&lt;/b&gt;&lt;/span&gt;).equals(&lt;span style="color:#ff40ff;"&gt;&lt;b&gt;"Linux"&lt;/b&gt;&lt;/span&gt;)) {&lt;br /&gt;      libc = Native.loadLibrary(&lt;span style="color:#ff40ff;"&gt;&lt;b&gt;"c"&lt;/b&gt;&lt;/span&gt;, LinuxLibC.&lt;span style="color:#00ff00;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;);&lt;br /&gt;    } &lt;span style="color:#ffff00;"&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt; {&lt;br /&gt;      libc = Native.loadLibrary(&lt;span style="color:#ff40ff;"&gt;&lt;b&gt;"msvcrt"&lt;/b&gt;&lt;/span&gt;, WinLibC.&lt;span style="color:#00ff00;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt;);&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style="color:#00ff00;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; setenv(String name, String value, &lt;span style="color:#00ff00;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; overwrite) {&lt;br /&gt;    &lt;span style="color:#ffff00;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (libc &lt;span style="color:#ffff00;"&gt;&lt;b&gt;instanceof&lt;/b&gt;&lt;/span&gt; LinuxLibC) {&lt;br /&gt;      &lt;span style="color:#ffff00;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; ((LinuxLibC)libc).setenv(name, value, overwrite);&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color:#ffff00;"&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt; {&lt;br /&gt;      &lt;span style="color:#ffff00;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; ((WinLibC)libc)._putenv(name + &lt;span style="color:#ff40ff;"&gt;&lt;b&gt;"="&lt;/b&gt;&lt;/span&gt; + value);&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style="color:#00ff00;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; unsetenv(String name) {&lt;br /&gt;    &lt;span style="color:#ffff00;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (libc &lt;span style="color:#ffff00;"&gt;&lt;b&gt;instanceof&lt;/b&gt;&lt;/span&gt; LinuxLibC) {&lt;br /&gt;      &lt;span style="color:#ffff00;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; ((LinuxLibC)libc).unsetenv(name);&lt;br /&gt;    }&lt;br /&gt;    &lt;span style="color:#ffff00;"&gt;&lt;b&gt;else&lt;/b&gt;&lt;/span&gt; {&lt;br /&gt;      &lt;span style="color:#ffff00;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; ((WinLibC)libc)._putenv(name + &lt;span style="color:#ff40ff;"&gt;&lt;b&gt;"="&lt;/b&gt;&lt;/span&gt;);&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#00ff00;"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt; POSIX libc = &lt;span style="color:#ffff00;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt; POSIX();&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;p&gt;Here we use JNA to load either libc on Linux or the msvcrt DLL (which contains &lt;code&gt;_putenv&lt;/code&gt;) on Windows. There are ugly casts in there, and other OSes are left as an exercise to the reader, but this means that I can call &lt;code&gt;POSIX.setenv()&lt;/code&gt; or &lt;code&gt;unsetenv()&lt;/code&gt; and have it work.&lt;/p&gt;&lt;p&gt;To complete the picture, the JNI equivalent of this would be:&lt;/p&gt;&lt;pre&gt;&lt;div style="background-color: rgb(0, 0, 0); color: rgb(255, 255, 255); font-weight: bold;"&gt;&lt;span style="font-family:monospace;"&gt;&lt;span style="color:#00ff00;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt; Environment {&lt;br /&gt;  &lt;span style="color:#00ff00;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt; LibC {&lt;br /&gt;    &lt;span style="color:#00ff00;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#8080ff;"&gt;&lt;b&gt;native&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; setenv(String name, String value, &lt;span style="color:#00ff00;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; overwrite);&lt;br /&gt;    &lt;span style="color:#00ff00;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#8080ff;"&gt;&lt;b&gt;native&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; unsetenv(String name);&lt;br /&gt;    LibC() {&lt;br /&gt;      System.loadLibrary(&lt;span style="color:#ff40ff;"&gt;&lt;b&gt;"Environment_LibC"&lt;/b&gt;&lt;/span&gt;);&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;  &lt;span style="color:#00ff00;"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt; LibC libc = &lt;span style="color:#ffff00;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt; LibC();&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;p&gt;The call to &lt;code&gt;System.loadLibrary()&lt;/code&gt; loads a dynamic/shared library. On Linux it looks for "libEnvironment&lt;code&gt;_&lt;/code&gt;LibC.so" and on Windows "Environment&lt;code&gt;_&lt;/code&gt;LibC.dll". The implementation of those &lt;code&gt;native&lt;/code&gt; calls could be like this C++ code:&lt;/p&gt;&lt;pre&gt;&lt;div style="background-color: rgb(0, 0, 0); color: rgb(255, 255, 255); font-weight: bold;"&gt;&lt;span style="font-family:monospace;"&gt;&lt;span style="color:#8080ff;"&gt;&lt;b&gt;#include &lt;/b&gt;&lt;/span&gt;&lt;span style="color:#ff40ff;"&gt;&lt;b&gt;"Environment_LibC.h"&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#8080ff;"&gt;&lt;b&gt;#include &lt;/b&gt;&lt;/span&gt;&lt;span style="color:#ff40ff;"&gt;&lt;b&gt;&amp;lt;stdlib.h&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#8080ff;"&gt;&lt;b&gt;#ifdef WINDOWS&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#8080ff;"&gt;&lt;b&gt;#include &lt;/b&gt;&lt;/span&gt;&lt;span style="color:#ff40ff;"&gt;&lt;b&gt;&amp;lt;string&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#8080ff;"&gt;&lt;b&gt;#endif&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#00ff00;"&gt;&lt;b&gt;struct&lt;/b&gt;&lt;/span&gt; JavaString&lt;br /&gt;{&lt;br /&gt;  JavaString(JNIEnv *env, jstring val):&lt;br /&gt;    m_env(env),&lt;br /&gt;    m_val(val),&lt;br /&gt;    m_ptr(env-&amp;gt;GetStringUTFChars(val, &lt;span style="color:#ff40ff;"&gt;&lt;b&gt;0&lt;/b&gt;&lt;/span&gt;)) {}&lt;br /&gt;&lt;br /&gt;  ~JavaString() {&lt;br /&gt;    m_env-&amp;gt;ReleaseStringUTFChars(m_val, m_ptr);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style="color:#ffff00;"&gt;&lt;b&gt;operator&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;const&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;char&lt;/b&gt;&lt;/span&gt;*() &lt;span style="color:#00ff00;"&gt;&lt;b&gt;const&lt;/b&gt;&lt;/span&gt; {&lt;br /&gt;    &lt;span style="color:#ffff00;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; m_ptr;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  JNIEnv *m_env;&lt;br /&gt;  jstring &amp;amp;m_val;&lt;br /&gt;  &lt;span style="color:#00ff00;"&gt;&lt;b&gt;const&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;char&lt;/b&gt;&lt;/span&gt; *m_ptr;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;JNIEXPORT jint JNICALL Java_Environment_00024LibC_setenv&lt;br /&gt;(JNIEnv *env, jobject obj, jstring name, jstring value, jint overwrite)&lt;br /&gt;{&lt;br /&gt;  JavaString namep(env, name);&lt;br /&gt;  JavaString valuep(env, value);&lt;br /&gt;&lt;span style="color:#8080ff;"&gt;&lt;b&gt;#ifdef WINDOWS&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;  std::string s(namep);&lt;br /&gt;  s += &lt;span style="color:#ff40ff;"&gt;&lt;b&gt;"="&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;  s += valuep;&lt;br /&gt;  &lt;span style="color:#00ff00;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; res = _putenv(s.c_str());&lt;br /&gt;&lt;span style="color:#8080ff;"&gt;&lt;b&gt;#else&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color:#00ff00;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; res = setenv(namep, valuep, overwrite);&lt;br /&gt;&lt;span style="color:#8080ff;"&gt;&lt;b&gt;#endif&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color:#ffff00;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; res;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;JNIEXPORT jint JNICALL Java_Environment_00024LibC_unsetenv&lt;br /&gt;(JNIEnv *env, jobject obj, jstring name)&lt;br /&gt;{&lt;br /&gt;  JavaString namep(env, name);&lt;br /&gt;&lt;span style="color:#8080ff;"&gt;&lt;b&gt;#ifdef WINDOWS&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;  std::string s(namep);&lt;br /&gt;  s += &lt;span style="color:#ff40ff;"&gt;&lt;b&gt;"="&lt;/b&gt;&lt;/span&gt;;&lt;br /&gt;  &lt;span style="color:#00ff00;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; res = _putenv(s.c_str());&lt;br /&gt;&lt;span style="color:#8080ff;"&gt;&lt;b&gt;#else&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color:#00ff00;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; res = unsetenv(namep);&lt;br /&gt;&lt;span style="color:#8080ff;"&gt;&lt;b&gt;#endif&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color:#ffff00;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; res;&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;p&gt;You generate the header files using &lt;code&gt;javah&lt;/code&gt; - that gives you the strange function names needed - and compile the code as C++ to produce a shared library:&lt;/p&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;javac Environment.java&lt;br /&gt;javah Environment&lt;br /&gt;g++ -shared Environment_LibC.cc -o libEnvironment_LibC.so -I$(JAVA_HOME)/include/linux -I$(JAVA_HOME)/include/&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This library needs to be in one of the &lt;em&gt;usual places&lt;/em&gt; to work - somewhere where it can be found by &lt;code&gt;dlopen()&lt;/code&gt;. So either in /usr/lib, a directory where ldconfig looks, or in one of the paths in &lt;code&gt;LD_LIBRARY_PATH&lt;/code&gt;. This depends on the OS you are using. For Windows, Solaris or Mac you need a whole different set of flags and incantations. You can see why I lean towards JNA, even though it has its own problems. For the record this is how to compile the JNI library on Windows using MinGW:&lt;/p&gt;&lt;pre&gt;&lt;code class="prettyprint"&gt;g++ -DWINDOWS -Wl,--kill-at -shared Environment_LibC.cc -o Environment_LibC.dll -I$(JAVA_HOME)/include/win32 -I$(JAVA_HOME)/include&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That &lt;code&gt;--kill-at&lt;/code&gt; switch is &lt;a href="http://dev.eclipse.org/newslists/news.eclipse.tools.jdt/msg19993.html"&gt;a real gotcha&lt;/a&gt;. Without it the function symbol that the MinGW compiler produces is not the one that the JVM was expecting. On Windows the library itself must be in the current directory, or in one of the directories listed in the PATH variable.&lt;/p&gt;&lt;p&gt;As you can see we repeat the whole setenv-and-unsetenv-do-not-exist dance and use &lt;code&gt;_putenv()&lt;/code&gt; for both. Here I fudge it with a bit of ifdeffing. Meh.&lt;/p&gt;&lt;p&gt;Now that we have a way to call the C library's &lt;code&gt;setenv()&lt;/code&gt; and &lt;code&gt;unsetenv()&lt;/code&gt; (or equivalent), let's wrap it all up. Here are the final &lt;code&gt;setenv()&lt;/code&gt; and &lt;code&gt;unsetenv()&lt;/code&gt; functions that update the C environment and the Java one too:&lt;/p&gt;&lt;pre&gt;&lt;div style="background-color: rgb(0, 0, 0); color: rgb(255, 255, 255); font-weight: bold;"&gt;&lt;span style="font-family:monospace;"&gt;&lt;span style="color:#00ffff;"&gt;&lt;b&gt;// inside the Environment class...&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#00ff00;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; unsetenv(String name) {&lt;br /&gt;  Map&amp;lt;String, String&amp;gt; map = getenv();&lt;br /&gt;  map.remove(name);&lt;br /&gt;  Map&amp;lt;String, String&amp;gt; env2 = getwinenv();&lt;br /&gt;  env2.remove(name);&lt;br /&gt;  &lt;span style="color:#ffff00;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; libc.unsetenv(name);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#00ff00;"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;static&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#00ff00;"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; setenv(String name, String value, &lt;span style="color:#00ff00;"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/span&gt; overwrite) {&lt;br /&gt;  &lt;span style="color:#ffff00;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (name.lastIndexOf(&lt;span style="color:#ff40ff;"&gt;&lt;b&gt;"="&lt;/b&gt;&lt;/span&gt;) != -&lt;span style="color:#ff40ff;"&gt;&lt;b&gt;1&lt;/b&gt;&lt;/span&gt;) {&lt;br /&gt;    &lt;span style="color:#ffff00;"&gt;&lt;b&gt;throw&lt;/b&gt;&lt;/span&gt; &lt;span style="color:#ffff00;"&gt;&lt;b&gt;new&lt;/b&gt;&lt;/span&gt; IllegalArgumentException(&lt;br /&gt;        &lt;span style="color:#ff40ff;"&gt;&lt;b&gt;"Environment variable cannot contain '='"&lt;/b&gt;&lt;/span&gt;);&lt;br /&gt;  }&lt;br /&gt;  Map&amp;lt;String, String&amp;gt; map = getenv();&lt;br /&gt;  &lt;span style="color:#00ff00;"&gt;&lt;b&gt;boolean&lt;/b&gt;&lt;/span&gt; contains = map.containsKey(name);&lt;br /&gt;  &lt;span style="color:#ffff00;"&gt;&lt;b&gt;if&lt;/b&gt;&lt;/span&gt; (!contains || overwrite) {&lt;br /&gt;    map.put(name, value);&lt;br /&gt;    Map&amp;lt;String, String&amp;gt; env2 = getwinenv();&lt;br /&gt;    env2.put(name, value);&lt;br /&gt;  }&lt;br /&gt;  &lt;span style="color:#ffff00;"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; libc.setenv(name, value, overwrite?&lt;span style="color:#ff40ff;"&gt;&lt;b&gt;1&lt;/b&gt;&lt;/span&gt;:&lt;span style="color:#ff40ff;"&gt;&lt;b&gt;0&lt;/b&gt;&lt;/span&gt;);&lt;br /&gt;}&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/pre&gt;&lt;p&gt;Curiously enough ProcessEnvironment is wired so as to validate the values that you add to the "unmodifiable" Map, but the case insensitive equivalent on Windows is not validated. If you try and add an invalid environment variable, such as one with a name that contains &lt;code&gt;=&lt;/code&gt;, only the unmodifiable map will throw an IllegalArgumentException. This makes it fairly robust as the nasty name doesn't trickle down to the underlying C environment, but for Windows we have to do an extra check manually.&lt;/p&gt;&lt;p&gt;I've uploaded a &lt;a href="http://sites.google.com/site/gbaremakes/home/downloads/java-setenv.tar.gz"&gt;tarball with all the files mentioned on here&lt;/a&gt; together with the dependencies to my &lt;a href="http://sites.google.com/site/gbaremakes/home/downloads"&gt;GBA Remakes site&lt;/a&gt;. So now you've no excuse to not go off setting environment variables like mad.&lt;/p&gt;&lt;p&gt;Of course you shouldn't really do any of this. This post was 60% "if you really need to", 40% "might be useful". ProcessBuilder is the way to go for changing the environment in child processes.&lt;/p&gt;&lt;p&gt;The only thing that you might want to do is change the environment in a running Java process, but even then it is probably easier to create a wrapper script or batch file that launches your program and fiddle the environment prior to launching the JVM. Using reflection to access all those inner member variables is pretty flaky - if they change their name in some future version, your code will stop working. Happy hacking :-)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-3154189616689193802?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/3154189616689193802/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2009/11/setting-environment-variables-in-java.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/3154189616689193802'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/3154189616689193802'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2009/11/setting-environment-variables-in-java.html' title='Setting environment variables in Java'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-3820505951284973199</id><published>2009-11-11T23:22:00.003+01:00</published><updated>2009-11-11T23:26:53.337+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Bunjalloo'/><title type='text'>Optimisations</title><content type='html'>If you have been reading the changes that I've been pushing out to Bunjalloo lately, you will have noticed that there are quite a few that are aimed at optimising parts of the code. There was a lot of low-hanging fruit in there and the rendering of some 200+ comment threads on reddit was starting to annoy me.&lt;br /&gt;&lt;p&gt;There's an old rule when it comes to optimising your code; &lt;em&gt;don't&lt;/em&gt;. 2nd verse, same as the first. The 3rd rule of optimisation is to profile your code first. So that's what I did.&lt;/p&gt;&lt;p&gt;The good old way to see where the bottle necks are is to use gprof. You compile with profiling on by passing a couple of flags to gcc, run the program and it spits out a profile upon exit. You then run the gprof command line tool and that interprets the profile to give you a table of hot spots. From commit 5beaffd581ed it looked something like this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;Each sample counts as 0.01 seconds.&lt;br /&gt;%   cumulative   self              self     total&lt;br /&gt;time   seconds   seconds    calls  ms/call  ms/call  name&lt;br /&gt;10.00      0.02     0.02   103228     0.00     0.00  Font::valueToIndex(unsigned int) const&lt;br /&gt;10.00      0.04     0.02    68648     0.00     0.00  std::_List_iterator&amp;lt;HtmlElement*&amp;gt;::operator--()&lt;br /&gt;7.50      0.06     0.01   701479     0.00     0.00  std::less&amp;lt;unsigned int&amp;gt;::operator()(unsigned int const&amp;amp;, unsigned int const&amp;amp;) const&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Right there you can see that &lt;code&gt;Font::valueToIndex&lt;/code&gt; was taking a lot of time, but I already knew that &lt;em&gt;that&lt;/em&gt; method could be improved. The other C++ &lt;a class="zem_slink" href="http://en.wikipedia.org/wiki/Standard_Template_Library" title="Standard Template Library" rel="wikipedia"&gt;STL&lt;/a&gt; calls were trickier to track down. I use all sorts of STL containers, so the problem could have been anywhere...&lt;/p&gt;&lt;p&gt;A couple of years ago Google released their &lt;a href="http://code.google.com/p/google-perftools/"&gt;performance analysis tools&lt;/a&gt;. One of the advantages google-perftools' CPU profiler has over gprof is that the output shows function calls line-by-line in a nifty graphical representation. Running the profiler on the same code gave this output:&lt;/p&gt;&lt;p&gt;&lt;img src="http://imgur.com/50ZLFl.gif" alt="thumbnail of the analysis" title="" /&gt;&lt;br /&gt;&lt;a href="http://imgur.com/50ZLF.gif"&gt;Here is the original full-size image&lt;/a&gt;&lt;/p&gt;&lt;p&gt;From there, I could trace the call graph back from the "slow" STL call to my code see that the use of a &lt;code&gt;std::set&lt;/code&gt; was causing problems. It was overkill anyway and a simple change improved things there.&lt;/p&gt;&lt;p&gt;The different output in the perftools analysis is probably due to the way it works compared to gprof. With gprof, you get a call to the profiling library added to each of your program's functions, which means you need to recompile all of your code. With the Google tools you don't need to recompile your code, you just have to link in the profiler library to your executable. It then hooks in to the start of the program and uses timers and signals to instrument the code, adding traces at the current point of execution. The result is that code that takes longer has more "hits", but the result is not exactly the same as gprof's output.&lt;/p&gt;&lt;p&gt;This is why being able to compile NDS code on the PC is a really good idea. These things are not impossible on the DS of course - counting the hblanks your slow function takes by changing the background color is a classic technique - but in general running unit tests, debugging, and doing performance analysis are much tougher to do on an embedded device.&lt;/p&gt;&lt;p&gt;Enough waffle. All this means that the next version of Bunjalloo may be a bit nippier, hopefully.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-3820505951284973199?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/3820505951284973199/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2009/11/optimisations.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/3820505951284973199'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/3820505951284973199'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2009/11/optimisations.html' title='Optimisations'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-7055820335431430326</id><published>2009-11-06T22:23:00.005+01:00</published><updated>2009-11-06T22:49:01.095+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DS'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><title type='text'>NDS thumbnail preview in Nautilus</title><content type='html'>When you insert a cartridge into a Nintendo DS, the start menu shows a little image or logo of the game. Homebrew games for the DS can also add their own logos and these show up when you view them in Moonshell or whatever menu your cartridge happens to use.&lt;br /&gt;&lt;p&gt;Ages ago I wrote a little script to show these images as the preview icon for NDS files in the Gnome file browser &lt;a class="zem_slink" href="http://www.gnome.org/projects/nautilus/" title="Nautilus (file manager)" rel="homepage"&gt;Nautilus&lt;/a&gt;. The script is about a hundred lines of Python and it's &lt;a href="http://code.google.com/p/quirkysoft/downloads/detail?name=nds-thumb.tar.gz"&gt;available here&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_nzN39P0Ykuk/SvSWAr6A2oI/AAAAAAAABLU/41_E7sCQOpo/s1600-h/Screenshot-nds+-+File+Browser.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 279px; height: 199px;" src="http://1.bp.blogspot.com/_nzN39P0Ykuk/SvSWAr6A2oI/AAAAAAAABLU/41_E7sCQOpo/s400/Screenshot-nds+-+File+Browser.png" alt="" id="BLOGGER_PHOTO_ID_5401106791654283906" border="0" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The setup file in that download tarball associates the icon-extracting command to the &lt;a class="zem_slink" href="http://en.wikipedia.org/wiki/MIME" title="MIME" rel="wikipedia"&gt;MIME&lt;/a&gt;-type of the Nintendo DS file. If you use an older distro then you may have to associate the script with the generic application/octet-stream MIME type. The script filters by file name anyway. This association is not done using the usual Nautilus scripting method, where you add a script to &lt;code&gt;~/.gnome2/nautilus-scripts/&lt;/code&gt;, but rather using gconf variables.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;If you need to uninstall the icon preview for some reason, you can run:&lt;br /&gt;&lt;/p&gt;&lt;code&gt;gconftool-2 -u /desktop/gnome/thumbnailers/application@x-nintendo-ds-rom&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Oh, and while we're here I recommend you go and play the absolutely brilliant nostalgia-fest that is &lt;a href="http://www.headsoft.com.au/index.php?category=mmll&amp;amp;page=download"&gt;Manic Miner in the Lost Levels&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-7055820335431430326?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/7055820335431430326/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2009/11/nds-thumbnail-preview-in-nautilus.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/7055820335431430326'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/7055820335431430326'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2009/11/nds-thumbnail-preview-in-nautilus.html' title='NDS thumbnail preview in Nautilus'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_nzN39P0Ykuk/SvSWAr6A2oI/AAAAAAAABLU/41_E7sCQOpo/s72-c/Screenshot-nds+-+File+Browser.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-1031009295813080398</id><published>2009-08-16T16:40:00.008+02:00</published><updated>2009-08-16T17:02:55.607+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Geocities'/><category scheme='http://www.blogger.com/atom/ns#' term='Game Boy Advance'/><title type='text'>Game Boy Remakes moves home</title><content type='html'>&lt;a class="zem_slink" href="http://geocities.com/" title="GeoCities" rel="homepage"&gt;Geocities&lt;/a&gt; has been around in one form or another since about 1995, but &lt;a class="zem_slink" href="http://www.yahoo.com/" title="Yahoo!" rel="homepage"&gt;Yahoo&lt;/a&gt; has recently announced that the web hosting service will close this October. With this in mind, I've moved all my &lt;a href="http://sites.google.com/site/gbaremakes/"&gt;Game Boy Advance remakes&lt;/a&gt; and &lt;a href="http://sites.google.com/site/gbaremakes/home/emulation"&gt;BBC emulation&lt;/a&gt; to a new &lt;a href="http://sites.google.com/site/gbaremakes/"&gt;home on Google Sites&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Do you remember when people said "don't forget to update your bookmarks!" when they changed their website address? Now nobody does that because everyone uses a &lt;a class="zem_slink" href="http://en.wikipedia.org/wiki/Web_search_engine" title="Web search engine" rel="wikipedia"&gt;search engine&lt;/a&gt; to find what they need. That means that when Geocities closes, all the search-juice for the old site will be lost. So here I'm sowing a little search seed, which will hopefully grow and let people find these remakes when Yahoo finally pulls the plug. BTW, closing down Geocities seems a really odd thing to do. The limits on bandwidth were tiny (4MB per hour!), the sites are full to the brim with adverts. It must have been costing Yahoo nothing to host all of them.&lt;br /&gt;&lt;br /&gt;Anyway the migration was completely manual, but hopefully I haven't missed anything and the &lt;a href="http://sites.google.com/site/gbaremakes"&gt;new web site&lt;/a&gt; should have all of the old content on it.&lt;br /&gt;&lt;br /&gt;As I moved all of the content over, I was reading through a lot of the stuff I had up on the old site. I really miss remaking these old games, I'd love to get back into that again one more time. Reading through old assembly code figuring out the algorithms used and rewriting them in C is pretty good fun. And at the end you get a game to play too. I have a few ideas for a remake, but I don't want to promise anything. I know from experience that announcing something that is a work in progress, or even less than that, can &lt;a href="http://www.psych.nyu.edu/gollwitzer/"&gt;suck the life out of the effort&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-1031009295813080398?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/1031009295813080398/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2009/08/game-boy-remakes-moves-home.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/1031009295813080398'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/1031009295813080398'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2009/08/game-boy-remakes-moves-home.html' title='Game Boy Remakes moves home'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-4043835566900517250</id><published>2009-07-20T20:00:00.001+02:00</published><updated>2009-07-20T21:45:51.501+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bunjalloo'/><category scheme='http://www.blogger.com/atom/ns#' term='HOWTO'/><category scheme='http://www.blogger.com/atom/ns#' term='Google Code'/><category scheme='http://www.blogger.com/atom/ns#' term='Mercurial'/><title type='text'>Migration to Mercurial</title><content type='html'>&lt;p class="zemanta-img" style="margin: 1em; float: right; display: block; width: 189px;"&gt;&lt;a href="http://www.flickr.com/photos/52039665@N00/145592282"&gt;&lt;img src="http://farm1.static.flickr.com/54/145592282_220656be31_m.jpg" alt="Liquid Metal, Venice" style="border: medium none ; display: block;" width="179" height="240" /&gt;&lt;/a&gt;&lt;span class="zemanta-img-attribution"&gt;Image by &lt;a href="http://www.flickr.com/photos/52039665@N00/145592282"&gt;ms sdb&lt;/a&gt; via Flickr&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;I've taken the plunge and decided to integrate all of the &lt;a href="http://code.google.com/p/quirkysoft/"&gt;Bunjalloo code onto the &lt;/a&gt;&lt;a href="http://code.google.com/p/quirkysoft/"&gt;Google Code&lt;/a&gt; site. This meant I migrated from the original &lt;a class="zem_slink" href="http://github.com/" title="GitHub" rel="homepage"&gt;Github&lt;/a&gt;-hosted &lt;a class="zem_slink" href="http://git-scm.com/" title="Git (software)" rel="homepage"&gt;Git&lt;/a&gt; repository to make use of the new &lt;a class="zem_slink" href="http://www.selenic.com/mercurial/" title="Mercurial (software)" rel="homepage"&gt;Mercurial&lt;/a&gt; support that GC added not so long ago.&lt;br /&gt;&lt;br /&gt;The main reason I migrated was to get all the issue tracking, wiki and code changes on to one site. I really had 2 choices: migrate the main site to Github and use the issues and wiki on there, or migrate the code to &lt;a class="zem_slink" href="http://code.google.com/" title="Google Code" rel="homepage"&gt;Google Code&lt;/a&gt; and use Mercurial. I quite like Github and I think it is amazing that there are so many brilliant free hosting services, but I really prefer the Google Code interface from a user's point of view. It is generally less cluttered.&lt;br /&gt;&lt;br /&gt;So what does this change get us? First off, we lose github's famous "social coding" features. I had one fork in 2 years, with 0 additional commits. No great loss there then. You can still email patches to the discussion list of course, and of course with either DVCS the author information is retained. I gain the fact that I can now reference changes a bit easier in bug reports and close tickets straight from commit messages. Assuming I even write any more code or fix any bugs ;-)&lt;br /&gt;&lt;br /&gt;I had a couple of pet peeves with Mercurial, mostly that I really missed gitk's features. Luckily I discovered what I assume everyone else must use: Tortoise HG. This provides "hgtk log" on Linux that works a lot better than the "hg view" history viewer, which is a port of a really ancient version of gitk. The most important feature that hgtk has is a refresh button so I don't have to keep killing and restarting the application each time I make some changes.&lt;br /&gt;&lt;br /&gt;Some other areas that I saw as weaknesses were to do with Mercurial's history fiddling, or lack thereof. However I decided that I'm probably better off not messing with history too much anyway. Lately I've tended to avoid doing that in Git and I get more done, even if the revision log is not as clean as it could be. I finally understood the way to do this using Mercurial Queues anyway, even if it is a bit more fiddly.&lt;br /&gt;&lt;br /&gt;My final missing feature was the "commit -v" feature, which shows you the patch of the commit that you are making without having to open up a separate console. This hasn't been fixed, but I've worked around it by writing a Vim script to do something similar. Pressing "K" shows the diff of the current tree in a new buffer. This actually works out pretty well as I can see a patch and write a comment at the same time, rather than having to jump back to the top as I did with the "commit -v" thing.&lt;br /&gt;&lt;br /&gt;To do the actual Git to Mercurial conversion I used the "hg convert" extension that is included with core Mercurial. That worked flawlessly and made switching really easy. The conversion guide on the Google Code support site has detailed steps on what to do when converting from &lt;a class="zem_slink" href="http://subversion.tigris.org/" title="Subversion (software)" rel="homepage"&gt;Subversion&lt;/a&gt;, but I'll describe a few gotchas that I found with the Git to Hg transition.&lt;br /&gt;&lt;br /&gt;The recently released Mercurial 1.3 included a tiny patch that I wrote to generate a slightly nicer log for git conversions, so I used that version. You see Git tracks both the author of a patch and the person who made the actual commit, but Mercurial only tracks the "user". The user is equivalent to Git's "committer" by default, while author information is assumed to be the same dude. When you ran hg convert, it added a line like "committer: A.Committer &lt;a.committer@example.com&gt;" to the Mercurial log message for every commit, &lt;a href="http://stackoverflow.com/questions/806209/how-can-i-convert-to-mercurial-without-the-extra-committer-line-in-the-log"&gt;even if the author and committer were one and the same&lt;/a&gt; in the original git repository. It looked a bit silly when 99.9% of the commits were my own. So my patch made sure that the "committer" line only got added if the author of the original change was not the same as the commiter of the change.&lt;br /&gt;&lt;br /&gt;Another interesting niggle: Git has 2 different types of tag; lightweight and annotated. Annotated tags can also be gpg signed, but that wasn't the case in my repository. The difference between lightweight and annotated tags is pretty subtle. As far as I understand it, a lightweight tag is simply a reference to a commit ID, while an annotated tag also has its own blob in the Git database.&lt;br /&gt;&lt;br /&gt;By default "git tag mytag HEAD" will create a tag of the lightweight variety. This is apparently the Wrong Thing To Do and one of the few places that Git's default behaviour is not the best option. You really should pass the "-a" option to create an annotated tag. Suffice to say that I used the default lightweight type of tags for quite a while until I discovered my mistake. The "hg convert" extension doesn't convert lightweight tags at all, it only converts the chunky annotated kind. This is possibly by design (maybe by misunderstanding?) as it would be easy to fix the convert extension to convert either type of tag.&lt;br /&gt;&lt;br /&gt;The easiest workaround for me was to just convert my git lightweight tags to annotated tags in the source git repository using the "--force" option to overwrite the old ones. The convert process picked these up and converted them over correctly. Interestingly enough &lt;a href="http://stackoverflow.com/questions/1146659/how-do-i-convert-my-git-repository-to-mercurial-and-bring-along-its-tags"&gt;Justin Williams had posted about a similar problem&lt;/a&gt; and his timing was perfect to ask it over on &lt;a href="http://stackoverflow.com/"&gt;StackOverflow.com&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Now that I've used DVCS a bit more and the novelty of branching has worn off, I decided that I wanted the minimal number of heads in my new Mercurial repository. I also wanted to maintain as much of the released history as possible. Luckily the history was mostly linear. I did create a couple of branches for maintenance releases of Bunjalloo early on, but after about version 0.4 I just made releases from the trunk.&lt;br /&gt;&lt;br /&gt;Originally the repository was in Subversion and I pulled in the tag branches with git-svn too. This lead to a few branch stubs with a single commit ("creating tag blah") with a corresponding git tag that I must have created at some point later on. I used the Mercurial Queues extension to trim these out of the history where applicable so that the final repo has just 2 heads - the main trunk and an old, closed maintenance branch from the 0.3 days.&lt;br /&gt;&lt;br /&gt;Oh, when you install Mercurial from source on Ubuntu (possibly on any Debian derivative?) it rather inexplicably creates an /etc/mercurial/hgrc file that enables all of the extensions. This lead me to &lt;a href="http://mercurial.selenic.com/bts/issue1719"&gt;(re)discover a bug with the inotify extension&lt;/a&gt; when used in conjunction with Mercurial Queues. My solution was to simply disable the inotify extension (in fact just removing the /etc/mercurial directory and enabling what you need in $HOME/.hgrc is a better idea overall).&lt;br /&gt;&lt;br /&gt;Anyway, feel free to check out the code and send me your patches to fix all of those open issues! :-)&lt;/a.committer@example.com&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-4043835566900517250?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/4043835566900517250/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2009/07/image-by-ms-sdb-via-flickr-ive-taken.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/4043835566900517250'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/4043835566900517250'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2009/07/image-by-ms-sdb-via-flickr-ive-taken.html' title='Migration to Mercurial'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm1.static.flickr.com/54/145592282_220656be31_t.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-6317206341362172094</id><published>2009-07-08T22:30:00.005+02:00</published><updated>2009-07-08T22:42:52.835+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DS'/><category scheme='http://www.blogger.com/atom/ns#' term='Bunjalloo'/><title type='text'>Bunjalloo 0.7.5</title><content type='html'>&lt;p class="zemanta-img" style="margin: 1em; float: right; display: block; width: 225px;"&gt;&lt;a href="http://www.flickr.com/photos/19363462@N00/123153665"&gt;&lt;img src="http://farm1.static.flickr.com/42/123153665_ddd0ff5dc1_m.jpg" alt="hand_and_bugcolor" style="border: medium none ; display: block;" width="215" height="240" /&gt;&lt;/a&gt;&lt;span class="zemanta-img-attribution"&gt;Image by &lt;a href="http://www.flickr.com/photos/19363462@N00/123153665"&gt;beneneuman&lt;/a&gt; via Flickr&lt;/span&gt;&lt;/p&gt;I've just put up yet another new version of &lt;a href="http://code.google.com/p/quirkysoft/downloads/list"&gt;Bunjalloo&lt;/a&gt;. This one fixes a load of bugs that caused lots of top pages to be broken. In particular you can log in to &lt;a class="zem_slink" href="http://gmail.com" title="Gmail" rel="homepage"&gt;GMail&lt;/a&gt; again. Yay!&lt;br /&gt;&lt;br /&gt;Changes in 0.7.5:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Improvements to caching - logging in to GMail works again&lt;/li&gt;&lt;li&gt;Clicking preference icon goes straight to preferences&lt;/li&gt;&lt;li&gt;Fix encoding problems that caused crashes&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Fixed lots of non-ascii character keyboard bugs&lt;/li&gt;&lt;li&gt;Fix configuration changes that use escapable % characters&lt;/li&gt;&lt;/ul&gt;You may have to manually fix the download path in your configuration settings. This is because the download path could have become messed up and show all path separators as %2F instead of /.&lt;br /&gt;&lt;br /&gt;In the next release I want to fix cookies so that you don't have to enter your name and password into all the sites that you log in to. I changed the password on my google account from something like "password" to a good strong one and it's a pain typing it in all the time on the DS ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-6317206341362172094?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/6317206341362172094/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2009/07/bunjalloo-075.html#comment-form' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/6317206341362172094'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/6317206341362172094'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2009/07/bunjalloo-075.html' title='Bunjalloo 0.7.5'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm1.static.flickr.com/42/123153665_ddd0ff5dc1_t.jpg' height='72' width='72'/><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-2560951669429462612</id><published>2009-07-06T23:24:00.011+02:00</published><updated>2010-12-05T16:38:40.712+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='HOWTO'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Creative Zen Mozaic on Ubuntu 9.04 Jaunty</title><content type='html'>&lt;div class="zemanta-img" style="display: block; float: right; margin: 1em; width: 250px;"&gt;&lt;a href="http://www.flickr.com/photos/29935447@N03/3121506262"&gt;&lt;img alt="Where Birthday Happens!" src="http://farm4.static.flickr.com/3220/3121506262_279b1f7850_m.jpg" style="border: medium none; display: block;" /&gt;&lt;/a&gt;&lt;span class="zemanta-img-attribution"&gt;Image by &lt;a href="http://www.flickr.com/photos/29935447@N03/3121506262"&gt;♪ Sleeping Sun ♪&lt;/a&gt; via Flickr&lt;/span&gt;&lt;/div&gt;I've just been given a Creative Zen Mozaic portable audio player for my birthday (it's a bit early, but I'm not complaining!). I've had a Zen Micro for a few years now and it's a pretty decent gizmo. Small enough to fit in my pocket, has stood up to several falls, has a &lt;a class="zem_slink" href="http://en.wikipedia.org/wiki/User_interface" rel="wikipedia" title="User interface"&gt;UI&lt;/a&gt; that gets out of the way and it works with &lt;a href="http://gnomad2.sourceforge.net/"&gt;Gnomad2&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Update for Ubuntu 9.10&lt;/span&gt;: The Mozaic now runs out of the box, no changes needed. I'll leave this here for posterity.&lt;br /&gt;&lt;br /&gt;After plugging the new Mozaic in to my laptop, which runs the latest release of &lt;a class="zem_slink" href="http://www.ubuntu.com/" rel="homepage" title="Ubuntu"&gt;Ubuntu&lt;/a&gt; (9.04 Jaunty Jackalope at the time of writing) I discovered that &lt;span style="font-style: italic;"&gt;horror!&lt;/span&gt; it wasn't recognised by Gnomad2. It seems like it's a &lt;a href="https://bugs.launchpad.net/ubuntu/+bug/292789"&gt;common&lt;/a&gt; &lt;a href="http://ubuntuforums.org/showthread.php?p=5824889"&gt;problem&lt;/a&gt;. The solution is sort of linked to on that bug report, but the help is in French and the file you have to change has moved since that was written. You couldn't make up a better "open source documentation sucks" anecdote even if you tried.&lt;br /&gt;&lt;br /&gt;So.. using your favourite editor open up the file &lt;span style="font-weight: bold;"&gt;/lib/udev/rules.d/45-libmtp8.rules&lt;/span&gt; and add the magic lines:&lt;br /&gt;&lt;pre&gt;# Creative ZEN Mozaic&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;ATTR{idVendor}=="&lt;span style="color: #990000; font-weight: bold;"&gt;041e&lt;/span&gt;", ATTR{idProduct}=="&lt;span style="color: #660000; font-weight: bold;"&gt;4161&lt;/span&gt;", SYMLINK+="libmtp-%k", MODE="660", GROUP="audio"&lt;/span&gt;&lt;/pre&gt;You'll have to do that with super powers, so use something like this to open the file with the correct permissions using gedit:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-size: 85%;"&gt;gksu gedit  /lib/udev/rules.d/45-libmtp8.rules&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Add the lines right before the first "#Creative ZEN" line that is already in there, just to be on the safe side. This can be derived from first priciples actually, because if you run &lt;span style="font-style: italic;"&gt;lsusb&lt;/span&gt; it'll say something like:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 85%;"&gt;&lt;span style="font-family: courier new;"&gt;Bus 001 Device 004: ID &lt;span style="color: #cc0000; font-weight: bold;"&gt;041e&lt;/span&gt;&lt;span style="color: #cc0000;"&gt;:&lt;/span&gt;&lt;span style="color: #cc0000; font-weight: bold;"&gt;4161&lt;/span&gt; Creative Technology, Ltd &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Which ties in pretty nicely to the line you have to add to the 45-libmtp8.rules file.&lt;br /&gt;&lt;br /&gt;Anyway, after adding that unplug the Mozaic and plug it back in again. That forces udev to reread the settings you have just changed. Start Gnomad2 and hopefully it will recognise your player and list all the tracks on it. Yipee!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-2560951669429462612?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/2560951669429462612/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2009/07/creative-zen-mozaic-on-ubuntu-904.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/2560951669429462612'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/2560951669429462612'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2009/07/creative-zen-mozaic-on-ubuntu-904.html' title='Creative Zen Mozaic on Ubuntu 9.04 Jaunty'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://farm4.static.flickr.com/3220/3121506262_279b1f7850_t.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-8549860549859762256</id><published>2009-07-02T22:01:00.003+02:00</published><updated>2009-07-02T22:22:16.634+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DS'/><category scheme='http://www.blogger.com/atom/ns#' term='Bunjalloo'/><category scheme='http://www.blogger.com/atom/ns#' term='devkitpro'/><title type='text'>Like buses</title><content type='html'>What a disaster! You wait ages for a release of Bunjalloo, then 2 arrive in 2 days. Let me tell you how this happened.&lt;br /&gt;&lt;br /&gt;I use version control for all of the main code. All my own code, that is. I also have a big bunch of downloadable 3rd party libraries that Bunjalloo needs. The build system only deals with my own code, it doesn't handle the 3rd party libraries that I install to $DEVKITPRO/libnds and assume are pretty much fixed. So stuff like libpng, jpeg, zlib, the matrix ssl library, all of these have to be downloaded, compiled and installed separately. I have a few patches that I've applied on top of these libraries too. All of these steps are handled by a script that downloads the source files, patches them if needed, compiles and installs. These patches are changes that would either never be accepted in the core library - removing printfs for example, or changing the Makefiles for the DS - or in the case of matrix, the upstream authors don't seem to have any real "community" or way to send them patches.&lt;br /&gt;&lt;br /&gt;These libraries are all relatively stable, and when I upgrade devkitPro I can just run my script to install the latest versions. I've also put a tarball of the compiled code on the Google Code site to make your life easier if you want to compile Bunjalloo from code.&lt;br /&gt;&lt;br /&gt;There are some libraries here that I've not yet mentioned and that I mostly take "as is". These are the core devkitPro libraries for the NDS - libnds, libfat, and friends. But! I have also been patching dswifi since about Bunjalloo v0.7 to fix an issue with non blocking sockets that just can't be worked around.&lt;br /&gt;&lt;br /&gt;Thanks to an oversight I didn't apply the patch when I installed the latest dswifi 0.3.9, which meant that the sockets are not dealt with properly. I assume a socket has connected before it really has, and start shoving data in before it's ready. This has the result that after a few page loads sockets just stop connecting, presumably because I've filled up some buffers with junk. Pages no longer load and the whole thing grinds to a halt.&lt;br /&gt;&lt;br /&gt;The solution? Short term, I've patched dswifi again and &lt;a href="http://code.google.com/p/quirkysoft/downloads/detail?name=bunjalloo-0.7.4.zip"&gt;uploaded v0.7.4&lt;/a&gt;. Longer term, I've added a &lt;a href="https://sourceforge.net/tracker/?func=detail&amp;atid=668553&amp;aid=2815971&amp;group_id=114505"&gt;bug report to devkitpro on sourceforge&lt;/a&gt;. Hopefully my patch can get integrated and I don't have to apply the changes manually each time I upgrade the DS toolchain. I should have done this a while ago really.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-8549860549859762256?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/8549860549859762256/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2009/07/like-buses.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/8549860549859762256'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/8549860549859762256'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2009/07/like-buses.html' title='Like buses'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-286519413735108695</id><published>2009-07-01T22:02:00.002+02:00</published><updated>2009-07-01T22:20:33.193+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DS'/><category scheme='http://www.blogger.com/atom/ns#' term='Bunjalloo'/><category scheme='http://www.blogger.com/atom/ns#' term='Woopsi'/><title type='text'>Bunjalloo 0.7.3 released</title><content type='html'>I've released a new version of &lt;a href="http://code.google.com/p/quirkysoft/downloads/list"&gt;Bunjalloo on the Google Code site&lt;/a&gt;. This is a fairly minor release that mostly updates the code for devkitARM r26 and the various library updates. Full details are in the &lt;a href="http://code.google.com/p/quirkysoft/wiki/BunjallooChangelog"&gt;ChangeLog&lt;/a&gt; over on the wiki.&lt;br /&gt;&lt;br /&gt;So it's a minor release, but Bunjalloo itself has gone through quite a lot since 0.7.2 came out in December. Development of new features went on hiatus while I tried to incorporate the Woopsi GUI library. After that failed to really work - mostly down to design decisions on both parts; Woopsi uses the DS hardware for really fast scrolling whereas I want flicker free double buffering - I started to go down this crazy architecture astronomy path that went nowhere either.&lt;br /&gt;&lt;br /&gt;Now I want to get back to basics. I want to start releasing versions a bit more regularly. I'm going to try getting a version out every month from now on, even if it is crap! Let's see how long I can last. You may notice the new  banner logo that can be seen when using moonshell and other menu programs. That is thanks to &lt;a href="http://twitter.com/SamGoldfield"&gt;Sam&lt;/a&gt; and I'd like to get some more community contributions. The only way for that to happen is if Bunjalloo is alive and kicking, and I think regular releases is the best way for that.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-286519413735108695?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/286519413735108695/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2009/07/bunjalloo-073-released.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/286519413735108695'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/286519413735108695'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2009/07/bunjalloo-073-released.html' title='Bunjalloo 0.7.3 released'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-7892387451765577669</id><published>2009-06-28T19:51:00.002+02:00</published><updated>2009-11-06T22:50:47.777+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DS'/><category scheme='http://www.blogger.com/atom/ns#' term='devkitpro'/><title type='text'>EZ Flash Vi and libnds 1.3.6</title><content type='html'>The version of libnds and the default ARM7 core that was &lt;a href="http://www.devkitpro.org/devkitarm/libnds-136-and-default-arm7-055/"&gt;released as part of devkitpro last week (24 June 2009)&lt;/a&gt; has a problem with the NDS touch screen controls on the EZ Flash Vi cartridge.&lt;br /&gt;&lt;br /&gt;The symptom is seen best if you run the nds-example "touch_test.nds" from the devkitpro distribution. The keys shows 00002000 in the top right, as if you were holding down the stylus, but in fact no touches are registered. Until an official fix is released by the ezflash coders, the workaround is to use devkitpro's own homebrew menu application. It's GPL code so there's no real conspiracy going on here! In fact it'd be nice to see this menu become the defacto standard in the homebrew world, but it is very rudimentary and only shows a textual listing of the files on your card.&lt;br /&gt;&lt;br /&gt;So on to the instructions to get the latest homebrew working. I'll assume that right now you've downloaded and installed all the latest devkitPro stuff and you're sat there wondering why your touch screen controls don't work.&lt;br /&gt;&lt;br /&gt;First download the latest EZ Flash DLDI driver from &lt;a href="http://www.ezflash.cn/software.htm"&gt;http://www.ezflash.cn/software.htm&lt;/a&gt;. You'll have to download the "Kernel 1.90" zip file, extract it and find the Ez5s.dldi file. Now you have to download the Homebrew Menu code. This is only available in the devkitPro Subversion repository.&lt;br /&gt;&lt;code&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;svn co http://devkitpro.svn.sourceforge.net/viewvc/devkitpro/trunk/projects/nds/HomebrewMenu/&lt;br /&gt;cd HomebrewMenu&lt;br /&gt;make&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Once that is compiled, you have to patch it with the previously extracted Ez5s.dldi file (if you use a high capacity SD card, use the Ez5sdhc.dldi instead). Do that using the dlditool in $DEVKITARM/bin:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;$DEVKITARM/bin/dlditool /path/to/ez5190ob11/moonshell/Ez5s.dldi HomebrewMenu.nds&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Now copy that file onto your card, but &lt;span style="font-weight: bold;"&gt;copy it as the ez5sys.bin file&lt;/span&gt;. This means that when the card boots up, it will boot our HomebrewMenu instead of the regular EZ Flash/Moonshell executable.&lt;br /&gt;&lt;br /&gt;Hopefully the next release of libnds will fix the issue so that homebrew written with it is compatible with all cartridges out of the box. Even better would be if the Homebrew Menu started to see regular updates and became a really cool and useful file browser.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-7892387451765577669?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/7892387451765577669/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2009/06/ez-flash-vi-and-libnds-136.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/7892387451765577669'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/7892387451765577669'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2009/06/ez-flash-vi-and-libnds-136.html' title='EZ Flash Vi and libnds 1.3.6'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-517544117724972155</id><published>2009-06-15T23:12:00.003+02:00</published><updated>2009-07-03T15:48:42.529+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CMake'/><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Vim'/><category scheme='http://www.blogger.com/atom/ns#' term='Unit Tests'/><title type='text'>Lint and CMake</title><content type='html'>I've just updated my &lt;a href="http://code.google.com/p/cmake-lint"&gt;cmake-lint&lt;/a&gt; project with version 1.2. This fixed a bug that I introduced when I added in the ability to specify defaults in a .cmakelintrc file. This was one of those silly errors that using a compiled language would have caught, but in the end better unit tests would have caught it too. I'm not really a rabid &lt;a href="http://en.wikipedia.org/wiki/Test-driven_development"&gt;TDD&lt;/a&gt;-weenie but automated tests that check for basic breakage are really handy. Python makes it dead easy to mock out unwanted and unrelated code too. &lt;a class="zem_slink" href="http://en.wikipedia.org/wiki/Unit_testing" title="Unit testing" rel="wikipedia"&gt;Unit testing&lt;/a&gt; C++ is hellish in comparison.&lt;br /&gt;&lt;br /&gt;As I was saying, &lt;a href="http://code.google.com/p/cmake-lint"&gt;cmake-lint is a really basic lint tool&lt;/a&gt; to root out common bad practices in &lt;a class="zem_slink" href="http://www.cmake.org/" title="CMake" rel="homepage"&gt;CMake&lt;/a&gt; files and &lt;a href="http://code.google.com/p/cmake-lint/wiki/CMakeStyleGuide"&gt;suggest some better practices&lt;/a&gt;. It also comes with some handy &lt;a class="zem_slink" href="http://www.vim.org/" title="Vim (text editor)" rel="homepage"&gt;Vim&lt;/a&gt; plugins for working with CMake. One is a better version of the omni completion code I previously posted. The other is a :CMakeHelp command that helps you learn what all the CMake commands mean. There's no documentation for these plugins, but it should be obvious how they work. In Vim, type :CMakeHelp followed by the name of a command, or partial name and tab to complete. When you edit a CMakeLists.txt file, type CTRL-X CTRL-O to start up the omni completion.&lt;br /&gt;&lt;br /&gt;I wrote these Vim scripts because CMake is a pretty good build system but there aren't that many &lt;a class="zem_slink" href="http://en.wikipedia.org/wiki/Integrated_development_environment" title="Integrated development environment" rel="wikipedia"&gt;IDE&lt;/a&gt; tools available. Actually, CMake is about my favourite build system ATM, it's quite a close call with &lt;a class="zem_slink" href="http://code.google.com/p/waf/" title="Waf" rel="homepage"&gt;Waf&lt;/a&gt; though. CMake's cross-compiling is probably what just pips Waf for any new stuff I do.&lt;br /&gt;&lt;br /&gt;CMake lets you set up a regular build that compiles for the PC, and just by passing in the name of a file that describes a different compiler via the command line you can compile the same code for the DS. With Waf you have to faff about writing more code, cloning environments, fiddling with variants... That gets a bit messy and it's all manual, especially if you want to compile with debug flags too.&lt;br /&gt;&lt;br /&gt;Waf does ease the pain of integrating multiple modules inside the same source tree though, and it doesn't compile templates down to Make (which seems slightly crazy). Although &lt;a href="http://code.google.com/p/gyp"&gt;gyp&lt;/a&gt; also does similar craziness for &lt;a class="zem_slink" href="http://en.wikipedia.org/wiki/Google_Chrome" title="Google Chrome" rel="wikipedia"&gt;Google Chrome&lt;/a&gt;, but converts python templates to Makefiles, &lt;a class="zem_slink" href="http://www.scons.org/" title="SCons" rel="homepage"&gt;SCons&lt;/a&gt; input files (!) or proprietary IDE project files. Makes you wonder why they didn't just go with CMake and add to it. I would have liked to have seen a CMake generator that spat out SConstructs, for example.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-517544117724972155?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://code.google.com/p/cmake-lint/downloads/list' title='Lint and CMake'/><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/517544117724972155/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2009/06/lint-andcmake-lint-cmake.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/517544117724972155'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/517544117724972155'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2009/06/lint-andcmake-lint-cmake.html' title='Lint and CMake'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-848465043034299889</id><published>2009-04-26T16:21:00.010+02:00</published><updated>2009-07-03T15:55:48.038+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Git'/><category scheme='http://www.blogger.com/atom/ns#' term='Tools'/><category scheme='http://www.blogger.com/atom/ns#' term='Google Code'/><category scheme='http://www.blogger.com/atom/ns#' term='Mercurial'/><title type='text'>Mercurial</title><content type='html'>&lt;a class="zem_slink" href="http://code.google.com/" title="Google Code" rel="homepage"&gt;Google Code&lt;/a&gt; is going to add &lt;a class="zem_slink" href="http://en.wikipedia.org/wiki/Mercurial_%28software%29" title="Mercurial (software)" rel="wikipedia"&gt;Mercurial&lt;/a&gt; support soon, in fact it's already available for some pilot projects. I'm more familiar with &lt;a class="zem_slink" href="http://en.wikipedia.org/wiki/Git_%28software%29" title="Git (software)" rel="wikipedia"&gt;Git&lt;/a&gt; though, so I needed a good translation guide and I found the &lt;a href="http://wiki.sympy.org/wiki/Git_hg_rosetta_stone"&gt;Git HG Rosetta Stone&lt;/a&gt;. That isn't bad, but there are still some gaps, so I thought I'd share my experience fiddling around with Mercurial. To try and pad out some of those gaps. This is a big long dull technical entry. Sorry.&lt;br /&gt;&lt;br /&gt;The first thing I tried was to convert a small Git repository to Mercurial. The way to do this is to use &lt;a href="http://www.selenic.com/mercurial/wiki/index.cgi/ConvertExtension"&gt;the convert extension&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Now a bit of a rant about extensions here. This goes for Mercurial, but I think it applies to Bazaar too. Anyway, the issue I have is that in order to activate extensions in Mercurial, you have to add a line to a file in your home directory called .hgrc. This seems a bit anti intuitive to me. If these extensions are available in the core, and they are installed and everything, then why do I have to activate them by changing a preferences file? It's probably to keep the core set of commands simple or something, but it adds needless complexity to the whole process.&lt;br /&gt;&lt;br /&gt;The documentation on the conversion page mentions converting from &lt;a class="zem_slink" href="http://en.wikipedia.org/wiki/Concurrent_Versions_System" title="Concurrent Versions System" rel="wikipedia"&gt;CVS&lt;/a&gt;, &lt;a class="zem_slink" href="http://en.wikipedia.org/wiki/Subversion_%28software%29" title="Subversion (software)" rel="wikipedia"&gt;Subversion&lt;/a&gt; and Darcs, but there is no mention of converting from Git. I wonder if this is because nobody would really want to convert from Git to something else? ;-) Anyway, the conversion was easy for a trivial repository, just run "hg convert /path/to/repo".&lt;br /&gt;&lt;br /&gt;This creates a new directory repo-hg that contains your shiny new Mercurial-converted repository. The directory is initially empty, except for the .hg directory. That's equivalent to the .git directory in a git repository. The odd thing here is that running "hg status" on this empty directory reports no changes - compare this to a "git status" in the same situation, where it would say to you "hey, you've deleted all of your files!", and it seemed a little strange. You have to run "hg checkout" to get all your files back in the directory, which is pretty much the same as the "git reset --hard" idiom that you'd use in the same situation.&lt;br /&gt;&lt;br /&gt;Converting my Bunjalloo repository wasn't as easy. I've used a few branches, and some of the history came from subversion originally and there are strange tag/branches there. Mercurial doesn't seem to like this at all and just creates a load of branch-less "things". There's probably a good way to do this, but it would need some investigation.&lt;br /&gt;&lt;br /&gt;After compiling and running "hg status" I had a load of unknown files, marked with things like "?  build/foo.o". I tried the simplest solution: "mv .gitignore .hgignore". This almost worked, but it game me the following strange error:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;could not start inotify server: /tmp/repo-hg/.hgignore: invalid pattern (relre): *.[oa]&lt;br /&gt;abort: /tmp/repo-hg/.hgignore: invalid pattern (relre): *.[oa]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;By default Mercurial uses Python's regular expression syntax, not globs. That probably makes some sense, it means it was less effort to code I bet. The error message about inotify is a strange red herring though. The fix was to add a "syntax: glob" line to the file.&lt;br /&gt;&lt;br /&gt;After this I made a change in my code to see how Mercurial handles the normal workflow. Git's diff command shows differences in colour. Well, that's not quite true - by default it doesn't, you have to set a preference by running something like "git config color auto". Mercurial does colour too, you have to edit the .hgrc file adding "hgext.color=".&lt;br /&gt;&lt;br /&gt;All these properties and preferences can either go in your global $HOME/.hgrc file or in the repository-local .hg/hgrc file. There's no core "hg config" command, but there is an extension to do it. It is a second class citizen that isn't shipped with the core Mercurial and requires an extra not-core-Python library (I suspect this is why it isn't in the default Mercurial). In git you can run the core command "git config --global" to add a config option to your global file, or by default it changes the repository local configuration in the .git directory. It makes things a bit more newbie friendly than editing strange dot files. I can't imagine an ex-Subversion user being comfortable editing a file below .hg, for example. In subversion you just don't go futzing about in the .svn directories.&lt;br /&gt;&lt;br /&gt;Once all that was done, I decided to commit the change I had made. Here hg doesn't use git's staging area. That's fine. It is something that works well, but a lot of people don't get it. Mercurial uses the classic approach to this - pass what you want to commit on the command line - which works too. What I do miss here from git is the ability to run "commit -v". With the -v option, you get shown the patch that you are committing as well as the file names. This saves running "$VCS diff" in a separate shell, which is what I always ended up doing with Subversion. A definite regression from git here.&lt;br /&gt;&lt;br /&gt;After committing a change or two, I sometimes run gitk to see what is going on overall.  Mercurial ships "hgk" which is a really ancient version of gitk tuned for Mercurial commands instead of Git ones. Unfortunately it isn't turned on by default and, you guessed it, you have to edit the .hgrc file. Not only that, but the examples given in the Mercurial wiki are not entirely correct, at least when you install from source. They all state silly paths for hgk.py - the real location is $PREFIX/lib/python$VERSION/site-packages/hgext/hgk.py, where PREFIX is usually /usr/local and VERSION is the Python version, probably 2.5. But even if you set that in your .hgrc, "hg view" doesn't work. You need to copy the file "hgk" from the source contrib directory into your path. This is quite awkward. If something ships with the core, it should be installed and Just Work (TM).&lt;br /&gt;&lt;br /&gt;Sadly hgk is not very as good as the current gitk. It's missing a lot of the search options, the "you are here" yellow ball on the current&lt;br /&gt;checkout, status bars for slower updates, and probably some other features that I've forgotten for the moment. Running help says "About gitk" and shows that it is version 1.2 (C) 2005 - the current gitk must be about version 1.80 now and is in active development. The hgk equivalent is about 4 years behind and appears to be more or less abandoned.&lt;br /&gt;&lt;br /&gt;The other graphical interface that git has is the "git gui" command. This is really needed for managing the index well, adding chunks of patches and so on. The index is handled automatically in Mercurial, so that's a big chunk of usage that you wouldn't need a gui for. There is an extension - hg record - that emulates the "git add -i" behaviour for adding partial patches. A hg gui would be handy for using that recording extension, if nothing else, but there's nothing included by default. The only likely candidate is hgct, which has not been updated for a couple of years.&lt;br /&gt;&lt;br /&gt;Another command I use a lot is "git rebase -i". This lets you squash up commits, change the order of unrelated commits, drop patches, break&lt;br /&gt;up monolithic changesets into smaller ones, and so on. It is really good and easy to use. You run "git rebase -i someid" and get back a&lt;br /&gt;list of commits to do stuff with, something like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 255, 0);"&gt;&lt;b&gt;pick&lt;/b&gt;&lt;/span&gt; &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;84d3267&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt; Add the key release waits back in&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;squash&lt;/b&gt;&lt;/span&gt; &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;63656f4&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt; This seems to work on desmume at least&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 255, 0);"&gt;&lt;b&gt;pick&lt;/b&gt;&lt;/span&gt; &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;d34b4f3&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt; WIP, damn sprites do not show up...&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(128, 128, 255);"&gt;&lt;b&gt;edit&lt;/b&gt;&lt;/span&gt; &lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;c9b6718&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(255, 64, 255);"&gt;&lt;b&gt; Mostly works&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;# Rebase &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;7c1db7e&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;..&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;c9b6718&lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt; onto &lt;/b&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;7c1db7e&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;#&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;# Commands:&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;#  p, pick = use commit&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;#  e, edit = use commit, but stop for amending&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;#  s, squash = use commit, but meld into previous commit&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;#&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;# If you remove a line here THAT COMMIT WILL BE LOST.&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;# However, if you remove everything, the rebase will be aborted.&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 255, 255);"&gt;&lt;b&gt;#&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Mercurial doesn't have rebase, but on the other hand it does have the incomprehensible queues system. I've read the documentation, but I just don't get it at all. You need to remember a whole bunch of new Q commands, and you need to initialise the repository to tell it that you want to use queues. Then you can add, push and pop patches. I dunno. It just feels too heavyweight and requires too much planning up front.&lt;br /&gt;&lt;br /&gt;The rebase command was added to the git core late in the game, but it integrates seamlessly with everything else (except submodules, but&lt;br /&gt;git submodules have other problems anyway). You don't need to plan to use git-rebase, you just do it. The visualisation is done in your editor - you don't have to push and pop patches to get them in the right order. You just move them about as lines of text. If it all goes wrong, you can run "rebase --abort" and you don't get screwed over by having all these strange extra patch commits, which is what MQs tends to do.&lt;br /&gt;&lt;br /&gt;Now to push things to a new bitbucket account, since Google Code doesn't let everyone use Mercurial yet. Creating the empty repository on Bit Bucket was dead simple. Pushing was equally simple - hg push http://bitbucket.org/quirky/repo. You enter a username and password, which is far easier than the git equivalent, where you have to generate a ssh key, perhaps having to fiddle with ~/.ssh/config to tell it that SSH should use the user "git" when it connects to the github server, and so on. I can see how this would be simpler for someone used to Subversion over HTTP. The Mercurial documentation on the push command seems easier to follow than the git equivalent, too.&lt;br /&gt;&lt;br /&gt;Running that line will just push changes to the remote repository - it doesn't set up the remote branch, the equivalent of a "git remote add origin git@github.com:user/repo.git".  To do that you have to edit .hg/hgrc and add a "[paths]" section pointing to the remote URL. The convention here is to set the URL to a value "default". i.e.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;[paths]&lt;br /&gt;default = http://example.com/repo&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;To see which changes have not been pushed to the remote repo with git, you can use gitk or git log --decorate. Both of these show where the remote head is and where the local one is. By inspection you can tell which commits are missing from the remote branch. The equivalent in Mercurial is to use "hg outgoing", which tells you which changes have yet to be pushed. Ah, another difference for the gitk/hgk list here: hgk doesn't show the remote branches at all. Anyway, Mercurial's outgoing command is handy. You could mostly emulate it in git using "git log origin/master..HEAD", but you need to know the name of the remote branch, which is surprisingly non-trivial in some cases.&lt;br /&gt;&lt;br /&gt;Another feature of Git that I tend to use is for creating patches to send to other people. I mostly use this together with git-svn. That way I can clone a Subversion repository, make my local commits and then send patches of those commits off in bug reports or to mailing lists or whatever. This is "git-format-patch" and "git-send-email". Mercurial has a single command for that, "hg email". It's pretty much the same, but also sends email by default (like git-send-email). Sometimes you need to attach patches to HTML forms rather than emailing them, and so generating files is my preferred approach. By default git generates one file per commit - in fact I think that is the only way it works- Mercurial on the other hand only ever generates one file, with multiple patches inside. A nice option in Mercurial is "-o", which automatically generates the patches that are not upstream on the remote branch. Anyway, the command lines are subtly different, and the output is similar-but-not-the-same. Git has its single-patch approach, where you get out what you put in, plus it is less irritating in the number of questions it asks you (none). Mercurial creates a patch-bomb mbox and asks you for a To: email address, even if you don't want to email the file to anyone. It is probably a personal preference thing, but I like the way Git does it better here. They are both usable and scale better than "svn diff &gt; ~/whatever.patch".&lt;br /&gt;&lt;br /&gt;Another gotcha that caught me out was that "hg add" without arguments adds all untracked files for commit. This is like "git add .", but normally commands without arguments don't do naughty things. I didn't like the default behaviour here, it was too surprising. Especially if your hgignore file is not set up right. To fix it, you have to run "hg revert -a", which forgets about the added files.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Here's a big ol' list with the subtle, and not-so-subtle differences that bugged me. I really wanted to use a table, but blogger doesn't do tables without adding a bunch of blank lines...&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Git&lt;/b&gt; gitignore&lt;br /&gt;&lt;b&gt;Hg&lt;/b&gt; .hgignore, syntax: glob to get the same behaviour as git&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Git&lt;/b&gt; .git/config, ~/.gitconfig, use git-config to modify the values&lt;br /&gt;&lt;b&gt;Hg&lt;/b&gt; .hg/hgrc, ~/.hgrc, hg config is a non-core extension&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Git&lt;/b&gt; git commit -v&lt;br /&gt;&lt;b&gt;Hg&lt;/b&gt; hg diff | less; hg commit&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Git&lt;/b&gt; gitk&lt;br /&gt;&lt;b&gt;Hg&lt;/b&gt; hg view - there is some set up involving .hgrc and placing hgk in the path.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Git&lt;/b&gt; git rebase&lt;br /&gt;&lt;b&gt;Hg&lt;/b&gt; Mercurial Queues, kind of.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Git&lt;/b&gt; git push URL ; git remote add origin URL&lt;br /&gt;&lt;b&gt;Hg&lt;/b&gt; hg push URL; $EDITOR .hg/hgrc ; [paths] default = URL&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Git&lt;/b&gt; gitk, git log origin/master..HEAD&lt;br /&gt;&lt;b&gt;Hg&lt;/b&gt; hg outgoing&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Git&lt;/b&gt; git format-patch RANGE&lt;br /&gt;&lt;b&gt;Hg&lt;/b&gt; hg email -m filename -o&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Git&lt;/b&gt; git gui&lt;br /&gt;&lt;b&gt;Hg&lt;/b&gt; Nothing equivalent. There's "hg record" for "git add -i", but it is less user friendly.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Git&lt;/b&gt; git add . ; Note the dot&lt;br /&gt;&lt;b&gt;Hg&lt;/b&gt; hg add ; No dot needed. Take care with that! You'll have to run "hg revert" to fix the mess&lt;br /&gt;&lt;br /&gt;The main arguments for using Mercurial over Git are better Windows support and ease of use. I can't comment on how well either work on Windows, but for Linux Mercurial worked more or less as expected. The second argument about hg being much easier than git... I don't know. Maybe. I'm tainted now that I more or less grok DVCS. But given the difficulty in setting up most of the core plugins and the lack of good core GUIs (gitk/git-gui), I disagree. The basic work flow is more or less the same, but Git has this batteries included feel while Mercurial is more limited. Mostly by default, by enabling optional extensions there isn't that much real difference. Besides, I think that for someone used to Subversion who has never used DVCS, either tool would be overwhelming at first.&lt;br /&gt;&lt;br /&gt;What I do know is that the GUI tools that come with Git are a huge help for getting up to speed with what is going on "under the hood". Seeing all the commits and their hierarchy in gitk is far easier than reading the log or viewing the gitweb page. Especially if you start doing rebases and history changing stuff. Maybe Mercurial's one-branch approach and lack of history-munging commands makes all these extras unnecessary. Who knows. Time will probably tell.&lt;br /&gt;&lt;br /&gt;Either way it's time to get stuck in to learning Mercurial. I'll definitely start using Mercurial when Google Code offers it to everyone, because the current github/GC integration works but it's a bit ad-hoc. It's missing automatic links from issues to commits, the source tab looks a bit wrong, the Updates feed doesn't update, little things like that. I like the Github UI for code - you get the last change right there on the front page - but for non coders, I think it could be a bit daunting. Google Code's interface is cleaner and easier to navigate. Also subversion is missing features like real tags (no the /tags directory is not the same) and a couple of projects I've got on GC still use the default Subversion just because it's easier to set up and everything. Mercurial will be a nice bonus feature.&lt;br /&gt; &lt;div style="margin-top: 10px; height: 15px;" class="zemanta-pixie"&gt;&lt;a class="zemanta-pixie-a" href="http://reblog.zemanta.com/zemified/7c197120-dfec-4980-ad59-79a6ccfda8f7/" title="Reblog this post [with Zemanta]"&gt;&lt;img style="border: medium none ; float: right;" class="zemanta-pixie-img" src="http://img.zemanta.com/reblog_e.png?x-id=7c197120-dfec-4980-ad59-79a6ccfda8f7" alt="Reblog this post [with Zemanta]" /&gt;&lt;/a&gt;&lt;span class="zem-script more-related pretty-attribution"&gt;&lt;script type="text/javascript" src="http://static.zemanta.com/readside/loader.js" defer="defer"&gt;&lt;/script&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-848465043034299889?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/848465043034299889/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2009/04/mercurial.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/848465043034299889'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/848465043034299889'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2009/04/mercurial.html' title='Mercurial'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-8836341148231061179</id><published>2009-04-07T23:22:00.004+02:00</published><updated>2009-11-06T22:50:36.405+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DS'/><category scheme='http://www.blogger.com/atom/ns#' term='Elite'/><title type='text'>Elite DS version 0.6</title><content type='html'>I've just cooked up a &lt;a href="http://code.google.com/p/ds-elite/downloads/detail?name=eliteagb-0.6.zip"&gt;new release of Elite DS&lt;/a&gt;. This adds the music back in that I had to take out when my own GBA XM library proved too tricky/time consuming to port to the DS. I've updated the code so that it compiles with &lt;a href="http://www.devkitpro.org/"&gt;devkitARM r25&lt;/a&gt; and the sound now uses devkitpro's default ARM7 core.&lt;br /&gt;&lt;br /&gt;From a technical POV the changes aren't very interesting, but I'll waffle on about them anyway!&lt;br /&gt;&lt;br /&gt;Prior to this release, I was using the DS's PSG sound system. This is the bleep-bleep-bleep square/triangle wave sound system that Nintendo has used in its handhelds since the dawn of time. I think it is pretty much unchanged since the original Gameboy ;-) The good thing about this "format" is that it is small - you can say "use this pitch", "play it!", "hold it!" in just a few bytes and the sound lasts ages. You just change the pitch after a given length of time to add new exciting effects. The bad part is that it sounds terrible! Also, the sound format is completely arbitrary/homegrown as you have to just poke registers with values to make the DS go BEEP.&lt;br /&gt;&lt;br /&gt;Additional amusement creeps in as you have to poke the sound registers on the ARM7, but the sound events trigger on the ARM9. Like when you get shot or fire a laser. I used the inter-processor FIFO to pass the "bleep now dammit!" messages from the '9 to the '7. Most of the sounds were taken from running Elite under emulation in pocket beeb, capturing the sound values that were written to the BBC sound registers, converting them into the equivalent values for the DS registers and then using these values in Elite DS. They sound more or less like the original BBC sounds this way. This is not necessarily a good thing :-)&lt;br /&gt;&lt;br /&gt;The new sound effects were easier to create. I used &lt;a href="http://www.cyd.liu.se/%7Etompe573/hp/project_sfxr.html"&gt;this simple (to use) sound generator&lt;/a&gt;. I spent a pleasant afternoon creating random sounds, some of which may be slightly above the "terrible" level. I forget where I stole the Elite music files from, I think they are nabbed from the NES version. Of course on the DS these all use the fantastic maxmod library. I wish this had been available years ago, it is very easy to use and works exceptionally well.&lt;br /&gt;&lt;br /&gt;Ah, there was one random bug that had me scratching my head for a while - I used to use a &lt;a href="http://code.google.com/p/ds-elite/source/browse/trunk/eliteagb/clear.S?spec=svn123&amp;amp;r=123"&gt;bit of assembler to clear the screen&lt;/a&gt;. This sets all the ARM registers to zero and creates an unrolled loop to blit these zeroes to the video RAM. For some reason it caused crashes on hardware when I started using maxmod. The only thing I can think of is that somehow registers were getting clobbered that maxmod uses in an interrrupt, or vice versa. My fix was to replace that clear screen routine with a DMA fill. Speed is not an issue on the DS compared to the GBA :-) It's a bit &lt;a href="http://en.wikipedia.org/wiki/Cargo_cult_programming"&gt;cargo-culty&lt;/a&gt; but I was desperate and with that register-clobbering explanation I sort of convinced myself. Anyway, I've been playing 0.6 all afternoon and it hasn't shown any more crashes (of the game; there have been colisions between myself and a few Cobra Mk IIIs). Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-8836341148231061179?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://code.google.com/p/ds-elite/downloads/detail?name=eliteagb-0.6.zip' title='Elite DS version 0.6'/><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/8836341148231061179/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2009/04/elite-ds-version-06.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/8836341148231061179'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/8836341148231061179'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2009/04/elite-ds-version-06.html' title='Elite DS version 0.6'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-6957744579606492153</id><published>2009-04-05T15:56:00.007+02:00</published><updated>2009-04-08T00:13:43.960+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Review'/><category scheme='http://www.blogger.com/atom/ns#' term='DSi'/><title type='text'>DSi thoughts</title><content type='html'>I'm fairly weak and couldn't &lt;a href="http://twitter.com/richq/status/1447827754"&gt;resist buying a new DSi on Friday&lt;/a&gt; when it was released here in Spain (and indeed, the rest of Europe). Here are my impressions of the new console. Keep in mind that I have never owned a DS lite, if that makes a difference.&lt;br /&gt;&lt;br /&gt;First of all the bad news: my EZ Flash V doesn't work with the DSi. I knew this would be the case, but had to check anyway. The card is recognised on the menu, but when selected an error message immediately appears. Oh well, I still have the phat DS for homebrew until someone hacks the DSi.&lt;br /&gt;&lt;br /&gt;The console itself has a most peculiar finish to it. It's as if the plastic used is "fuzzy". I don't really know how to describe the feeling that you get when you touch the outer case, but it sets my teeth on edge somewhat. Rather like touching polystyrene or chalk.&lt;br /&gt;&lt;br /&gt;Once you boot up, the main menu is a new version of the old firmware. I'd completely forgotten about the new-world paranoia too, all those messages about health and safety that loopy's firmware hacks got rid of so many years ago are of course back on the 'i. And there doesn't seem to be a way to get the console to boot directly to the inserted game. You always have to go through the menu.&lt;br /&gt;&lt;br /&gt;This menu also has options for the camera, the sound thing, connect to the DSi shop, as well as the old DS download play and pictochat that have been there since day 1 (and nobody actually uses). In addition, any downloaded games from the store appear on this menu in their own icon.&lt;br /&gt;&lt;br /&gt;A new feature that was long overdue is in the way the wifi-settings are changed. Rather than have every game that needs to connect to the internet reimplement the settings screen, the firmware itself has a way to update them. This is a good move, although all the existing DS games will still use a different method to the new built in one, even if the settings themselves are stored the same way in the internal memory.&lt;br /&gt;&lt;br /&gt;The first thing I did was to download the new Web Browser application for free from the DSi shop. The browser is based on Opera 9.50 and is pretty nifty. More on that in a minute though. First off, it seems that the firmware itself is updateable. The first time you connect to the "DSi Ware" shop, it updates the system. This means that any future firmware-hacks to get homebrew running will be an inevitable arms war with Nintendo. A bit sad really. If the shop were done correctly (i.e. like the Apple app store or the Android equivalent) then the DSi could have been an amazing platform for homebrew. But Nintendo are real control freaks, they make Apple look like some bunch of free for all hippies. For example, before you connect to the DSi Ware store, you have to agree to some sort of Excentric Unenforceable Licence Agreement (or "EULA" as they are known). One of the clauses states that if you sell your DSi you must erase any software you have downloaded from the shop first, as the right to use the software is not transferable. It's quite clear that Nintendo do not want to sell you games, but to sell you a licence to play a game on a given console.&lt;br /&gt;&lt;br /&gt;I must say that when you download a game or program from the DSi Ware store, the "progress bar" is great!&lt;br /&gt;&lt;br /&gt;I haven't really tried out the built in sound program/toy thing, so no comments on that.&lt;br /&gt;&lt;br /&gt;The cameras that are built in are low res - I've seen ambiguous reports on the interwebs that one of them is 0.3 megapixels and the other is 3.0 megapixels. I can confirm that they are both lame-oh 0.3 megapixels. Never mind, they work quite well for the amusing games and stuff that are available at the moment.&lt;br /&gt;&lt;br /&gt;You can store your photos onto either internal storage, of which there is about 32MB, or onto SD cards that fit into the side of the console. The internal storage is shared with applications that you download from the store. &lt;strike&gt;Once again, Nintendo have screwed up by making it impossible to save these games to the SD card! They made this mistake on the Wii and have repeated it here with the DSi.&lt;/strike&gt; Update: I have discovered the option hidden away in the settings menu to copy the applications over to the SD card. By default they are stored internally, but it seems that lessons have been learnt since the Wii.&lt;br /&gt;&lt;br /&gt;Speaking of cock ups.... There is no way, via either the camera tool or via the Web Browser, to upload your photos to any sort of web site or anything. For example, in gmail the "attach file" control is greyed out - the browser doesn't implement the &lt;span style="font-style: italic;"&gt;input type="file"&lt;/span&gt; form element.&lt;br /&gt;&lt;br /&gt;The camera software lets you trade images locally, i.e. with other DSi users in the same room, but that is all. Hilariously there is another paranoid legalese message when you try to do this: "you acknowledge that you are entitled to distribute these photos and frames and agree that they may be modified, distributed and/or posted by the recipient and/or third parties." Given that you can only exchange the photos with someone stood next to you, this seems a bit overkill to me. &lt;span style="font-weight: bold;"&gt;A console that has a camera and is wifi enabled, but has no way to send those photos via the intertubes seems like a huge missed oportunity to me.&lt;/span&gt; I look forward to some homebrew program that will allow us to do this. Oh. No. Homebrew doesn't run on the DSi. Gah!&lt;br /&gt;&lt;br /&gt;You get 1000 "free" points for the store when you first connect to it. Free as in "you just payed 170 euros for the console, the least we can do is give you some cheapo games for it". Apart from a couple of rehashes (Pyoro, Paper Plane) and some puzzle games (I'm more than fed up with brain draining), there is a Wario game that makes use of the camera, "Warioware: Snapped!" it is called. I wish I had read &lt;a href="http://dsiware.nintendolife.com/reviews/2009/04/warioware_snapped_dsiware"&gt;this review (rating: 4/10)&lt;/a&gt; before downloading it though. It is amusing for a few minutes, but has no replay value and is not even very practical to play. I get the feeling that this is going to be the pinnacle of camera based games on the DSi, however. It plays similar to the eye-toy games on the Playstation, with the added irritation of the screen being tiny. On the plus side, the replay mode at the end of each round is amusingly done.&lt;br /&gt;&lt;br /&gt;The first DS game I plugged in to the 'i was &lt;a href="http://www.atlus.com/etrian2/"&gt;Etrian Odyssey II&lt;/a&gt;. It ran fine, so at least the much touted region lock out is not applied retro-actively. I'm on to the 4th stratus, which (if you forgive the minor spoiler) has some quite colourful cherry blossoms and trees. On the DSi they really are extra colourful. The new screen is a lot clearer than the phat one.  Even on brightness 1, the lowest, it is brighter than the phat DS screen. The size is slightly larger too, but not so much that it makes any difference. Even side by side it is difficult to notice the difference. I suppose it couldn't be made too big at the same resolution or games would start looking pixelated.&lt;br /&gt;&lt;br /&gt;So all in all what do I think of the DSi? Well, as an upgraded DS it is OK if you don't have a DS lite, which I don't. The lack of uploadable photos from the camera is a missed opportunity, what with everyone having Facebook accounts and whatnot nowadays. The browser is cool, even if it does run out of memory when reading pages on blogger.com. In column mode it feels a lot like Bunjalloo ;-) of course these Opera guys have a lot more resources than I do to get things right. They also have Nintendo breathing down their necks, so get things (like no file uploads) wrong too. I wonder if their will be updates to the browser? Given that it is stored in RAM, rather than ROM, it is possible that new versions will appear. Given how tightly Nintendo control everything, together with their restrictive software quality control process - which would make even minor upgrades an expensive effort for Opera -, I won't hold my breath.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-6957744579606492153?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/6957744579606492153/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2009/04/dsi-thoughts.html#comment-form' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/6957744579606492153'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/6957744579606492153'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2009/04/dsi-thoughts.html' title='DSi thoughts'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-6834177662252910287</id><published>2009-04-02T22:35:00.006+02:00</published><updated>2009-04-07T23:58:08.028+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SCons'/><title type='text'>Avoid hard coded variant directories by using a SCons Repository</title><content type='html'>One of the things about &lt;a href="http://www.scons.org/"&gt;SCons&lt;/a&gt; that I didn't like was that by default it built your object files in the same directory as your source code. This means you end up with this:&lt;br /&gt;&lt;pre&gt;src/foo.c&lt;br /&gt;src/foo.o&lt;br /&gt;&lt;/pre&gt;Your ${VCS} status output would be full of this sort of thing:&lt;br /&gt;&lt;pre&gt;Untracked files:&lt;br /&gt;&lt;span style="color: rgb(51, 102, 255);"&gt;? src/foo.o&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;Tab completion would stop at &lt;span style="font-style: italic;"&gt;vi src/foo.&lt;/span&gt;, grep would add spurious "&lt;span style="font-style: italic;"&gt;Binary file foo.o matches&lt;/span&gt;". Yuck, what &lt;span style="font-weight: bold;"&gt;a mess&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Then you discover &lt;a href="http://www.scons.org/doc/production/HTML/scons-user/c3271.html#AEN3283"&gt;VariantDir in the SCons documentation&lt;/a&gt; and this looks great. You add &lt;span style="font-style: italic;"&gt;variant_dir="build"&lt;/span&gt;, quickly followed by &lt;span style="font-style: italic;"&gt;duplicate=False&lt;/span&gt;, and all is well. However, this hard coding of "build" is a bit lame. Think about &lt;a href="http://en.wikipedia.org/wiki/GNU_build_system"&gt;autotools&lt;/a&gt; - you could build out-of-source to any directory you liked...&lt;br /&gt;&lt;pre&gt;mkdir /tmp/build&lt;br /&gt;cd /tmp/build&lt;br /&gt;/path/to/source/configure &amp;amp;&amp;amp; make&lt;br /&gt;&lt;/pre&gt;Wouldn't it be great if SCons could do this?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;It can!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is a little known feature that I recently stumbled upon completely by chance. Assuming the code is in ~/projects/code, the &lt;span&gt;magic incantation&lt;/span&gt; is as follows:&lt;br /&gt;&lt;pre&gt;scons -Y ~/projects/code -f ~/projects/code/SConstruct&lt;br /&gt;&lt;/pre&gt;This uses a SCons secret weapon - &lt;a href="http://www.scons.org/doc/production/HTML/scons-user/c3810.html"&gt;Repositories&lt;/a&gt;. As a bonus, this particular feature is not even mentioned in the documentation. It means you can compile into any directory using the original source code. The explanation is that the options do the following:&lt;br /&gt;&lt;pre&gt;&lt;span style="font-style: italic;"&gt;-Y REPOSITORY&lt;/span&gt; Search REPOSITORY for source and target files.&lt;br /&gt;&lt;span style="font-style: italic;"&gt;-f FILE&lt;/span&gt; Read FILE as the top-level SConstruct file.&lt;br /&gt;&lt;/pre&gt;By saying &lt;span style="font-style: italic;"&gt;use this SConstruct to build the code&lt;/span&gt; and &lt;span style="font-style: italic;"&gt;if you don't find a file, look here&lt;/span&gt;, you emulate the autotools/CMake out-of-source behaviour almost perfectly. If the command line looks long, just add --interactive. That way hitting "b" and enter will rebuild.&lt;br /&gt;&lt;br /&gt;Hang on, because there are 2 caveats.&lt;br /&gt;&lt;br /&gt;First, you have to be careful that when you specify files that are not handled natively by SCons that you use the right names, i.e. in your own Builders. Also internal include directories should use # so that they mean "from the top of the source tree" rather than from the top of the build tree. That means &lt;span style="font-style: italic;"&gt;env.Append(CPPPATH=['#mylib'])&lt;/span&gt; instead of just "mylib".&lt;br /&gt;&lt;br /&gt;Secondly, and more annoyingly, the &lt;span style="font-weight: bold;"&gt;build directory can't be below&lt;/span&gt;&lt;span style="font-weight: bold;"&gt; the source directory&lt;/span&gt;. SCons gets all confused and starts putting another build directory in your build directory (so you can build while you build). But then crashes out saying it can't find the source code. Boo!&lt;br /&gt;&lt;br /&gt;Apart from that, you're good to go.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-6834177662252910287?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/6834177662252910287/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2009/04/avoid-hard-coded-variant-directories-by.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/6834177662252910287'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/6834177662252910287'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2009/04/avoid-hard-coded-variant-directories-by.html' title='Avoid hard coded variant directories by using a SCons Repository'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-3509760535761014493</id><published>2009-03-14T17:07:00.005+01:00</published><updated>2009-04-07T23:58:33.879+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CMake'/><category scheme='http://www.blogger.com/atom/ns#' term='Vim'/><title type='text'>Vim omni completion for CMake</title><content type='html'>As &lt;a href="http://www.cmake.org/"&gt;CMake&lt;/a&gt; uses its own language, learning what commands are available can be a bit of a pain. I've written &lt;a href="http://github.com/quirky/userscripts/blob/90f83b281214ad904f55741e1348edd25c09dcf4/vim/cmakecomplete.vim"&gt;this really basic Vim omni completion plugin&lt;/a&gt; that takes some of the effort out of getting to know the API.  Install the file to the autoload directory in your .vim directory, i.e in ~/.vim/autoload/, and add the following line to your .vimrc file&lt;br /&gt;&lt;pre&gt;  &lt;span style="color: rgb(255, 102, 0);"&gt;autocmd&lt;/span&gt; &lt;span style="color: rgb(0, 255, 0);"&gt;FileType&lt;/span&gt; cmake &lt;span style="color: rgb(255, 102, 0);"&gt;set&lt;/span&gt; &lt;span style="color: rgb(255, 64, 255);"&gt;omnifunc&lt;/span&gt;=cmakecomplete#Complete&lt;br /&gt;&lt;/pre&gt;Now when you edit a CMakeLists.txt file, it should do omni completion when you summon help with the Ctrl-X Ctrl-O enchantment. Maybe someone will find it useful.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_nzN39P0Ykuk/SbvYGf5dZjI/AAAAAAAAA9k/RxtnRYoGuhM/s1600-h/cmake.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 300px;" src="http://4.bp.blogspot.com/_nzN39P0Ykuk/SbvYGf5dZjI/AAAAAAAAA9k/RxtnRYoGuhM/s320/cmake.png" alt="" id="BLOGGER_PHOTO_ID_5313077791566947890" border="0" /&gt;&lt;/a&gt;I've only tested this with the latest CMake and Vim versions, it is quite likely that I assume things that do not work in earlier editions of these programs. Patches welcome ;-)&lt;br /&gt;&lt;br /&gt;Edit: Updated to add property and module completion&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-3509760535761014493?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://github.com/quirky/userscripts/blob/90f83b281214ad904f55741e1348edd25c09dcf4/vim/cmakecomplete.vim' title='Vim omni completion for CMake'/><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/3509760535761014493/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2009/03/vim-omni-completion-for-cmake.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/3509760535761014493'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/3509760535761014493'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2009/03/vim-omni-completion-for-cmake.html' title='Vim omni completion for CMake'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_nzN39P0Ykuk/SbvYGf5dZjI/AAAAAAAAA9k/RxtnRYoGuhM/s72-c/cmake.png' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-8677109350900615703</id><published>2009-02-14T12:57:00.013+01:00</published><updated>2009-04-07T23:59:20.033+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Waf'/><category scheme='http://www.blogger.com/atom/ns#' term='Eclipse'/><title type='text'>Notes on Eclipse CDT</title><content type='html'>It has been a while since I last tried out &lt;a href="http://www.eclipse.org/cdt/"&gt;Eclipse CDT&lt;/a&gt;. I've been using Eclipse at work recently for Java and RCP stuff, so I thought I'd give CDT another go. I prefer Vim, but I don't mind trying new things. So I thought I'd try it out for my homebrew stuff.&lt;br /&gt;&lt;br /&gt;Eclipse for Java is actually pretty good. When you write Eclipse plug-ins you usually have to implement a load of seemingly random interfaces. There are project wizards in Eclipse that generate all the necessary stubs and what-not for you. Then once your project is underway, the editor has all sorts of auto-completion and javadoc "hints" to help you figure out the &lt;a href="http://en.wikipedia.org/wiki/API"&gt;API&lt;/a&gt;. The facetious among you may say that all these crutches are necessary because the Eclipse API is not discoverable enough. I might not argue with you, but I've seen some terrible C++ libraries in my time too.&lt;br /&gt;&lt;br /&gt;Now I am not a big Java coder. I mostly write C++, with a bit of Python. In Vim I can emulate a lot of what Eclipse does for Java, but for C++. &lt;a href="http://ctags.sourceforge.net/"&gt;Exuberant CTAGS&lt;/a&gt; is a marvelous help for doing this. Coupled with Vim's omni-complete, you can have a lot of context sensitive auto-completion for C++ code. The completion in Vim also gracefully degrades to just regular context-insensitive completion. So even if it doesn't complete your class based on its available member variables and methods, Vim completes based on the contents of the current buffer, or loaded buffers, or included files. Most of the time this achieves what you want.&lt;br /&gt;&lt;br /&gt;By the way, to set up omni-completion in Vim for C++ you need to do a couple of things. First you need a modern Vim. Version 7.1 or so should do. Then you need to either pass these flags to ctags, or create a $HOME/.ctags file:&lt;br /&gt;&lt;pre&gt;--c++-kinds=+p&lt;br /&gt;--fields=+iaS&lt;br /&gt;--extra=+q&lt;/pre&gt;Now run "ctags -R ." in your source code tree. That creates a tags file with the index that Vim uses to auto complete. Armed with that knowledge, you can create tags files for the STL to have auto-completed vectors, lists, strings and so on. Using g] in Vim it jumps to methods, variables and defines.&lt;br /&gt;&lt;br /&gt;OK, back to the story. I'm trying to use Eclipse CDT for C++ to see how it compares to my Vim setup. This &lt;a href="http://www.ibm.com/developerworks/aix/library/au-unix-eclipse/"&gt;article from IBM&lt;/a&gt; describes how to compile UNIX software from Eclipse using the C++ IDE. Instead of using make directly, it recommends using ant to call configure and then make. That's quite novel and it "works" insomuch that your code compiles, but it isn't very good for proper coding. The main issue is that the errors from ant are not parsed into clickable quick fix errors. In other words, if you screw up and your code doesn't compile the errors are not highlighted in the editor as they should be.&lt;br /&gt;&lt;br /&gt;Aha! But I don't use make. I use &lt;a href="http://code.google.com/p/waf/"&gt;waf&lt;/a&gt; for bunjalloo. The waf interface is almost identical to make. In Vim I use "set makeprg=waf" so that running ":make" compiles my code. I realised that I could do the same thing in Eclipse, and here's how.&lt;br /&gt;&lt;br /&gt;Before starting anything I did what I normally do to install new programs on Ubuntu; I opened up &lt;a href="http://www.nongnu.org/synaptic/"&gt;Synaptic&lt;/a&gt;. Sadly Ubunutu 8.04 has an ancient version of Eclipse (3.2.2! That's from the middle ages, held together with wattle and daub). I made like I was using Windows and went off to the Eclipse web site to download the latest release, which is 3.4.1 at the time of writing. Excellently this is just a big fat tarball, so you can unpack it in /opt or wherever you like and it runs. No dependencies and with batteries included.&lt;br /&gt;&lt;br /&gt;Now I had to get my code into Eclipse. There's a bit of irritation involved with this. Eclipse insists on copying your files into its own workspace, even if you already have a perfectly good space for working available. My plan here was to create a new workspace, use the import tools to copy the code there, then manually copy the secret Eclipse project files back to my regular directory. I could then import the original directory as an already existing project. Convoluted, but I just don't trust Eclipse not to bork up my files while it whispers softly "it's for your own good..."&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 1.&lt;/span&gt; Start Eclipse and tell it the workspace to use&lt;br /&gt;&lt;pre&gt;eclipse -data /tmp/workspace&lt;/pre&gt;This was a throwaway workspace that I wouldn't use once the project files had been created.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 2.&lt;/span&gt; Create a new C++ project in Eclipse. This has to be an empty Makefile project.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_nzN39P0Ykuk/SZa0d0w1aqI/AAAAAAAAA8M/P0pS1BP5Ffs/s1600-h/Screenshot-C%2B%2B+Project+.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 300px; height: 320px;" src="http://1.bp.blogspot.com/_nzN39P0Ykuk/SZa0d0w1aqI/AAAAAAAAA8M/P0pS1BP5Ffs/s320/Screenshot-C%2B%2B+Project+.png" alt="Create empty C+ project" id="BLOGGER_PHOTO_ID_5302624035748014754" border="0" /&gt;&lt;/a&gt;This created an empty project that would not be managed by Eclipse's internal builder. Eclipse just calls "make all" and crosses its fingers.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 3.&lt;/span&gt; Add the source code. I used the Import &gt; General &gt; File System option.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_nzN39P0Ykuk/SZa1FlmyxeI/AAAAAAAAA8U/E5J1puwHas4/s1600-h/Screenshot-Import+.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 300px; height: 320px;" src="http://1.bp.blogspot.com/_nzN39P0Ykuk/SZa1FlmyxeI/AAAAAAAAA8U/E5J1puwHas4/s320/Screenshot-Import+.png" alt="Import Files" id="BLOGGER_PHOTO_ID_5302624718874133986" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;This copied all the code into the /tmp/workspace/project folder.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Step 4.&lt;/span&gt; Set up waf as an alternative to make&lt;br /&gt;&lt;br /&gt;To do this, I only needed to change "make" to "waf", and change the default incremental build target to be "build" instead of "all". This is done from the Project &gt; Properties &gt; C/C++ Build. In Builder Settings, uncheck "use default command" and change "make" to "waf". From the Behaviours tab, change the "all" target to "build".&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_nzN39P0Ykuk/SZa2aZxZcqI/AAAAAAAAA8c/yeAlyoUfmao/s1600-h/Screenshot-Properties+for+bunjalloo+.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; cursor: pointer; width: 320px; height: 238px;" src="http://3.bp.blogspot.com/_nzN39P0Ykuk/SZa2aZxZcqI/AAAAAAAAA8c/yeAlyoUfmao/s320/Screenshot-Properties+for+bunjalloo+.png" alt="" id="BLOGGER_PHOTO_ID_5302626175986266786" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_nzN39P0Ykuk/SZa2hM4KPQI/AAAAAAAAA8k/dDQj09b1Xpg/s1600-h/Screenshot-Properties+for+bunjalloo+-1.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; cursor: pointer; width: 320px; height: 238px;" src="http://3.bp.blogspot.com/_nzN39P0Ykuk/SZa2hM4KPQI/AAAAAAAAA8k/dDQj09b1Xpg/s320/Screenshot-Properties+for+bunjalloo+-1.png" alt="" id="BLOGGER_PHOTO_ID_5302626292784053506" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;At this point I was almost done. However first I had to add the configuration step in. Waf, like autotools, first configures the environment to see where your compilers, libraries and other tools are installed. This is done by running "waf configure" from the command line. I added a new Make target "configure" to do this. That's right click on the project &gt; Make Targets &gt; Create... In the dialog, I added "configure" in both the target fields.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_nzN39P0Ykuk/SZb0WOTh1aI/AAAAAAAAA8s/vrr-S8mmaBs/s1600-h/Screenshot-Create+a+new+Make+target+.png"&gt;&lt;img style="cursor: pointer; width: 156px; height: 200px;" src="http://2.bp.blogspot.com/_nzN39P0Ykuk/SZb0WOTh1aI/AAAAAAAAA8s/vrr-S8mmaBs/s200/Screenshot-Create+a+new+Make+target+.png" alt="" id="BLOGGER_PHOTO_ID_5302694273909642658" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;I ran the "configure" target first, then ran "build" as normal. With this done, the whole thing was compiled.&lt;br /&gt;&lt;br /&gt;Now that everything was set up, I could use the project files created by Eclipse. These are called .project and .cproject. The .project file is pretty light weight and describes the project basics. But &lt;a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=226457"&gt;the .cproject file is a mess&lt;/a&gt;. 276 lines of incomprehensible XML, with all sorts of redundant and machine-specific configuration information encrusted in it. Yuck. It also changes "randomly" when you alter minor details in the project. This makes it really unsuitable for storing in version control, but without it the whole CDT project is useless. A hairy dilemma, and one that doesn't occur in the Eclipse Java IDE, where the .project file is pretty stable.&lt;br /&gt;&lt;br /&gt;I just completely ignored this problem and I copied the project metadata files to the original location of the project in $HOME/src/ndsdev/ anyway. This is to make sure I can re-import the project using just these files. I restarted Eclipse, using a different workspace now (the default $HOME/workspace), and used the "import existing project" option. This all went well. I now had all my code in Eclipse in its original location, compiling, running, and so on.&lt;br /&gt;&lt;br /&gt;I then wanted to fiddle around, see what Eclipse could do with C++. The first problem I hit was a lot of "unresolved inclusion" errors. This occurs when the #include files cannot be found. As I wasn't using Eclipse's managed build, my project compiles OK but Eclipse is ignorant to the actual internal paths my Makefiles, er, wscripts use. To fix this, I had to add the project include paths using the Properties &gt; C/C++ General &gt; Paths and Symbols setup page.&lt;br /&gt;&lt;br /&gt;Next up, I thought I'd try out the auto completion. What a disappointment! Compared to the Java equivalent, which has an almost 6th sense ability to guess what you are trying to write, the CDT version is hobbled. My Vim+CTAGS solution works much better. As an example, say we have this code:&lt;br /&gt;&lt;pre&gt;&lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;class&lt;/b&gt;&lt;/span&gt; Test {&lt;br /&gt;&lt;span style="color: rgb(255, 255, 0);"&gt;&lt;b&gt;public&lt;/b&gt;&lt;/span&gt;:&lt;br /&gt;Test();&lt;br /&gt;&lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; getValue() &lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;const&lt;/b&gt;&lt;/span&gt; {&lt;br /&gt; &lt;span style="color: rgb(255, 255, 0);"&gt;&lt;b&gt;return&lt;/b&gt;&lt;/span&gt; m_&lt;br /&gt;}&lt;br /&gt;&lt;span style="color: rgb(255, 255, 0);"&gt;&lt;b&gt;private&lt;/b&gt;&lt;/span&gt;:&lt;br /&gt;&lt;span style="color: rgb(0, 255, 0);"&gt;&lt;b&gt;int&lt;/b&gt;&lt;/span&gt; m_value;&lt;br /&gt;};&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_nzN39P0Ykuk/SZb1Qi960RI/AAAAAAAAA88/9lFH-3bSc4c/s1600-h/eclipse-complete.png"&gt;&lt;img style="cursor: pointer; width: 320px; height: 247px;" src="http://1.bp.blogspot.com/_nzN39P0Ykuk/SZb1Qi960RI/AAAAAAAAA88/9lFH-3bSc4c/s320/eclipse-complete.png" alt="" id="BLOGGER_PHOTO_ID_5302695275888562450" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;the cursor is at the end of "m_" and I press Ctrl+Space to auto-complete, but I get told that there are no proposals. What about that m_value just 4 lines down, eh? Gah. You can "fix" this by placing the definition of m_value above where we were trying to use it, but that's just silly.&lt;br /&gt;&lt;br /&gt;Another niggle I have is with the cut and paste mechanism. In Vim, yy, dd and pp all copy, cut and paste entire lines - from the very left of the screen to the end of the line. In Eclipse however, the keyboard shortcut for cutting a line is not enabled by default, copying a line with ctrl-alt-down results in a copy directly below where the line was, which you can then ctrl-x cut. But pasting is awkward - the cursor jumps about unexpectedly to an indented place, and it is very easy to add unwanted blanks at the end of text. Perhaps this just requires getting used to, but it feels weird and icky.&lt;br /&gt;&lt;br /&gt;The other nice feature in Java is the documentation hints for filling out constructors and functions. There's an option to support Doxygen (Properties&gt;C++ General), but it doesn't seem to make any difference. I've Doxygenized most of my headers, and Woopsi also uses the convention, but when I hover over a method that has documentation it just shows the implementation and leading comment. Fair enough, you get some idea of what is needed, but it'd be nicer if it showed the actual documentation.&lt;br /&gt;&lt;br /&gt;Finally I tried some of that cool refactoring that the hip kids are all talking about. I found method that was looking a bit full, selected a portion of code and hit Refactor &gt; Extract function. This was in a class method and the code used member variables. Ideally refactor would create a new method and add the prototype to the header file (no chance!). The dialog was disconcerting:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_nzN39P0Ykuk/SZb3qzPGxRI/AAAAAAAAA9E/-KiBEjE4910/s1600-h/Screenshot-Refactoring+.png"&gt;&lt;img style="cursor: pointer; width: 320px; height: 233px;" src="http://2.bp.blogspot.com/_nzN39P0Ykuk/SZb3qzPGxRI/AAAAAAAAA9E/-KiBEjE4910/s320/Screenshot-Refactoring+.png" alt="" id="BLOGGER_PHOTO_ID_5302697925955470610" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;eclipse-refactor.png&gt;&lt;br /&gt;&lt;/eclipse-refactor.png&gt;The dialog says Function Name, the text entry says Method name. &lt;eclipse-refactor.png&gt;Which is it? Function or method? A function is a named section of code. A method is a function that is part of a class. I had a bad feeling about this. Rather surprisingly, it did what I expected! It extracted the code, placed it in a new method and added the prototype to the header. Wow! Unfortunately the header file got a bit mangled, with all the comments stripped out. I tracked down a minimal bit of code that causes this and opened &lt;a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=264712"&gt;a bug report&lt;/a&gt;. It does mean that you probably have to be extra careful about using this feature blindly, but it's better than nothing. &lt;span style="font-weight: bold;"&gt;UPDATE&lt;/span&gt;: The bug has been fixed in record time! I opened it on the 12th, and it was marked fixed on the 17th.&lt;br /&gt;&lt;br /&gt;Eclipse has a lot of other cool features - I haven't mentioned mylyn or the debugger integration here - but the C++ IDE itself is still a bit rough around the edges. This is probably to be expected if we consider that it's a C++ editor written in Java. That isn't meant as Java bashing, let me explain. The people who write the Java IDE version of Eclipse undoubtedly use this Java IDE to edit the Java code. The people writing the C++ IDE also need to write Java code. They don't necessarily need to write C++ though. Likewise, the users of the Java IDE edition of Eclipse are presumably capable Java coders, so it is more likely that they would be able to investigate the code and provide patches for bugs they find. Users of the C++ IDE are coders who probably know Java, but there are no guarantees, and it may not be their preferred language. They are less likely to dig into the guts of the editor to add functionality or fix bugs. Maybe. It's the &lt;a href="http://en.wikipedia.org/wiki/Eat_one%27s_own_dog_food"&gt;dog food&lt;/a&gt; thing again.&lt;br /&gt;&lt;br /&gt;Another factor is the size of the target audience. In the case of the C++ IDE, this is a lot smaller. According to &lt;a href="http://www.eclipse.org/downloads/"&gt;the eclipse download page&lt;/a&gt;, there have been around 4.5 million downloads of the various Java flavours of the IDE, but less than 700,000 downloads of the C++ version. That doesn't take into account updates of the Java version to the C++ equivalent, but the opposite is also true (updates of the C++ IDE to add Java components) so it's probably a pretty accurate reflection. The Java IDE is more than 6 times as popular. More eyes means more bug fixes and polish.&lt;br /&gt;&lt;br /&gt;So will I use Eclipse for C++ from now on? Probably not. I'll check back when the next release comes out, as the improvement over the last CDT release is major - the indexer hung last time I tried to load the bunjalloo code base into it and refactoring now has more than rename variable. Hopefully the next release will fix more niggles and add more features. But I've used Vim for years and it is an extremely optimal way to edit text once you get used to the interface. &lt;escape&gt;:wq&lt;/escape&gt;&lt;/eclipse-refactor.png&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-8677109350900615703?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/8677109350900615703/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2009/02/it-has-been-while-since-i-last-tried.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/8677109350900615703'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/8677109350900615703'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2009/02/it-has-been-while-since-i-last-tried.html' title='Notes on Eclipse CDT'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_nzN39P0Ykuk/SZa0d0w1aqI/AAAAAAAAA8M/P0pS1BP5Ffs/s72-c/Screenshot-C%2B%2B+Project+.png' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-5030805546482958057</id><published>2009-02-07T17:05:00.002+01:00</published><updated>2009-04-08T00:00:17.253+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Git'/><category scheme='http://www.blogger.com/atom/ns#' term='Bunjalloo'/><category scheme='http://www.blogger.com/atom/ns#' term='Woopsi'/><title type='text'>WIP Woopsi screenshot</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_nzN39P0Ykuk/SY2xroenLAI/AAAAAAAAA8E/f9Ulr5boqGQ/s1600-h/Screenshot-SDL+Application.png"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 129px; height: 200px;" src="http://1.bp.blogspot.com/_nzN39P0Ykuk/SY2xroenLAI/AAAAAAAAA8E/f9Ulr5boqGQ/s200/Screenshot-SDL+Application.png" alt="" id="BLOGGER_PHOTO_ID_5300087699643247618" border="0" /&gt;&lt;/a&gt;I've started the &lt;a href="http://github.com/quirky/bunjalloo/tree/woopsi"&gt;port to Woopsi&lt;/a&gt; now and it's going alright-ish. There are still a lot of bugs to iron out and old features to re-implement, but I think being able to view 2 web pages at the same time is going to make a huge difference. This screenshot shows a test page and &lt;a href="http://code.google.com/p/quirkysoft/"&gt;the Google code hosting&lt;/a&gt; site. The page title is shown on the screen title bar. Each web page is a borderless window gadget. Clicking a link opens it in the same window. Shift-clicking (clicking with the stylus while holding a shoulder button) opens the web page on the opposite screen. So you can have 2 web pages open at once. This is an artificial limit, but given the memory limits I think is a good compromise.&lt;br /&gt;&lt;br /&gt;Now for some technical crap! I'm using &lt;a href="http://www.kernel.org/pub/software/scm/git/docs/git-submodule.html"&gt;git's submodule&lt;/a&gt; support here to track &lt;a href="http://woopsi.svn.sourceforge.net/viewvc/woopsi/woopsi/trunk/"&gt;Woopsi's development&lt;/a&gt;&lt;a href="http://woopsi.svn.sourceforge.net/viewvc/woopsi/woopsi/trunk/"&gt; on sourceforge&lt;/a&gt; (via git svn...). Sounds complicated, but it's not really. And in the end it means I get bug fixes for free, but can also add my own hacks on top of the main Woopsi code. I've added my own build scripts for example, but most of the rest of my bug fixes have been committed by &lt;a href="http://ant.simianzombie.com/blog/"&gt;ant&lt;/a&gt; to his svn repository. Nice!&lt;br /&gt;&lt;br /&gt;The main issues I've seen so far are to do with my "meta-gadget" that keeps track of all the text and image gadgets. There are some scrolling issues and position problems there. The other problem is with unicode of course, but I knew that was going to be a sticking point when I started.&lt;br /&gt;&lt;br /&gt;I still need to figure out how I'm going to add in the back-forward-stop buttons. I think these will have to be in a separate window, but I get the feeling that that would be awkward. I'll probably end up adding them to each window under the main display. It'll cut off some screen space, but not too much. In the current version the buttons are shown on top of the text and are slightly transparent. This is a bit ugly though and you can't really read the text underneath anyway. Woopsi's gadget heirachy means that it might be easier to add these as separate controls and forget about it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-5030805546482958057?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/5030805546482958057/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2009/02/wip-woopsi-screenshot.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/5030805546482958057'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/5030805546482958057'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2009/02/wip-woopsi-screenshot.html' title='WIP Woopsi screenshot'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_nzN39P0Ykuk/SY2xroenLAI/AAAAAAAAA8E/f9Ulr5boqGQ/s72-c/Screenshot-SDL+Application.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-4576129289115904264</id><published>2009-01-22T21:19:00.004+01:00</published><updated>2009-04-08T00:00:30.573+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bunjalloo'/><category scheme='http://www.blogger.com/atom/ns#' term='Woopsi'/><title type='text'>GUI plans</title><content type='html'>This week Pedro Estébanez wrote what he claims will be the &lt;a href="http://okiwi.blogspot.com/2009/01/y-fin-de-la-historia.html"&gt;last entry in his Okiwi blog&lt;/a&gt;. It's a shame that there'll be no more updates to Okiwi, but I think we all new that this was the case after the quiet period following his initial release. A web browser is a lot of work.&lt;br /&gt;&lt;br /&gt;I've looked at Okiwi's code and, apart from some monster thousand-line functions, it looked OK. The quad-tree rendering algorithms are certainly miles better than Bunjalloo's naive approach to showing words and images on the screen. But what counts is releasing stuff that's useful too. Okiwi didn't have all the minimal extras to get some websites to work (I'm thinking cookies and forms here) and these things need to be thought about from the start. I'll admit that I'm not the best at getting new releases out, especially now with a 1-year-old running about the house, but I've managed a few releases over the last year or so.&lt;br /&gt;&lt;br /&gt;So what does this mean? Well with DSOrganize also abandoned, it looks like I've succeeding in boring the competition into early retirement! Go me! Heh. Now I just have to keep going. Since I wrote about &lt;a href="http://quirkygba.blogspot.com/2008/10/dsi-and-thoughts-on-future.html"&gt;abandoning Bunjallo&lt;/a&gt; a few weeks back, I've received quite a few emails and comments saying "don't give up dude!". And I can't really give up, I'm a code addict. Not everything I hack on gets released of course, there are many false starts and dead ends before I get something that's worth releasing.&lt;br /&gt;&lt;br /&gt;My current way of wasting time is trying to integrate, or to port (or whatever), Bunjalloo to &lt;a href="http://ant.simianzombie.com/blog/?page_id=128"&gt;the Woopsi GUI library&lt;/a&gt;. There are a couple of problems with this, but it would have its advantages too. First off, the bad news. Woopsi is ASCII only. That's a really big stumbling block, but I think I'll be able to fix it given my experience writing UTF-8 decoders already. The other problem is that I'll have to rewrite the current rendering "engine" to this new Woopsi API. I have no idea if  this'll go well or if it'll annoy me to such a degree that I'll throw the whole attempt in the bin.&lt;br /&gt;&lt;br /&gt;The advantages of using Woopsi are that I'll get this widget toolkit that was designed specifically for the DS for free. The current widgets are OK, but there are some design issues and writing multi-window style configuration screens more difficult than it ought to be. Writing the configuration screens has been the most irritating and dull part of the whole Bunjalloo experience so far. A couple of core classes were getting ugly and it was clear to me that I'd got something wrong in the design. A change of tack will get things rolling again hopefully, while making it easier to add new features. If I rewrite the lot in Woopsi, then changing to an options screen wouldn't hide the current web page, for example. And I could even add multi-tab browsing (well, multi-window but it boils down to the same thing). This would be my killer feature of a Woopsi port.&lt;br /&gt;&lt;br /&gt;The current progress on the port is not very impressive, sadly. I can show the start page, without images or links. Hmph. But the command line version can connect and show web pages (albeit just as crudely). This isn't starting from scratch you see - I have all the back end stuff still in place, and the design has been improved to allow multi-tab/window to be possible, memory permitting. The biggest UI shock is that each web page would be rendered on only one screen, rather than across both. I don't know if Woopsi allows windows to span both screens, but the fact is that I never really find myself looking at the top screen when browsing pages anyway. It just feels like dead space. Perhaps I'll be able to add the controls to a window on the top screen, since swapping screens is very easy with Woopsi - you just click a little icon in the top right and the screens switch places. This way the current controls for stop, forward, back, etc., could be moved out of the way when browsing. We'll see how it goes.&lt;br /&gt;&lt;br /&gt;So what do you think? A crazy idea? Or a flash of brilliance? (Clue: it's a crazy idea). I'd recommend downloading &lt;a href="https://sourceforge.net/project/showfiles.php?group_id=207650&amp;amp;package_id=248933"&gt;the latest Woopsi demo&lt;/a&gt;, play around with it a bit, then try to imagine what a mini web browser with that kind of "feel" would be like. I think it'd be pretty cool.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-4576129289115904264?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/4576129289115904264/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2009/01/gui-plans.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/4576129289115904264'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/4576129289115904264'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2009/01/gui-plans.html' title='GUI plans'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-3437895388150014456</id><published>2008-12-15T22:18:00.004+01:00</published><updated>2009-11-06T22:52:44.972+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DS'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='HOWTO'/><title type='text'>Upgrading to devkitARM r24 (on Linux)</title><content type='html'>The latest version of the devkitARM toolchain was released last week, and it was a biggie. A whole new API for sprites and backgrounds was added to libnds. A new default ARM7 binary was added that automatically handles wifi, sound and sleep mode. The other big addition was a new fangled sound library that adds mod playback and fancy sound effects.&lt;br /&gt;&lt;br /&gt;This is my post on the upgrade process for Bunjalloo on Linux (Ubuntu 8.04 in particular). Hey, if you read all this and get through it, then you could probably help out hacking on Bunjalloo too :-)&lt;br /&gt;&lt;br /&gt;A summary for the impatient: not without hassles, but &lt;span style="font-weight: bold;"&gt;the gain is worth the short term pain&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;I assume you have a directory devkitPro somewhere. This will contain devkitARM and libnds. You should set an environment variable DEVKITPRO to point to this directory. Something like this will do:&lt;br /&gt;&lt;pre class="prettyprint"&gt;export DEVKITPRO=$HOME/devkitpro_r24&lt;br /&gt;mkdir -p $DEVKITPRO&lt;/pre&gt;I recommend versioning this release at the devkitpro directory level. Release &lt;span style="font-weight: bold;"&gt;r24 contains some breaking changes&lt;/span&gt; and by having the possibility to change between r23 and r24 you may save yourself some headaches. At the very least, it will ensure you don't mix versions, which would be a big no-no.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Download the devkitARM r24 files from the &lt;a href="http://sf.net/projects/devkitpro"&gt;sf.net project page&lt;/a&gt;&lt;ul&gt;&lt;li&gt; devkitARM_r24-i686-linux.tar.bz2&lt;/li&gt;&lt;li&gt; libnds-src-1.3.1.tar.bz2&lt;/li&gt;&lt;li&gt; dswifi-src-0.3.5.tar.bz2&lt;/li&gt;&lt;li&gt; maxmod-src-1.0.1.tar.bz2&lt;/li&gt;&lt;li&gt; default_arm7-src-20081210.tar.bz2&lt;/li&gt;&lt;li&gt; nds-examples-20081210.tar.bz2&lt;/li&gt;&lt;li&gt; libfat-src-1.0.3.tar.bz2&lt;/li&gt;&lt;/ul&gt;I saved them all in $HOME/Downloads, and that's what I've put in this post. Change that path as you need.&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt; Install the devkitARM toolchain. This provides the compiler and C/C++ standard libraries. I usually install it in a versioned file, but if you already have named your devkitpro directory "devkitpro_r24" then there's no need.&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;cd $DEVKITPRO&lt;br /&gt;tar xvf ~/Downloads/devkitARM_r24-1686-linux.tar.bz2&lt;br /&gt;mv devkitARM devkitARM_r24&lt;/pre&gt;&lt;/li&gt;&lt;br /&gt;The rest of these steps can be done in any directory. I tend to use $DEVKITPRO/vendor for all this build stuff. You can also use the precompiled binaries, but this way you know you have everything you need installed.&lt;br /&gt;&lt;br /&gt;&lt;li&gt; Set the DEVKITARM environment variable to point to our installed toolkit &lt;pre class="prettyprint"&gt;export DEVKITARM=$DEVKITPRO/devkitARM_r24&lt;/pre&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Install libnds&lt;br /&gt;!!! CARE !!! these source tars &lt;span style="font-weight: bold;"&gt;don't have a top level directory, so you need to create them manually&lt;/span&gt;. This is the case for all of the devkitPro tar balls, except the main devkitARM_r24 one. They will splurge their files in the current directory, instead of creating their own top level one. Yuck!&lt;br /&gt;&lt;pre class="prettyprint"&gt;mkdir libnds-1.3.1&lt;br /&gt;cd libnds-1.3.1&lt;br /&gt;tar xjf ~/Downloads/libnds-src-1.3.1.tar.bz2&lt;/pre&gt;Now to compile libnds - if you have DEVKITPRO and DEVKITARM set correctly then this should compile the library succesfully.&lt;br /&gt;&lt;pre&gt;make -j 3 install&lt;/pre&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;libfat is optional, but recommended. Open up the tar, compile and install it too, if you like. libfat for the nds depends on having libnds installed, so you'll have to do step 4 first.&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;mkdir libfat-1.0.2&lt;br /&gt;cd libfat-1.0.2&lt;br /&gt;tar xvf ~/Downloads/libfat-src-1.0.2.tar.bz2&lt;br /&gt;make nds-install&lt;br /&gt;&lt;/pre&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Now install dswifi 0.3.5 in a similar way - untar the release files, compile and install. dswifi depends on libnds, so you have to do the previous steps before this one.&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;mkdir dswifi-0.3.5&lt;br /&gt;cd dswifi-0.3.5&lt;br /&gt;tar xvf ~/Downloads/dswifi-src-0.3.5.tar.bz2&lt;br /&gt;make -j 3 install&lt;/pre&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Install maxmod. Again, this depends on libnds and won't compile if you have skipped a step.&lt;br /&gt;&lt;pre class="prettyprint"&gt;mkdir maxmod-1.0.1&lt;br /&gt;cd maxmod-1.0.1&lt;br /&gt;tar xvf ~/Downloads/maxmod-src-1.0.1.tar.bz2&lt;br /&gt;make -j 3 install-nds&lt;/pre&gt;&lt;/li&gt;&lt;br /&gt;&lt;br /&gt;&lt;li&gt;Install the new default ARM7 core. This requires dswifi and maxmod, if either are missing then you will get compile or link errors.&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;mkdir default_arm7-20081210&lt;br /&gt;cd default_arm7-20081210&lt;br /&gt;tar xvf ~/Downloads/default_arm7-src-20081210.tar.bz2&lt;br /&gt;make install&lt;/pre&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Try out the nds examples! Now that everything is installed, you can compile and run some examples.&lt;br /&gt;&lt;pre class="prettyprint"&gt;mkdir nds-examples-20081210&lt;br /&gt;cd nds-examples-20081210&lt;br /&gt;tar xvf ~/Downloads/nds-examples-20081210.tar.bz2&lt;br /&gt;cd audio/maxmod&lt;br /&gt;make&lt;br /&gt;# test the nds files on your DS!&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;Write your own program :-) This part is a bit trickier!&lt;/li&gt;&lt;/ol&gt;Now once I had all this installed, I needed to update Bunjalloo to use the new code (Elite DS coming soon!). The first step was to see what would compile without drastic changes. The list of changes required in my code was:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Remove irqInit() calls - this is now done by libnds before your main is called&lt;/li&gt;&lt;li&gt;Register name changes: DISPLAY_CR -&gt; REG_DISPCNT, BG0_X0 -&gt; REG_BG0HOFS, BG0_CR -&gt; REG_BG0CNT (and their SUB equivalents, where applicable)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Function name changes: powerON, powerOFF -&gt; powerOn, powerOff, touchReadXY() -&gt; touchRead(touch_structure)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Deprecated header: nds/jtypes.h -&gt; nds/ndstypes.h&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Look-up table changes: COS[angle] -&gt; cosLerp(angle), SIN[angle] -&gt; sinLerp(angle)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Some #defines have gone: BG_16_COLOR -&gt; BG_COLOR_16, BG_256_COLOR -&gt; BG_COLOR_256, SOUND_8BIT -&gt; SOUND_FORMAT_8BIT&lt;br /&gt;&lt;/li&gt;&lt;li&gt;powerOn/Off now expects a PM_Bits enum value, not an int&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Nothing major there... the big breaking changes are on the ARM7 side. Here &lt;span style="font-weight: bold;"&gt;trying to use your own hand-coded arm7 causes plenty of problems&lt;/span&gt; - most of the old inter-processor communications code has been removed from libnds, or has changed completely. Unfortunately, that means it's quite tricky to migrate to the new libnds and use your own ARM7 core. The easiest thing to do here is ignore your ARM7 code completely and use the new default_arm7. There's no one-stop solution, since most IPC code has been built in an ad hoc way, but here are some pointers.&lt;br /&gt;&lt;br /&gt;For wifi code, your old wifi init code should be replaced by a single call to Wifi_InitDefault(true/false) - no need to faff about setting up the interrupts and timers. Then you can either now use sockets (if you passed "true", which means connect using the firmware settings) or connect using a detected AP first - all this is documented in the dswifi headers and by the new examples. Pretty neat, and cuts down on maintenance for everyone.&lt;br /&gt;&lt;br /&gt;If you have a debug console, then consoleInitDefault() is a bit trickier to update. It has disappeared, pretty much. In most cases consoleDemoInit() will probably suffice. If you are doing anything much more complicated, then you will have to get to grips with the PrintConsole structure. This seems to be quite a powerful new feature, for example it allows printing to both screens from within the same program, but will take a while to get used to. I doubt many people used the old consoleInitDefault in "real" programs, and the new API looks like it might be possible to use the printf stuff on something other than a black/white screen.&lt;br /&gt;&lt;br /&gt;Sound has seen a rather large shakeup in this release. The new MaxMod sound engine seems to fill a huge gap in the homebrewer's library arsenal. It isn't without its drawbacks though, if you did just basic NDS sound effects. Previously you could play individual samples by sending the raw data to the playGenericSound() function, after having previously set the sample rate, volume, panning and format via the setGenericSound() function. That has now been completely removed, replaced by new MaxMod sound engine functions. This is a flexible sound and music system, but requires that the sound effects are in a special format. A tool (mmutil) is provided to convert wav and mod file formats to the expected static structure. Alternatively, a more complex streaming system can be used. This latter does not require input sounds to be converted, and is the only way to play sound from a file, but is slightly trickier to use than the straight forward playGenericSound() function.&lt;br /&gt;&lt;br /&gt;The sound streaming approach requires you the coder to implement an audio-filling callback and to call the mmUpdateStream() function often enough to keep the sound buffer full. Fortunately there are some good examples of all the MaxMod library's usage in the nds-examples pack, and the new system is a great addition. Besides music, you can do looped samples, proper panning, mixing, etc, etc. Bah, I'm just miffed because I'll have to rewrite some of my SDL sound code ;-)&lt;br /&gt;&lt;br /&gt;Needless to say, on the ARM7 side of things the sound handling stuff has completely changed - this alone is a good enough reason to abandon any hand-rolled arm7 code. Added to the new sleep function - no more will-it-wont-it wondering when you close the lid - and all in all I think this is a great release.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-3437895388150014456?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/3437895388150014456/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2008/12/upgrading-to-devkitarm-r24-on-linux.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/3437895388150014456'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/3437895388150014456'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2008/12/upgrading-to-devkitarm-r24-on-linux.html' title='Upgrading to devkitARM r24 (on Linux)'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-5330135439590391494</id><published>2008-12-01T21:41:00.003+01:00</published><updated>2009-04-08T00:01:05.079+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DS'/><category scheme='http://www.blogger.com/atom/ns#' term='HOWTO'/><title type='text'>Things you never wanted to know about assembler but were too afraid to ask</title><content type='html'>When you write homebrew for the Nintendo DS, or the Game Boy Advance, you can choose to use a friendly language like C or C++. This makes life a bit easier. It's comfortable, familiar. But at the back of your mind there's this nagging doubt... Shouldn't I be writing some of this in assembler? After all, if I'm writing C code, I may as well code for a PC and use SDL or Allegro. But then you think... Assembler, that sounds a bit tricky, I wouldn't know where to begin!&lt;br /&gt;&lt;br /&gt;And that's where this post comes in.&lt;br /&gt;&lt;br /&gt;Getting started with assembler is probably the hardest part. There's aren't many articles on best practices, what not to do, which idioms to use, and so on, as there are for other languages. Many of the ideas you have about C can't be applied to assembler, or at leas that's what you might think at first, so you probably brush it off as impossible. This is a bit sad, because these Nintendo consoles use an ARM processor and ARM assembler has a nice syntax. Unlike assembler for Intel processors, say, the ARM syntax is fairly small, has few real surprises and can be learned quite easily.&lt;br /&gt;&lt;br /&gt;Now, I don't want to claim that I'm some assembler guru. I've written about 6,000 lines of ARM for Pocket Beeb and Elite AGB, plus some in a current "top secret" project I'm working on. It's not really that much, especially compared to the millions of lines of C and C++ I've probably written. But it is a good enough amount to get a feel for how to code in this way, I think.&lt;br /&gt;&lt;br /&gt;Before we dive in, let's see at how we go from C to "the magic" that runs on a DS. The first step is to write a function in C. We then use a compiler, which converts this to a file in the ELF format. This binary file is joined together with all the other compiled modules in your program, and the output is a "pure" binary blob with some header information. So that's C to object file, then object files to NDS "ROM" file.&lt;br /&gt;&lt;br /&gt;Let's rewind to those first steps. The C function is compiled to an ELF file, which typically ends in ".o", for "object file". This step actually skips out quite a lot. You can see the intermediate files involved by passing --save-temps to your compilation step. Lets try this. Here's a useless function that does some pointless thing. We pass in a couple of variables, and add or subtract them depending on their relative values.&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;int my_function(int x, int y) {&lt;br /&gt;  if (x &amp;lt; y) {&lt;br /&gt;    return x + y;&lt;br /&gt;  } else {&lt;br /&gt;    return x - y;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If we compile this as so: "arm-eabi-gcc --save-temps -c -o my_function.o my_function.c" then the output will be 3 files. These are my_function.o (as expected), my_function.i and my_function.s. The .i file is the post-processed output - what happens after running the C preprocessor on the file. This finds-and-replaces any #defines, pastes in any #include'd files and adds in compiler-specific information. The .s file is what we are after. This is the output of the C code converted to ARM assembler. It contains a lot of "cruft" that you wouldn't write if you were to write this function by hand, but some of the features are important:&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;&amp;#09;.text&lt;br /&gt;&amp;#09;.align  2&lt;br /&gt;&amp;#09;.global my_function&lt;br /&gt;&amp;#09;.type   my_function, %function&lt;br /&gt;my_function:&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The lines that start with a dot are called directives. They are psuedo-instructions that tell the assembler to do extra things.&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://sources.redhat.com/binutils/docs-2.12/as.info/Text.html#Text"&gt;.text&lt;/a&gt; directive adds headers to let the linker know where abouts the code should be placed. It's not too important on the DS, more so on the GBA, where if you omit it then the code may be placed in RAM. You can also force code to go into fast iwram on the GBA by using the directive .section .iwram,"ax",%progbits. Don't ask what it means, just use the voodoo.&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://sources.redhat.com/binutils/docs-2.12/as.info/Align.html#Align"&gt;.align&lt;/a&gt; directive ensures that our code is padded to 4 byte boundaries. The "2" means the number of bits that must be zero in the location counter at this point. So 2 bits signifies aligned by 4 bytes. Since ARM assembler instructions are 32 bits big (4 bytes) we need to align the code to 4-byte boundaries, or Very Bad Things can happen.&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://sources.redhat.com/binutils/docs-2.12/as.info/Global.html#Global"&gt;.global&lt;/a&gt; directive makes the symbol name (my_function) visible outside the compilation unit, so you can use it in other parts of your program. Without .global, the symbol would be the equivalent of using "static" in a C definition.&lt;br /&gt;&lt;br /&gt;The &lt;a href="http://sources.redhat.com/binutils/docs-2.12/as.info/Type.html#Type"&gt;.type&lt;/a&gt; directive is pretty pointless, but I tend to use it to mark what are functions and what are just helper "scraps" of assembler with a named label. It's use is supposed to be for interoperability with other assemblers, but we always use GCC from devkitPro so its a moot point.&lt;br /&gt;&lt;br /&gt;Finally, "my_function:" is a label - this is like a goto label in C and is where the program jumps to when we call this function.&lt;br /&gt;&lt;br /&gt;The rest of the ARM code spit out by GCC is as good as could be for this example, if you compile with -O2. Normally, the advantages of assembler tend to be minimal for small functions, they are better when you do things that can't be easily done in C. Such as unrolling loops, keeping often-used memory addresses in a single register, that kind of thing. Also, hand coded ARM assembler can make better use of the registers in some cases, more on registers in a minute, but GCC assembler tends to make more use of the stack. This tends to manifest itself only in more complex functions. Anyway, lets just say that it'd complicate matters needlessly to copy paste the rest of the code here, and for this example GCC does a good job.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Registers&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I mentioned the registers back there. The ARM processor in the NDS and GBA has 16 registers - usually named r0, r1, r2... up to r12, then sp, lr, pc instead of r13, r14 and r15. I say usually, because there is an alternate naming scheme that some documents use. Here certain registers are given special names:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  std | alt&lt;br /&gt; -----+-----&lt;br /&gt;  r0  | a1&lt;br /&gt;  r1  | a2&lt;br /&gt;  r2  | a3&lt;br /&gt;  r3  | a4&lt;br /&gt;  r4  | v1&lt;br /&gt;  r5  | v2&lt;br /&gt;  r6  | v3&lt;br /&gt;  r7  | v4&lt;br /&gt;  r8  | v5&lt;br /&gt;  r9  | v6&lt;br /&gt;  r10 | v7 or sl&lt;br /&gt;  r11 | v8 or fp&lt;br /&gt;  r12 | ip&lt;br /&gt;  r13 | sp&lt;br /&gt;  r14 | lr&lt;br /&gt;  r15 | pc&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It's probably best to use the r0-r12,sp,lr,pc naming scheme as that is what the ARM documentation uses. The trick is to pick one scheme and stick to it. sp is a mnemonic for "stack pointer" and points to, you guessed it, the stack. lr means "link register" and is used as the return address for function calls. pc is the program counter and is the address of the current instruction (i.e. where we are in the program).&lt;br /&gt;&lt;br /&gt;The stack is an area of RAM. Initially it points to the end of the RAM area and grows downwards as programs allocate memory (on the stack). When writing assembler I find it's not that usual to use the stack - generally I only use it for storing register values that I may need later, such as the lr when calling functions recursively.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Code set up&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Remember how gcc spat out a .s file? Well, that means "pure assembler code". The common way to store ARM code is in a file ending in ".S". This is interpreted by gcc as a source file containing assembler and pre-processor directives. So here we can use #defines and #includes if we really need to. It also distinguishes hand coded assembler files from any --save-temps left-overs.&lt;br /&gt;&lt;br /&gt;Lets try writing our my_function in assembler. First I fire up an $EDITOR and write out the preamble to my_function.S. Now lets think about what we want. This function has the following C prototype:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;int my_function(int, int);&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;So that means it accepts 2 input values and returns a value. The input values in ARM are in the first 4 registers - any more than 4 inputs are stored on the stack. The original function wanted an addition if x was less than y, else it subtracted y from x. Here's my final code to do this:&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;&amp;#09;.text&lt;br /&gt;&amp;#09;.align  2&lt;br /&gt;&amp;#09;.global my_function&lt;br /&gt;&amp;#09;.type   my_function, %function&lt;br /&gt;my_function:&lt;br /&gt;&amp;#09;cmp&amp;#09;r0, r1&lt;br /&gt;&amp;#09;addlt&amp;#09;r0, r0, r1&lt;br /&gt;&amp;#09;subge&amp;#09;r0, r0, r1&lt;br /&gt;&amp;#09;bx&amp;#09;lr&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The header is as we saw before. The my_function label is the start of the function. The r0 and r1 registers contain the input values.&lt;br /&gt;&lt;br /&gt;The cmp instruction means "compare r0 to r1 and set the flags accordingly"... now I don't really want to copy out the whole ARM assembler guide here, but suffice to say that this sets some flags based on the mathematical result of performing "r0 - r1". These tests are in the form of those "lt", "ge" that follow the end of the other instructions. This is one of the neat parts about ARM - every instruction is conditional!&lt;br /&gt;&lt;br /&gt;The default condition is "al" for "always", but may be omitted for obvious reasons. We don't want to write al after every instruction, right? So here we say, if r0 is less than (lt) r1, then add r0 to r1 and store the result in r0. A normal add would just be "add", but here we write "addlt". This makes the processor skip over the instruction if the "less than" state is not set. It's important to note that conditional instructions like this still have some overhead, the processor still has to read the operation in some way, so if you have more than say 3 or 4 conditional instructions with the same condition, it may be faster to use a branch to skip the code completely.&lt;br /&gt;&lt;br /&gt;If the result was greather than or equal (ge) then the subtraction is done and the result stored in r0, followed by a return. The bx instruction is used to return from a function - it means "branch to the address in the register lr". As you see, we use the link register to return to the calling code.&lt;br /&gt;&lt;br /&gt;Finally, the result is always stored in r0 in this example. This is part of the ARM binary interface - results are returned in registers r0 and r1. This convention allows C and ARM code to interoperate sensibly. If you are returning to your own ARM function, then you can invent any convention you like - return values in r4, r7 and r11 if you want - but sticking to the "C way" means that you can use the function from C later, if that becomes necessary.&lt;br /&gt;&lt;br /&gt;You may have noticed that addition and subtraction seem to work "backwards" compared to C convention. Instead of reading left-to-right and the result being stored at the end, the result is actually stored in the first register given. This is fairly common in other flavours of assembler code too, and once you get used to it, it isn't so bad.&lt;br /&gt;&lt;br /&gt;We can write a simple test program to run this code:&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;#include &amp;lt;nds.h&amp;gt;&lt;br /&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;&lt;br /&gt;int my_function(int x, int y);&lt;br /&gt;&lt;br /&gt;int main(void) {&lt;br /&gt; consoleDemoInit();&lt;br /&gt; int x = 1;&lt;br /&gt; int y = 2;&lt;br /&gt; iprintf("my_function(%d, %d) returns %d\n", x, y, my_function(x, y));&lt;br /&gt; x = 100;&lt;br /&gt; y = 20;&lt;br /&gt; iprintf("my_function(%d, %d) returns %d\n", x, y, my_function(x, y));&lt;br /&gt;&lt;br /&gt; while(1) { swiWaitForVBlank(); }&lt;br /&gt; return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This prints out the results on the DS screen. Nothing very exciting, but you can see that combining C and ARM assembler in a project is not as difficult as you first thought!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Tips and tricks&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There are quite a few traps for the unwary - apart from the shift in thought process needed to code assembler, of course. The first of these is that loading a value into a register requires some thought. You can only load values with "mov" that are shifted 8 bit values - 0xff0, 0x1c00, but not 0x101, for example. There is a psuedo opcode to get around this easily - "ldr r1, =0x101" for example - but it may bite you if you didn't know this. The error would look like this "Error: invalid constant (101) after fixup", just in case you were wondering.&lt;br /&gt;&lt;br /&gt;When you write ARM, always try to maximise what each instruction does! Shifts can be added onto the end of instructions, so often instead of a shift then logical orr, you can do the lot in one go:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;orr  r3, r0, r1, lsl r2&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;This is the same as &lt;code&gt;r3 = r0 | (r1 &amp;lt;&amp;lt; r2)&lt;/code&gt; all in one instruction! Similarly you can load data from structures using offsets with ldr, with "ldr r0, [r1, r2, lsl #2]". That means r0 = r1[r2*4] - useful for loading 32-bit values from structures into registers. Remember that in assembler pointer arithmetic works as if all pointers were to char, there are no data types. Adding 1 to a pointer really just adds 1 to it, not like in C where it can increase by the size of the data type.&lt;br /&gt;&lt;br /&gt;Generally, make use of all the registers you have available and avoid pushing/popping to and from the stack. You can use r0-r12 however you want, make the most of these and you'll find some nice shortcuts that provide speedy, optimised code. Hopefully. If you need to push multiple registers to the stack, then the idiom to use is the stmfd/ldmfd one (store/load multiple full descending). This stores a comma seprated list and/or range of registers to the stack, and decrements/increments the stack by the right amount. It is written as follows, to store here registers r0 to r7 and lr (r14):&lt;br /&gt;&lt;br /&gt;&lt;pre class="prettyprint"&gt;&lt;br /&gt;&amp;#09;stmfd sp!,{r0-r7, lr}&lt;br /&gt;... do stuff with registers r0-r7 and lr ...&lt;br /&gt;&amp;#09;ldmfd sp!,{r0-r7, lr}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Always try and reduce duplication - not only is it a maintenance problem, but each copied line is a wasted cycle. Try and reduce code to the minimum number of instructions, that's the name of the game here. Ah, but remember: get a working version first, then optimise heavily. No point having a fast bit of code that doesn't do what you want :-)&lt;br /&gt;&lt;br /&gt;I'd recommend &lt;a href="http://infocenter.arm.com/help/topic/com.arm.doc.qrc0001l/QRC0001_UAL.pdf"&gt;this PDF cheat sheet&lt;/a&gt; for a quick guide to the ARM instruction set. Keep in mind that the DS doesn't support all the instructions on there - rbit, bfc, and some others - but they are generally the more exotic operations that are used less. If in doubt, compile a quick test file. You'll get the error "Error: selected processor does not support..." if the instruction is not supported by the CPU.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Conclusions.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So why would you want to do all this? Isn't this just for head cases?&lt;br /&gt;&lt;br /&gt;I think learning how to write code at this level leads to a better understanding of why things are done in certain ways in high level languages. You'll certainly grok pointers, if you haven't already. Learning new coding styles - not just using C-like languages - will make you a better coder too. Heck, maybe a better person even ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-5330135439590391494?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/5330135439590391494/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2008/12/things-you-never-wanted-to-know-about.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/5330135439590391494'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/5330135439590391494'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2008/12/things-you-never-wanted-to-know-about.html' title='Things you never wanted to know about assembler but were too afraid to ask'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-2674848131119242136</id><published>2008-11-07T20:14:00.006+01:00</published><updated>2009-04-08T00:01:20.126+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Git'/><category scheme='http://www.blogger.com/atom/ns#' term='HOWTO'/><title type='text'>Recovering history with git reflog</title><content type='html'>I use &lt;a href="http://www.kernel.org/pub/software/scm/git/docs/git-svn.html"&gt;git-svn&lt;/a&gt; quite a bit at work. One of the nice things about this is that I can create perfect patch sets - instead of commit a whole raft of random chunks, I can polish a change until it works. Quite often I'll reset the HEAD to a few commits back, to get rid of changes that add crap like "printf" or were just bug-fix dead ends. You know, the usual cargo cult "I'll change this to see what happens", that once you understand the problem realise had nothing really to do with the root cause of the problem.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_nzN39P0Ykuk/SRSVkY1SVGI/AAAAAAAAArM/5hLcdDR9cas/s1600-h/ball.png"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 200px; height: 108px;" src="http://2.bp.blogspot.com/_nzN39P0Ykuk/SRSVkY1SVGI/AAAAAAAAArM/5hLcdDR9cas/s200/ball.png" alt="" id="BLOGGER_PHOTO_ID_5265998316676732002" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;One of the side effects of this is that, after a while I tend to end up with lots of "dead" commits. While using gitk I can see these as little commit balls that aren't joined to anything, like the headless branchy thing in the image. If I close gitk, or click the "Reload" option then the commit tree is cleaned up to show only commits that have a head.&lt;br /&gt;&lt;br /&gt;Occasionally, once I've finished a change, squashed all my commits and committed them to subversion, it turns out that &lt;span style="font-weight: bold;"&gt;one of those lost commits really should have been part of the patch set&lt;/span&gt;. Oops! I've closed gitk by now, so all those lost commits can't be seen. How can I get them back? Here's where git reflog comes to the rescue.&lt;br /&gt;&lt;br /&gt;I didn't discover the wonders of &lt;span style="font-weight: bold;"&gt;git reflog&lt;/span&gt; until quite recently. Its man page is not too helpful in describing what it does: &lt;span style="font-style: italic;"&gt;"Manage reflog information"&lt;/span&gt;. What it actually does is print out a list of commits that are in a branch, or are in limbo. It doesn't distinguish between the two. So you can use it, together with gitk, to show your lost commits. For example I use this:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;blockquote&gt;  gitk --all `git reflog | cut -c1-7`&lt;/blockquote&gt;&lt;/span&gt;That's it. It shows all branches (--all) and all the commits in the reflog, so all those lost commits are reachable, cherry-pickable and branchable again. I just wanted to share that with the internet, because I know I'll forget it by next week :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-2674848131119242136?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/2674848131119242136/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2008/11/recovering-history-with-git-reflog.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/2674848131119242136'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/2674848131119242136'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2008/11/recovering-history-with-git-reflog.html' title='Recovering history with git reflog'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_nzN39P0Ykuk/SRSVkY1SVGI/AAAAAAAAArM/5hLcdDR9cas/s72-c/ball.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-8749748930949370607</id><published>2008-10-13T20:22:00.006+02:00</published><updated>2009-04-08T00:02:11.591+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DS'/><category scheme='http://www.blogger.com/atom/ns#' term='SCons'/><category scheme='http://www.blogger.com/atom/ns#' term='HOWTO'/><title type='text'>Alternatives to Make, Part II</title><content type='html'>Last time I described how somebody insane enough could use &lt;a href="http://www.cmake.org/"&gt;CMake&lt;/a&gt; for their cross compiling needs. This entry I'll consider the next entry on the list of interesting Make replacements: &lt;a href="http://www.scons.org/"&gt;SCons&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;SCons&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When using SCons as your build system you have 2 options: install scons on the system or include a version in your source tree. The easiest way is to install a version of scons on your system, and mark your build scripts that they require that version or newer of scons to run. This does put a burden on end users as they must appropriate their own copy of SCons, but it means your repository of code isn't full of 3rd party stuff. Additionally, the machine doing the compiling must have Python installed. On Linux this is no problem, but on Windows it's Yet Another Dependency. This is because SCons, unlike CMake, uses an already-existing programming language to describe the build process. In this case, &lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt;. The build scripts are called "SConstruct" and, apart from some oddities, work like normal Python modules.&lt;br /&gt;&lt;br /&gt;So on to the cross compiling issue - compiling our C or C++ code into a DS program. Unlike CMake, there's no set way to handle cross compilation. In fact, there are no real "best working practices" outlined anywhere in the (quite extensive) &lt;a href="http://www.scons.org/documentation.php"&gt;SCons documentation&lt;/a&gt; - you're free to do what you like. My recommendation here is to take a leaf out of CMake's book and separate out as much as possible into a toolchain file.&lt;br /&gt;&lt;br /&gt;As with the CMake example, let's start off with the ansi_console example from &lt;a href="http://www.devkitpro.org/"&gt;devkitPro&lt;/a&gt;. This has a source sub directory and a main.c file. First, create a SConstruct file that will read in a toolchain called "arm":&lt;br /&gt;&lt;pre style="font-size: 89%;"&gt;&lt;code&gt;env = Environment(tools='arm', toolpath='.')&lt;/code&gt;&lt;/pre&gt;The toolpath means "look for the file in the current directory". The toolchain file is a normal python module. This means a file called "arm.py". In order to make it a true SCons tool file we need to add 2 functions, "generate" and "exists". So that would be:&lt;br /&gt;&lt;pre style="font-size: 89%;"&gt;&lt;code&gt;def generate(env, **kwargs):&lt;br /&gt;   pass&lt;br /&gt;&lt;br /&gt;def exists(env):&lt;br /&gt; return 1&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;I get the feeling that exists() is not actually used - it certainly isn't in SCons 1.0.1, but the documentation says it is required. The generate function is called when we create the Environment, passing the Environment into the generate function so we can mess about with the innards. So lets do the usual setup, which is to check DEVKITARM and DEVKITPRO are set in the user's environment. SCons by default doesn't pull all the environment variables into its own Environment object. This is good, as we don't really want a build to depend "randomly" on some rogue variable. But! we do want to use some of them. Anyway, on to the code:&lt;br /&gt;&lt;pre style="font-size: 89%;" class="prettyprint"&gt;from os import environ&lt;br /&gt;from os.path import pathsep,join&lt;br /&gt;def check_devkit(env):&lt;br /&gt;   ENV = env['ENV']&lt;br /&gt;   for var in ('DEVKITARM', 'DEVKITPRO'):&lt;br /&gt;       if var not in environ:&lt;br /&gt;           print 'Please set %s. export %s=/path/to/%s'%(var, var, var)&lt;br /&gt;           env.Exit(1)&lt;br /&gt;       ENV[var] = environ[var]&lt;br /&gt;   ENV['PATH'] = ENV['PATH']+pathsep+join(environ['DEVKITARM'], 'bin')&lt;br /&gt;   if not find_devkitarm(env):&lt;br /&gt;       print 'DevkitARM was not found'&lt;br /&gt;       env.Exit(1)&lt;br /&gt;&lt;br /&gt;def generate(env, **kwargs):&lt;br /&gt;   check_devkit(env)&lt;br /&gt;&lt;/pre&gt;That is pretty straight forward - it checks the environ(ment) and adds $DEVKITARM/bin to the path. Now we need to find out if we have a suitable compiler. Here things get a bit icky. Because SCons isn't a priori designed for cross compilation, it assumes that your GNU-based compiler is called just "gcc". This means that, in order to X-compile, you'll need to install gcc, since we use the gcc tool detection and environment set up and overwrite parts with our arm-eabi-gcc. A bit of an irritating flaw, and one which CMake has understood and implemented correctly. The alternative, of course, is to copy paste the entire SCons gcc tools and replace gcc with arm-eabi-gcc - or suitable prefix. In fact, this alternative approach may well work out better... anyway. For now we'll use the approach that assumes vanilla gcc and overwrites with arm-eabi.&lt;br /&gt;&lt;pre style="font-size: 89%;" class="prettyprint"&gt;def setup_tools(env):&lt;br /&gt;   gnu_tools = ['gcc', 'g++', 'gnulink', 'ar', 'gas']&lt;br /&gt;   for tool in gnu_tools:&lt;br /&gt;       env.Tool(tool)&lt;br /&gt;   env['CC'] = prefix+'gcc'&lt;br /&gt;   env['CXX'] = prefix+'g++'&lt;br /&gt;   env['AR'] = prefix+'ar'&lt;br /&gt;   env['AR'] = prefix+'as'&lt;br /&gt;   env['OBJCOPY'] = prefix+'objcopy'&lt;br /&gt;   env['PROGSUFFIX'] = '.elf'&lt;br /&gt;&lt;br /&gt;def generate(env, **kwargs):&lt;br /&gt;   check_devkit(env)&lt;br /&gt;   setup_tools(env)&lt;br /&gt;&lt;/pre&gt;So that sets up the environment for compiling, then overwrites the tool names with the arm-eabi equivalent. We also set the PROGSUFFIX (program suffix) to .elf - this makes life easier for the objcopy step. Now we need the "magic flags" that cause our Nintendo DS program to compile.&lt;br /&gt;&lt;pre style="font-size: 89%;" class="prettyprint"&gt;def add_flags(env):&lt;br /&gt;   # add arm flags&lt;br /&gt;   env.Append(CCFLAGS='-march=armv5te -mtune=arm946e-s'.split())&lt;br /&gt;   env.Append(CPPDEFINES='ARM9')&lt;br /&gt;   env.Append(LIBS='nds9')&lt;br /&gt;   env.Append(LINKFLAGS=['-specs=ds_arm9.specs'])&lt;br /&gt;   # add libnds&lt;br /&gt;   libnds = join(environ['DEVKITPRO'], 'libnds')&lt;br /&gt;   env.Append(LIBPATH=[ join(libnds, 'lib')])&lt;br /&gt;   env.Append(CPPPATH=[ join(libnds, 'include')])&lt;br /&gt;&lt;br /&gt;def generate(env, **kwargs):&lt;br /&gt;   check_devkit(env)&lt;br /&gt;   setup_tools(env)&lt;br /&gt;   add_flags(env)&lt;br /&gt;&lt;/pre&gt;These flags are the usual ARM9 flags and libnds include path for compiling C code, and libnds9 and the specs flag when linking. Without these devkitArm complains (this is as expected, it is a multi-platform ARM compiler, so you need to tell it the exact platform you want to use). There's one more step here - we need a way to build the nds file from an .elf file - but first lets go back to the SConstruct. If you recall, at the top of the post there, we had just created an Environment. Now we have added a load of ARM stuff to that Environment. The next step here is to create a program. In SCons we can do this as follows:&lt;br /&gt;&lt;pre style="font-size: 89%;"&gt;&lt;code&gt;env.Program('ansi_console', os.path.join('source','main.c')) &lt;/code&gt;&lt;/pre&gt;That's it! Except, no it isn't. This produces ansi_console.elf, which needs to be objcopy'd and ndstool'd. To do &lt;span style="font-style: italic;"&gt;that&lt;/span&gt; we can go back to our arm.py tool file. Here we add in new "Builders" to do the work. A Builder is like the Program method we saw in the SConstruct - it takes the names of the source files and produces the outputs... so we add in the builders to our arm.py file:&lt;br /&gt;&lt;pre style="font-size: 89%;" class="prettyprint"&gt;def add_builders(env):&lt;br /&gt;   def generate_arm(source, target, env, for_signature):&lt;br /&gt;       return '$OBJCOPY -O binary %s %s'%(source[0], target[0])&lt;br /&gt;   def generate_nds(source, target, env, for_signature):&lt;br /&gt;       if len(source) == 2:&lt;br /&gt;           return "ndstool -c %s -7 %s -9 %s"%(target[0], source[0], source[1])&lt;br /&gt;       else:&lt;br /&gt;           return "ndstool -c %s -9 %s"%(target[0], source[0])&lt;br /&gt;   env.Append(BUILDERS={&lt;br /&gt;       'Ndstool': SCons.Builder.Builder(&lt;br /&gt;                   generator=generate_nds,&lt;br /&gt;                   suffix='.nds',&lt;br /&gt;                   src_suffix='.arm'),&lt;br /&gt;       'Objcopy': SCons.Builder.Builder(&lt;br /&gt;                   generator=generate_arm,&lt;br /&gt;                   suffix='.arm',&lt;br /&gt;                   src_suffix='.elf')})&lt;br /&gt;def generate(env, **kwargs):&lt;br /&gt;   [f(env) for f in (check_devkit, setup_tools, add_flags, add_builders)]&lt;br /&gt;&lt;/pre&gt;That's a fair amount of typing! What does it do? Well, the "generate_arm" function is called when we want to generate an .arm file from an .elf file. It returns a SCons-y string that will be executed to do the actual work. Here it is our old OBJCOPY string - the $OBJCOPY is replaced automagically by SCons with the equivalent Environment variable. The "generate_nds" function is called when we want to generate an .nds from an .arm, it too returns the command line that will be executed. There's a bit of a trick there that checks if we need to combine an ARM7 and ARM9 core, or just use the default ARM7, but apart from that it is straightforward. The "env.Append(BUILDERS=...)" bit creates new functions called Ndstool and Objcopy that can be used like Program. Passing in a generator function means we use functions - you could use a fixed string and pass it as an action too.&lt;br /&gt;&lt;br /&gt;Armed with our new methods, lets go back to the SConstruct. We can objcopy and ndstool the Program/elf file as follows:&lt;br /&gt;&lt;pre style="font-size: 89%;"&gt;&lt;code&gt;env.Ndstool(env.Objcopy(env.Program('ansi_console', join('source','main.c'))))&lt;/code&gt;&lt;/pre&gt;That's it. There are a couple of things we can do to make this better. For example, rather than splurge the build artifacts all over the source tree, we can use a build directory. To do this we need to use SCons recursively. The Recursive file is called a "SConscript", and all we have to remember is that to pass objects (like the env created in the top level SConstruct) down to the other SConscripts, we have to use an Export/Import mechanism. A bit confusing, but the code's easy enough:&lt;br /&gt;&lt;pre style="font-size: 89%;" class="prettyprint"&gt;#in SConstruct&lt;br /&gt;env = Environment(tools=['arm'], toolpath=['.'])&lt;br /&gt;SConscript(join('source','SConscript'),&lt;br /&gt;           variant_dir='build',&lt;br /&gt;           duplicate=0,&lt;br /&gt;           exports='env')&lt;br /&gt;&lt;br /&gt;# in source/SConscript&lt;br /&gt;Import('env')&lt;br /&gt;env.Ndstool(env.Objcopy(env.Program('ansi_console', 'main.c')))&lt;br /&gt;&lt;/pre&gt;Passing exports to the SConscript file exports the named variables. Using Import imports them into the local namespace. Magical! There's also a Return() function to return variables from sub scripts. That's usefull when tracking local library dependencies.&lt;br /&gt;&lt;br /&gt;OK, so what about "dual core" programs? It turns out that it is a bit of effort. More even than CMake, I'd say. We can either create a second Environment and set up the variables for ARM9 or ARM7 according to the core in question, or use a single Environment instance, set flags that should be used for ARM9 or ARM7, and use these appropriately for each Program call that we make. The first approach ends up a bit messy, with ifs for processor type in several places. The second approach is cleaner, but means there is a bit more code used when calling env.Program. I use the latter approach in &lt;a href="http://ds-elite.googlecode.com/svn/trunk/site_scons/site_tools/arm.py"&gt;Elite DS&lt;/a&gt;, so that's what I'll outline here. You have to set the compiler flags for arm9 and arm7 in the env variable. This can be done as follows, modifying the add_flags() function of our arm.py tool:&lt;br /&gt;&lt;pre style="font-size: 89%;" class="prettyprint"&gt;THUMB_FLAGS = ' -mthumb -mthumb-interwork '&lt;br /&gt;PROCESSOR_CFLAGS = {&lt;br /&gt; '9': ' -march=armv5te -mtune=arm946e-s',&lt;br /&gt; '7': ' -mcpu=arm7tdmi -mtune=arm7tdmi'&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;PROCESSOR_LDFLAGS = THUMB_FLAGS + \&lt;br /&gt;       ' -specs=ds_arm%c.specs -g -mno-fpu -Wl,-Map,${TARGET.base}.map  -Wl,-gc-sections'&lt;br /&gt;EXTRA_FLAGS = ' -Wno-strict-aliasing -fomit-frame-pointer -ffast-math '&lt;br /&gt;&lt;br /&gt;def add_flags(env):&lt;br /&gt;   ccflags = ' '.join([EXTRA_FLAGS, THUMB_FLAGS])&lt;br /&gt;   CCFLAGS_ARM9 = ' '.join([ccflags, PROCESSOR_CFLAGS['9']])&lt;br /&gt;   CCFLAGS_ARM7 = ' '.join([ccflags, PROCESSOR_CFLAGS['7']])&lt;br /&gt;   CPPDEFINES_ARM9 = 'ARM9'&lt;br /&gt;   CPPDEFINES_ARM7 = 'ARM7'&lt;br /&gt;   LIBS_ARM9 = ['fat', 'nds9']&lt;br /&gt;   LIBS_ARM7 = ['nds7']&lt;br /&gt;   LINKFLAGS_ARM9 = PROCESSOR_LDFLAGS%'9'&lt;br /&gt;   LINKFLAGS_ARM7 = PROCESSOR_LDFLAGS%'7'&lt;br /&gt;&lt;br /&gt;   env.Append(CCFLAGS_ARM9=CCFLAGS_ARM9)&lt;br /&gt;   env.Append(CCFLAGS_ARM7=CCFLAGS_ARM7)&lt;br /&gt;   env.Append(CPPDEFINES_ARM9=CPPDEFINES_ARM9)&lt;br /&gt;   env.Append(CPPDEFINES_ARM7=CPPDEFINES_ARM7)&lt;br /&gt;   env.Append(LIBS_ARM9=LIBS_ARM9)&lt;br /&gt;   env.Append(LIBS_ARM7=LIBS_ARM7)&lt;br /&gt;   env.Append(LINKFLAGS_ARM9=LINKFLAGS_ARM9)&lt;br /&gt;   env.Append(LINKFLAGS_ARM7=LINKFLAGS_ARM7)&lt;br /&gt;&lt;br /&gt;   # add libnds&lt;br /&gt;   libnds = join(environ['DEVKITPRO'], 'libnds')&lt;br /&gt;   env.Append(LIBPATH=[ join(libnds, 'lib')])&lt;br /&gt;   env.Append(CPPPATH=[ join(libnds, 'include')])&lt;br /&gt;&lt;br /&gt;def generate(env, **kwargs):&lt;br /&gt;   [f(env) for f in (check_devkit, setup_tools, add_flags, add_builders)]&lt;br /&gt;&lt;/pre&gt;Most of those flags are taken from the devkitPro examples and should be pretty familiar. In order to actually use them, we can override the flags used for each individual program. So in the SConscript, the env.Program line would become:&lt;br /&gt;&lt;pre style="font-size: 89%;" class="prettyprint"&gt;env.Program('ansi_console', os.path.join('source','main.c'),&lt;br /&gt;       CCFLAGS=env['CCFLAGS_ARM9'],&lt;br /&gt;       CPPDEFINES=env['CPPDEFINES_ARM9'],&lt;br /&gt;       LIBS=env['LIBS_ARM9'],&lt;br /&gt;       LINKFLAGS=env['LINKFLAGS_ARM9'])&lt;br /&gt;&lt;/pre&gt;More typing, but there's no need to pass extra Environments about. The equivalent for an ARM7 program would obviously replace the 9's for 7's.&lt;br /&gt;&lt;br /&gt;As before with my CMake entry, here is a quick summary to help you decide whether or not to use SCons as your build system for cross compiling NDS programs.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;The Bad&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Scalability: I haven't mentioned this yet, but the biggest problem SCons has is that when you reach several hundred source files, the time that it takes to parse the SConscripts and generate dependencies becomes considerable. If you also use SCons autoconf-like Configure functions, then the configuration step is, by default, run each and every time you compile. The results are cached, but it takes several seconds to go through the tests. This became an issue for me on &lt;a href="http://quirkysoft.googlecode.com/"&gt;Bunjalloo&lt;/a&gt;, which used to use SCons. Before compiling anything SCons would typically sit around in silence for 15 seconds contemplating the build. I've seen builds that do "nothing" for minutes at a time that, when changed to CMake or whatever, did similar thinking time in seconds. KDE and OpenMoko are two famous SCons "deserters" due to performance problems. On the other hand for &lt;a href="http://ds-elite.googlecode.com/"&gt;Elite DS&lt;/a&gt;, which only has around a hundred source files, the do-nothing time is negligible and SCons works great.&lt;br /&gt;&lt;br /&gt;Not really cross-compiling friendly: Unlike CMake, SCons is not built with cross compiling in mind. This is demonstrated by the hard-coding of "gcc", etc, in the gcc.py SCons-tools. This means you probably will have to install native tools as well as the cross tools in order to compile anything. (Note: the new 1.1.0 may have fixed this, it was released as I was writing this post!)&lt;br /&gt;&lt;br /&gt;Syntax can get complicated: When writing scripts that use multiple local libraries, the Return() and Import/Export() mechanisms that SCons uses can get a bit unwieldy. You end up with lots of global variable names that you have to Import() and Export() across SConscripts, or else Return() everything to the parent file and let it sort out the mess.&lt;br /&gt;&lt;br /&gt;Python can look intimidating: Unlike CMake, which still looks a bit Makefile-like, SCons scripts can have any old Python code in it. Without discipline, this can result in build scripts that are difficult to follow, especially if Python is not one of your strong languages.&lt;br /&gt;&lt;br /&gt;Dependencies: As with CMake, you still need to install stuff - namely the SCons build system itself. As more projects use scons this will become less of a problem, but at the moment it can be annoying for users ("oh no! where is my Makefile?")&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;The Good&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Python code: If you are familiar with Python already, you don't need to learn yet another language. There are no hacks to get loops working. Proper data structures can be used to describe the build. Any of the Python libraries can be imported and used. This is a very powerful advantage, as well as being multi-platform (providing you stick to cross platform safe python code, of course).&lt;br /&gt;&lt;br /&gt;Stable API: SCons is backwards compatible with the practically stone-age Python 1.5.2 and its APIs for building things changes infrequently, first deprecating functions and rarely removing anything. This makes changing from an older version to a newer one fairly painless. A full suite of tests means that regressions on new versions are pretty rare - if something goes wrong, it is likely to be due to a bug in your SConscript, rather than a bug in SCons.&lt;br /&gt;&lt;br /&gt;Great documentation: There is loads of good &lt;a href="http://www.scons.org/documentation.php"&gt;documentation on the SCons website&lt;/a&gt;. The manual is particularly well done, with an easy step-by-step guide. Once installed, a very complete man page is installed (on Linux, FreeBSD, etc at least) that contains examples as well as the full API.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Conclusion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As with CMake, you probably need a good reason to not use a bog-standard Makefile. For me, being able to code the build logic in Python is the deciding factor. I think SCons is pretty good, and &lt;a href="http://ds-elite.googlecode.com/svn/trunk/SConstruct"&gt;use it&lt;/a&gt; for &lt;a href="http://ds-elite.googlecode.com/"&gt;Elite DS&lt;/a&gt;. I'd probably use SCons for other projects I do too, depending on their size (and my mood). The Bunjalloo build became a bit too slow with SCons, but I'll talk more about that next time when I discuss &lt;a href="http://waf.googlecode.com/"&gt;Waf&lt;/a&gt;. There seems to be quite an uptake of SCons for new OSS projects (Google's &lt;a href="http://src.chromium.org/svn/trunk/src/build/SConscript.main"&gt;Chrome browser for one&lt;/a&gt;), especially in favour of autotools, and hopefully we'll see some improvement in the speed because of this (the latest release, 1.1.0, boasts improved memory use, but I have yet to see any benchmarks). Until then, you could probably do a lot worse than &lt;a href="http://www.scons.org/download.php"&gt;download the latest release&lt;/a&gt; and have a mess around to see what it's all about.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-8749748930949370607?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/8749748930949370607/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2008/10/alternatives-to-make-part-ii.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/8749748930949370607'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/8749748930949370607'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2008/10/alternatives-to-make-part-ii.html' title='Alternatives to Make, Part II'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-7889927077391020522</id><published>2008-10-06T20:25:00.003+02:00</published><updated>2009-04-08T00:02:24.990+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DSi'/><category scheme='http://www.blogger.com/atom/ns#' term='Bunjalloo'/><title type='text'>DSi and thoughts on the future</title><content type='html'>Nintendo have announced a new version of the DS, calling it &lt;a href="http://www.1up.com/do/newsStory?cId=3170323"&gt;the DSi&lt;/a&gt;. No idea what the &lt;span style="font-style:italic;"&gt;i&lt;/span&gt; means, a nod at the &lt;a href="http://www.apple.com/ipodtouch/"&gt;good work&lt;/a&gt; Apple are doing presumably. But what does this mean for Bunjalloo development? &lt;br /&gt;&lt;br /&gt;I think it is time to call it a day.&lt;br /&gt;&lt;br /&gt;The thing is, this new console includes a web browser and, I assume, it will kitted out with a lot more RAM than the current-gen DS. Pure speculation, but you can't do much with 4 megabytes nowadays. Especially on the ever-expanding internet. While the actual DS can also run a full-blown browser, if you bought Opera, having one by default is the killer. Especially if it is free (not &lt;a href="http://www.fsf.org/"&gt;Free&lt;/a&gt;, but free "as in beer") and doesn't need a RAM expansion pack. Additionally, the rumour mill is already speculating about the security upgrades on the new DSi, like it'll  have a software black list to disallow homebrew carts, upgradable firmware like the PSP and so on. I don't think anyone actually buys DS games anymore. Everyone I've seen IRL with a DS has a flash cartridge thingy of some sort. It just makes economic sense, really. So Nintendo will want to end this rampant piracy with the next gen console, and at the same time make it pretty tricky for normal folk to run homebrew games for a while. At least until a new hack comes out and the cartridge manufacturers take it mainstream. Oh, and region locking a handheld? Grrr...&lt;br /&gt;&lt;br /&gt;Anyhow, that doesn't mean I'll give up on Bunjalloo completely, but it will enter Maintainance Mode, where only bug fixes will go in with no new stuff. See? You should have sent me patches to add those cool features, duh! There's a new release out now, 0.7.1, that fixes some of the bugs in 0.7, just to show I'm still hacking around.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-7889927077391020522?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/7889927077391020522/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2008/10/dsi-and-thoughts-on-future.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/7889927077391020522'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/7889927077391020522'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2008/10/dsi-and-thoughts-on-future.html' title='DSi and thoughts on the future'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-5516123929242479696</id><published>2008-09-27T00:05:00.004+02:00</published><updated>2009-04-08T00:02:42.219+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DS'/><category scheme='http://www.blogger.com/atom/ns#' term='CMake'/><category scheme='http://www.blogger.com/atom/ns#' term='HOWTO'/><title type='text'>Alternatives to Make, Part 1</title><content type='html'>In the Nintendo DS scene the build tool that everyone uses is plain ol' Make. There are several alternatives for the brave developer, however. I'm going to write a few posts describing how you can use &lt;a href="http://www.cmake.org"&gt;CMake&lt;/a&gt;, &lt;a href="http://www.scons.org"&gt;SCons&lt;/a&gt; or &lt;a href="http://code.google.com/p/waf"&gt;Waf&lt;/a&gt; to compile your code. Yes, I'm a bit of a build system junkie. This week viewers we'll look at CMake.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;CMake&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.cmake.org/"&gt;CMake&lt;/a&gt; is a build system that generates files for use with the build tool on your platform. You write a configuration file, called CMakeLists.txt, run the cmake program to generate a load of Makefiles or project files, then run make (or whatever) to compile your project. On Windows, CMake generates project files for use with Visual Studio. It can also generate project files for &lt;a href="http://www.codeblocks.org/"&gt;CodeBlocks&lt;/a&gt;, &lt;a href="http://www.eclipse.org/cdt/"&gt;Eclipse CDT&lt;/a&gt; and &lt;a href="http://www.kdevelop.org/"&gt;KDevelop&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;A hefty obstacle for using CMake with the DS is that currently CMake doesn't support building multiple target architectures in one build tree. So compiling ARM7 and ARM9 cores and combining the result into the final .nds file requires a bit of fiddling. More on that later, as it can be done.&lt;br /&gt;&lt;br /&gt;The first thing you will need is the &lt;a href="http://www.cmake.org/cmake/resources/software.html"&gt;latest version of CMake&lt;/a&gt;. The features needed to compile on the DS were only added quite recently (version 2.6 onwards).&lt;br /&gt;&lt;br /&gt;After you've installed CMake, you can start hacking away. First we need to create a Toolchain File that CMake uses to understand your target platform. Normally CMake autodetects the local platform type and configures the compiler, linker, compilation flags and so on, to the correct values. When cross compiling for the DS, you have to tell CMake which compiler it should use. We don't want it to try and guess based on any native compiler installed.&lt;br /&gt;&lt;br /&gt;As described in the &lt;a href="http://www.cmake.org/Wiki/CMake_Cross_Compiling"&gt;CMake wiki&lt;/a&gt; we first have to turn off the auto detection. This is done by setting the variable CMAKE_SYSTEM_NAME to "Generic". Here we come across one of the oddities that takes a bit of getting used to. Instead of the usual &lt;a href="http://en.wikipedia.org/wiki/Backus-Naur_Form"&gt;BNF variable = value style syntax&lt;/a&gt; for assignment, CMake uses a function. So we have set(variable value). Whatever. The other 2 variables set here are optional: &lt;br /&gt;&lt;pre style="font-size:89%"&gt;&lt;code&gt;set(CMAKE_SYSTEM_NAME Generic)&lt;br /&gt;set(CMAKE_SYSTEM_VERSION 1)&lt;br /&gt;set(CMAKE_SYSTEM_PROCESSOR arm-eabi)&lt;/code&gt;&lt;/pre&gt;A note on style here. Commands like if, message, endif, set and so on can be written either in ALL CAPS or in lower case. The keywords inside commands have to be in UPPER CASE. I prefer to write the commands in lowercase and everything else in upper case.&lt;br /&gt;&lt;br /&gt;So, after those first set() lines we begin to describe which compiler we'll use. The approach I'm going to use doesn't stray from the standard DEVKITARM and DEVKITPRO environment variables, which should point to where you have the devkitARM toolchain and libnds installed. We set 2 CMake variables based on environment variables as follows:&lt;pre style="font-size:89%"&gt;&lt;code&gt;set(DEVKITARM $ENV{DEVKITARM})&lt;br /&gt;set(DEVKITPRO $ENV{DEVKITPRO})&lt;/code&gt;&lt;/pre&gt;Actually this is quite good - it means that CMake by default doesn't drag the whole environment into the namespace. This means there is a better chance of our build being repeatable without having to set up a million environment variables. After this, we can check if they are set with these lines of code:&lt;br /&gt;&lt;pre style="font-size:89%"&gt;&lt;code&gt;if(NOT DEVKITARM)&lt;br /&gt; message(FATAL_ERROR "Please set DEVKITARM in your environment")&lt;br /&gt;endif(NOT DEVKITARM)&lt;/code&gt;&lt;/pre&gt;And similarly for DEVKITPRO. So now we need to check if the compiler is installed. This is done by setting the CMAKE_C(XX)_COMPILER variables as follows. Also we set the CMAKE_FIND_ROOT_PATH, which lets us use objcopy, ar, ranlib and friends. The other flags tell CMake to just use the compiler headers and libraries, to not search DEVKITARM for other libs and headers. Really we could create an install base for the DS, with lib, include and so on, but that is not the usual way to do things. It would probably break a lot of other hand-coded Makefiles that people use, so we'll stick with the $DEVKITPRO/libnds convention. Anyway, here is the code for setting up the compilers:&lt;br /&gt;&lt;pre style="font-size:89%"&gt;&lt;code&gt;set(CMAKE_C_COMPILER ${DEVKITARM}/bin/arm-eabi-gcc)&lt;br /&gt;set(CMAKE_CXX_COMPILER ${DEVKITARM}/bin/arm-eabi-g++)&lt;br /&gt;set(CMAKE_FIND_ROOT_PATH ${DEVKITARM})&lt;br /&gt;set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)&lt;br /&gt;set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)&lt;br /&gt;set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)&lt;/code&gt;&lt;/pre&gt;Here if DEVKITARM points somewhere that doesn't really have the arm-eabi compiler installed, then CMake will throw up an error message when we run it:&lt;pre style="font-size:89%"&gt;&lt;code&gt;CMake Error: your C compiler: "/path/to/devkitARM/bin/arm-eabi-gcc" was not found.   Please set CMAKE_C_COMPILER to a valid compiler path or name.&lt;br /&gt;CMake Error: your CXX compiler: "/path/to/devkitARM/bin/arm-eabi-g++" was not found.   Please set CMAKE_CXX_COMPILER to a valid compiler path or name.&lt;/code&gt;&lt;/pre&gt; Apart from the compiler, we also need to indicate where libnds lives. This is done by telling CMake how to construct a library name - prepending lib, and adding .a at the end - and where to search for the library and headers:&lt;br /&gt;&lt;pre style="font-size:89%"&gt;&lt;code&gt;set(CMAKE_FIND_LIBRARY_PREFIXES lib)&lt;br /&gt;set(CMAKE_FIND_LIBRARY_SUFFIXES .a)&lt;br /&gt;include_directories(${DEVKITPRO}/libnds/include)&lt;br /&gt;link_directories(${DEVKITPRO}/libnds/lib)&lt;br /&gt;find_library(NDS9 nds9)&lt;br /&gt;find_library(NDS7 nds7)&lt;/code&gt;&lt;/pre&gt;OK, that's it. The rest is now "vanilla" CMake. When we run the cmake program we need to tell it to use cross compiling. This is done with the CMAKE_TOOLCHAIN_FILE variable. We can set it with a gcc-like "-D" flag:&lt;br /&gt;&lt;pre style="font-size:89%"&gt;&lt;code&gt;cmake -DCMAKE_TOOLCHAIN_FILE=/full/path/to/devkitArm.cmake .&lt;/code&gt;&lt;/pre&gt;So now we have this, we can take an example from the &lt;a href="http://sourceforge.net/project/showfiles.php?group_id=114505&amp;amp;package_id=159894"&gt;nds-examples that are distributed with devkitArm&lt;/a&gt; and try to have it compile using CMake. Let's use the ansi_console example. Unzip the examples, and copy ansi_console to some place - it's in the Graphics/2D directory. Now create a file ansi_console/CMakeLists.txt and start editing it. The first thing to do here is to give the project a name:&lt;br /&gt;&lt;pre style="font-size:89%"&gt;&lt;code&gt;project(NDS-EXAMPLES)&lt;/code&gt;&lt;/pre&gt;In order to compile correctly when using libnds, we need to set a C define &lt;span style="font-style: italic;"&gt;ARM9&lt;/span&gt;. For this, we use the &lt;span style="font-weight: bold;"&gt;add_definition&lt;/span&gt; macro. I'll also create a variable EXE_NAME that we can use instead of copying ansi_console everywhere. This way if we want to change the name of the binary later it won't be too much hassle.&lt;pre style="font-size:89%"&gt;&lt;code&gt;add_definitions(-DARM9)&lt;br /&gt;set(EXE_NAME ansi_console)&lt;/code&gt;&lt;/pre&gt;Now we can describe how to build the "executable". The next line tells CMake to create an executable from the file source/main.c&lt;br /&gt;&lt;pre style="font-size:89%"&gt;&lt;code&gt;add_executable(${EXE_NAME} source/main.c )&lt;/code&gt;&lt;/pre&gt;That alone isn't enough, as we also need to link with libnds for the ARM9 and pass in the required -specs flag.&lt;br /&gt;&lt;pre style="font-size:89%"&gt;&lt;code&gt;target_link_libraries(${EXE_NAME} nds9)&lt;br /&gt;set_target_properties(${EXE_NAME}&lt;br /&gt; PROPERTIES&lt;br /&gt; LINK_FLAGS -specs=ds_arm9.specs&lt;br /&gt; COMPILER_FLAGS "-mthumb -mthumb-interwork")&lt;/code&gt;&lt;/pre&gt;The &lt;span style="font-weight: bold;"&gt;set_target_properties&lt;/span&gt; macro allows us to fiddle with the compilation and link flags. A bit later, if you decide to use CMake for your NDS projects, you could make a wrapper around this to set up the usual flags for a NDS binary, rather than copying the above lines everywhere.&lt;br /&gt;&lt;br /&gt;So to here this would normally be enough on a platform that has an operating system and knows how to load the executable file format. We could run cmake, passing in the devkitArm toolchain file and the path to the ansi_console directory. The DS doesn't have an OS however and we need to strip out all the "elfyness" - the ELF headers and whatnot -, and add the special DS header. Converting the ELF to a pure binary is done with objcopy. Adding the header is done with ndstool, provided as part of the devkitArm distribution. We can write macros to help with these steps, and that allows me to write this kind of thing to finish off the process:&lt;pre style="font-size:89%"&gt;&lt;code&gt;objcopy_file(${EXE_NAME})&lt;br /&gt;ndstool_file(${EXE_NAME})&lt;/code&gt;&lt;/pre&gt;So where do these come from? Well, we have 2 choices. Either add the macro inline in the CMakeLists.txt file or create a module. The first is easier, but the second approach lets us reuse the module elsewhere. So in a new file called ndsmacros.cmake I'll add the following lines to define the macros OBJCOPY_FILE and NDSTOOL_FILE&lt;br /&gt;&lt;pre style="font-size:89%"&gt;&lt;code&gt;macro(OBJCOPY_FILE EXE_NAME)&lt;br /&gt; set(FO ${CMAKE_CURRENT_BINARY_DIR}/${EXE_NAME}.bin)&lt;br /&gt; set(FI ${CMAKE_CURRENT_BINARY_DIR}/${EXE_NAME})&lt;br /&gt; message(STATUS ${FO})&lt;br /&gt; add_custom_command(&lt;br /&gt;  OUTPUT "${FO}"&lt;br /&gt;  COMMAND ${CMAKE_OBJCOPY}&lt;br /&gt;  ARGS -O binary ${FI} ${FO}&lt;br /&gt;  DEPENDS ${FI})&lt;br /&gt; get_filename_component(TGT "${EXE_NAME}" NAME)&lt;br /&gt; add_custom_target("TargetObjCopy_${TGT}" ALL DEPENDS ${FO} VERBATIM)&lt;br /&gt; get_directory_property(extra_clean_files ADDITIONAL_MAKE_CLEAN_FILES)&lt;br /&gt; set_directory_properties(&lt;br /&gt;  PROPERTIES&lt;br /&gt;  ADDITIONAL_MAKE_CLEAN_FILES "${extra_clean_files};${FO}")&lt;br /&gt; set_source_files_properties("${FO}" PROPERTIES GENERATED TRUE)&lt;br /&gt;endmacro(OBJCOPY_FILE)&lt;br /&gt;&lt;br /&gt;if(NOT NDSTOOL_EXE)&lt;br /&gt; message(STATUS "Looking for arm-eabi-objcopy")&lt;br /&gt; find_program(NDSTOOL_EXE ndstool ${DEVKITARM}/bin)&lt;br /&gt; if(NDSTOOL_EXE)&lt;br /&gt;  message(STATUS "Looking for arm-eabi-objcopy -- ${NDSTOOL_EXE}")&lt;br /&gt; endif(NDSTOOL_EXE)&lt;br /&gt;endif(NOT NDSTOOL_EXE)&lt;br /&gt;&lt;br /&gt;if(NDSTOOL_EXE)&lt;br /&gt; macro(NDSTOOL_FILE EXE_NAME)&lt;br /&gt;  set(FO ${CMAKE_CURRENT_BINARY_DIR}/${EXE_NAME}.nds)&lt;br /&gt;  set(I9 ${CMAKE_CURRENT_BINARY_DIR}/${EXE_NAME}.bin)&lt;br /&gt;  add_custom_command(&lt;br /&gt;   OUTPUT ${FO}&lt;br /&gt;   COMMAND ${NDSTOOL_EXE}&lt;br /&gt;   ARGS -c ${FO} -9 ${I9}&lt;br /&gt;   MAIN_DEPENDENCY ${I9}&lt;br /&gt;   )&lt;br /&gt;  get_filename_component(TGT "${EXE_NAME}" NAME)&lt;br /&gt;  add_custom_target("Target9_${TGT}" ALL DEPENDS ${FO} VERBATIM)&lt;br /&gt;  get_directory_property(extra_clean_files ADDITIONAL_MAKE_CLEAN_FILES)&lt;br /&gt;  set_directory_properties(&lt;br /&gt;   PROPERTIES&lt;br /&gt;   ADDITIONAL_MAKE_CLEAN_FILES "${extra_clean_files};${FO}")&lt;br /&gt;  set_source_files_properties(${FO} PROPERTIES GENERATED TRUE)&lt;br /&gt; endmacro(NDSTOOL_FILE)&lt;br /&gt;endif(NDSTOOL_EXE)&lt;/code&gt;&lt;/pre&gt;The first macro that defines OBJCOPY_FILE uses the built-in CMake command "add_custom_command". This has lots of options, but the ones used here say that cmake should run the CMAKE_OBJCOPY command passing in the given arguments (ARGS). CMAKE_OBJCOPY is defined automagically from our CMAKE_FIND_ROOT_PATH in the devkitArm toolchain file, it corresponds to arm-eabi-objcopy in the devkitArm installation. The "add_custom_target" isn't really needed here, but we will need it later for combined arm7/9 cores. It adds a new top level target called TargetObjCopy_[name of exe] that depends on the out file to the "all" target, so when we run "make all" it will build the binary file, if needed. Whew! That was all a bit complicated. The rest of the macro adds the output file to the clean  target and marks the output as a generated file.&lt;br /&gt;&lt;br /&gt;The "if" block in the middle is a bit like the autoconf functionality from the GNU Build System - it tries to find the ndstool program, and raises an error if it cannot be found. Otherwise we get a varible NDSTOOL_EXE that we can use to run the program. The NDSTOOL_FILE macro uses the ndstool exe to create a "single core" binary. Actually, it uses a default arm7 core, which is why we don't have to provide one. Again, we add a custom command to make sure the thing gets built when we run "make all" and add the nds file to the list of things to get cleaned.&lt;br /&gt;&lt;br /&gt;So we have ndsmacros.cmake. To include it there are 2 ways that vary subtly. The best approach is to set the CMAKE_MODULE_PATH variable to the directory containing our macro file and then include the macro as a module:&lt;br /&gt;&lt;pre style="font-size:89%"&gt;&lt;code&gt;set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR})&lt;br /&gt;include(ndsmacros)&lt;/code&gt;&lt;/pre&gt;That assumes you have the macro file at the top of the ansi_console directory, which for a small example like this is fine. On a bigger project, if you want lots of extra tools, you would probably park them off in a sub-directory to avoid clutter.&lt;br /&gt;&lt;br /&gt;So that's more or less it. Let's run this and see what happens. Ah! first I should just mention that we will compile in a separate build tree, keeping the source tree free from object files and other build artifacts. This is just good practice.&lt;br /&gt;&lt;pre style="font-size:89%"&gt;&lt;code&gt;$ cd ansi_console&lt;br /&gt;$ mkdir build&lt;br /&gt;$ cd build&lt;br /&gt;$ cmake -DCMAKE_TOOLCHAIN_FILE=$(pwd)/../devkitArm.cmake ..&lt;br /&gt;-- The C compiler identification is GNU&lt;br /&gt;-- The CXX compiler identification is GNU&lt;br /&gt;-- Check for working C compiler: /path/to/devkitARM/bin/arm-eabi-gcc&lt;br /&gt;-- Check for working C compiler: /path/to/devkitARM/bin/arm-eabi-gcc -- works&lt;br /&gt;-- Detecting C compiler ABI info&lt;br /&gt;-- Detecting C compiler ABI info - done&lt;br /&gt;-- Check for working CXX compiler: /path/to/devkitARM/bin/arm-eabi-g++&lt;br /&gt;-- Check for working CXX compiler: /path/to/devkitARM/bin/arm-eabi-g++ -- works&lt;br /&gt;-- Detecting CXX compiler ABI info&lt;br /&gt;-- Detecting CXX compiler ABI info - done&lt;br /&gt;-- Looking for grit&lt;br /&gt;-- Looking for grit -- /home/rich/src/ndsdev/devkitARM/bin/grit&lt;br /&gt;-- Looking for arm-eabi-objcopy&lt;br /&gt;-- Looking for arm-eabi-objcopy -- /path/to/devkitARM/bin/ndstool&lt;br /&gt;-- In data&lt;br /&gt;-- Configuring done&lt;br /&gt;-- Generating done&lt;br /&gt;-- Build files have been written to: /path/to/examples-cmake/ansi_console/build&lt;/code&gt;&lt;/pre&gt;Now if we look at what has been produced we see that there's a normal Makefile in the build directory. So lets run it...&lt;pre style="font-size:89%"&gt;&lt;code&gt;$ make&lt;br /&gt;&lt;span style="color: rgb(204, 51, 204);"&gt;Scanning dependencies of target ansi_console&lt;/span&gt;&lt;br /&gt;[ 25%] &lt;span style="color: rgb(51, 204, 0);"&gt;Building C object ansi_console/CMakeFiles/ansi_console.dir/source/main.c.obj&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;Linking C executable ansi_console&lt;/span&gt;&lt;br /&gt;[ 25%] Built target ansi_console&lt;br /&gt;&lt;span style="color: rgb(204, 51, 204);"&gt;Scanning dependencies of target Target9_ansi_console&lt;/span&gt;&lt;br /&gt;[ 25%] &lt;span style="color: rgb(51, 51, 255);"&gt;Generating ansi_console.bin&lt;/span&gt;&lt;br /&gt;[ 25%] &lt;span style="color: rgb(51, 51, 255);"&gt;Generating ansi_console.nds&lt;/span&gt;&lt;br /&gt;Nintendo DS rom tool 1.38 - May 14 2008&lt;br /&gt;by Rafael Vuijk, Dave Murphy, Alexei Karpenko&lt;br /&gt;[ 75%] Built target Target9_ansi_console&lt;br /&gt;&lt;span style="color: rgb(204, 51, 204);"&gt;Scanning dependencies of target TargetObjCopy_ansi_console&lt;/span&gt;&lt;br /&gt;[100%] Built target TargetObjCopy_ansi_console&lt;/code&gt;&lt;/pre&gt;Nice coloured output there. And we have our ansi_console.nds. That's it, job done. As you can see, the Makefile tracks dependencies. For this simple example it isn't too bad - everything really only depends on the main.c file. But for larger projects, not having to think about generating the dependencies manually is a big plus. Sadly we are limited to timestamp checks for updates to dependencies, the make legacy showing through. We can do better than that with hashes. I'll mention that when I discuss SCons next time.&lt;br /&gt;&lt;br /&gt;There are still things missing from this, but armed with the basics we can improve the build without too much hassle. For example, we'd need a tool to convert images to data using grit. There are more flags that we need to pass in for C++ code to turn off exceptions and RTTI, for example. And we still have the dual code problem. The grit tool would be pretty much the same as our objcopy_file example, except it'd change a png file to a c source file. A bit of a limitation that, CMake doesn't compile assembler into executables, only C/C++.&lt;br /&gt;&lt;br /&gt;Dual core is not too bad - we already have the basics. If we follow the above but for the "combined" example, then the main CMakeLists.txt would have the following lines:&lt;pre style="font-size:89%"&gt;&lt;code&gt;add_subdirectory(arm9)&lt;br /&gt;add_subdirectory(arm7)&lt;/code&gt;&lt;/pre&gt;We wouldn't actually use the ADD_EXECUTABLE macro here. In the arm7/CMakeLists.txt file, we'd have something like this:&lt;br /&gt;&lt;pre style="font-size:89%"&gt;&lt;code&gt;include_directories(${CMAKE_CURRENT_SOURCE_DIR})&lt;br /&gt;add_definitions(-DARM7)&lt;br /&gt;add_executable(combined_arm7 arm7.c)&lt;br /&gt;target_link_libraries(combined_arm7 nds7)&lt;br /&gt;set_target_properties(combined_arm7&lt;br /&gt; PROPERTIES&lt;br /&gt; LINK_FLAGS -specs=ds_arm7.specs)&lt;br /&gt;objcopy_file(combined_arm7)&lt;/code&gt;&lt;/pre&gt;This layout is mandatory because the ADD_DEFINITIONS macro applies the -D flag in the directory where it is used and for all sub directories. I tried using REMOVE_DEFINITIONS to work around the problem, but that does not work:&lt;br /&gt;&lt;pre style="font-size:89%"&gt;&lt;code&gt;add_definitions(-DARM7)&lt;br /&gt;add_executable(combined_arm7 arm7/arm7.c)&lt;br /&gt;remove_definitions(-DARM7)&lt;br /&gt;add_definitions(-DARM9)&lt;br /&gt;add_executable(combined_arm9 arm9/arm9.c)&lt;/code&gt;&lt;/pre&gt;CMake uses the final set of definitions for all the executables. So we'd end up with the -DARM9 flag for the ARM7 binary too, which is not what we want. Ok, so the arm9/CMakeLists.txt file would have similar content to the arm7/CMakeLists.txt one, just switching all "7"s for "9"s. At the end we'd use the following macro to combine the 2 binaries into the nds file, in combined/CMakeLists.txt:&lt;br /&gt;&lt;pre style="font-size:89%"&gt;&lt;code&gt;ndstool_files(arm7/combined_arm7 arm9/combined_arm9 combined)&lt;/code&gt;&lt;/pre&gt;You have probably guessed that this macro is added to our ndsmacros.cmake file and would take 3 arguments:&lt;br /&gt;&lt;pre style="font-size:89%"&gt;&lt;code&gt;macro(NDSTOOL_FILES arm7_NAME arm9_NAME exe_NAME)&lt;br /&gt;set(FO ${CMAKE_CURRENT_BINARY_DIR}/${exe_NAME}.nds)&lt;br /&gt;set(I9 ${CMAKE_CURRENT_BINARY_DIR}/${arm9_NAME}.bin)&lt;br /&gt;set(I7 ${CMAKE_CURRENT_BINARY_DIR}/${arm7_NAME}.bin)&lt;br /&gt;add_custom_command(&lt;br /&gt; OUTPUT ${FO}&lt;br /&gt; COMMAND ${NDSTOOL_EXE}&lt;br /&gt; ARGS -c ${FO} -9 ${I9} -7 ${I7})&lt;br /&gt;get_filename_component(TGT "${exe_NAME}" NAME)&lt;br /&gt;get_filename_component(TGT7 "${arm7_NAME}" NAME)&lt;br /&gt;get_filename_component(TGT9 "${arm9_NAME}" NAME)&lt;br /&gt;add_custom_target("Target97_${TGT}" ALL DEPENDS ${FO} VERBATIM)&lt;br /&gt;add_dependencies("Target97_${TGT}"&lt;br /&gt; "TargetObjCopy_${TGT7}"&lt;br /&gt; "TargetObjCopy_${TGT9}")&lt;br /&gt;get_directory_property(extra_clean_files ADDITIONAL_MAKE_CLEAN_FILES)&lt;br /&gt;set_directory_properties(&lt;br /&gt; PROPERTIES&lt;br /&gt; ADDITIONAL_MAKE_CLEAN_FILES "${extra_clean_files};${FO}")&lt;br /&gt;endmacro(NDSTOOL_FILES)&lt;/code&gt;&lt;/pre&gt;This is a bit more hacky than I would have liked, that add_dependencies line shouldn't be needed. But if we use DEPENDS in the add_custom_command macro as the documentation suggests, then we only see errors like "No rule to make target `combined/arm7/combined_arm7.bin'" - I imagine it is because of the use of sub directories. We need sub directories though, otherwise we cannot set flags per ARM core, so we'll have to live with the rather hacky solution here. Unless someone knows better and posts a comment! ;-)&lt;br /&gt;&lt;br /&gt;That's the lot! Now we can compile either single or dual core nds files and know how to check for the installed tools and libraries. So should you use CMake? Here is my round up to help you decide!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;The Bad&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Documentation: CMake sometimes requires what feels like &lt;a href="http://catb.org/jargon/html/C/cargo-cult-programming.html"&gt;cargo cult coding&lt;/a&gt; to get the desired result. It took me a lot longer than I would have liked to get this working. Part of the problem as to why I couldn't figure this out was the lack of good documentation. The CMake wiki is, like most wikis, not very well organised. Most help ends up pointing you towards the main site's "documentation" page, which only tells you how to buy a CMake book. The cynical side of me believes that this is a deliberate strategy - why have good free docs when you can sell books?&lt;br /&gt;&lt;br /&gt;Syntax: I think the whole mixed case thing is a bit yucky. ALL IN CAPS makes things tricky to read, but at least you know you'll get it right. Mixing case is easier on the eye, but has the potential for cock ups. Meh.&lt;br /&gt;&lt;br /&gt;Make's limitations: As we've seen here, there are problems when we push CMake to do things it possibly wasn't meant to do. Often the lowest-common-denominator build tool underneath leaks through the abstraction CMake provides. When I was trying to get the nds file to depend on the 2 binaries built in the sub directories, all the errors came from make - the cmake script looked correct. And those time stamped dependency checks... are you from the past?&lt;br /&gt;&lt;br /&gt;Needs installing: Before we can do anything we have to install CMake itself, as well as the bog-standard make (or platform equivalent). This is extra bootstrapping that is not always necessary - waf manages to get round this on Linux, at least.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;The Good&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Cross platform: we can generate build scripts native to the host platform. Cool!&lt;br /&gt;&lt;br /&gt;Configure checks: We can check that the building machine has everything we need to compile our project. If not, we can provide usefull info on how to obtian the code. This is better than having the build explode with "error: foo.h not found" followed by a billion other errors.&lt;br /&gt;&lt;br /&gt;Compact syntax: The syntax of CMake is streamlined for building stuff. It's less wordy than make alone and more to-the-point than the other competitors in this field.&lt;br /&gt;&lt;br /&gt;Starting to gain critical mass: I think this is important. There's no point using something if you're going to be the only one that uses it. CMake is now gaining enough popularity that it is fairly well tested, has a stable API and enough features to make it worthwhile.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Conclusion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Nobody is going to move away from regular Makefiles to compile the standard "Hello, World!" example. But when your project starts to grow in size and you introduce more sub-libraries, or unit tests, or want to have better control of the way the code gets built, then it's nice to know there are better options out there. I think CMake is a worthy candidate for consideration. The learning curve is quite shallow, especially if you already are familiar with Make or bash scripting, and it is something that is gradually gaining more mainstream recognition. Hey, at least it isn't as difficult to use as &lt;a href="http://en.wikipedia.org/wiki/GNU_build_system"&gt;autohell&lt;/a&gt; ;-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-5516123929242479696?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/5516123929242479696/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2008/09/alternatives-to-make-part-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/5516123929242479696'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/5516123929242479696'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2008/09/alternatives-to-make-part-1.html' title='Alternatives to Make, Part 1'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-395920015664996384</id><published>2008-08-26T23:51:00.010+02:00</published><updated>2009-04-08T00:02:53.664+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bunjalloo'/><title type='text'>GMail in new Bunjalloo version</title><content type='html'>I've made a &lt;a href="http://code.google.com/p/quirkysoft/downloads/detail?name=bunjalloo-0.7.zip"&gt;new release of Bunjalloo&lt;/a&gt;. This version adds inline images, amongst other things.&lt;br /&gt;&lt;br /&gt;What I really want to discuss though is this comment that gronfeldt posted on the &lt;a href="http://code.google.com/p/quirkysoft/wiki/Bunjalloo"&gt;Bunjalloo wiki/discussion thing&lt;/a&gt;:&lt;br /&gt;&lt;blockquote&gt;Comment by gronfeldt, Aug 07, 2008&lt;br /&gt;&lt;br /&gt;The browser is great! It's great that the project is still active. I'm mostly&lt;br /&gt;stoked about being able to access GMail, but after hours of trying everything I&lt;br /&gt;can think of I'm still not having any luck. I found a blog somewhere that said:&lt;br /&gt;&lt;br /&gt;"Luckily there is a work around - once logged in to the Google collective, you&lt;br /&gt;can navigate to http://www.google.com/xhtml and from there to the Mobile GMail&lt;br /&gt;portal. That works fine and has a better layout for the DS to boot."&lt;br /&gt;&lt;br /&gt;The trouble is I can't get anywhere near a page that would allow me to log on&lt;br /&gt;without having to wait a very long time only to receive a message saying&lt;br /&gt;"Unable to load:........".&lt;br /&gt;&lt;br /&gt;If someone who has been able to access GMail has a minute I would love it if&lt;br /&gt;they could add a comment with the steps to getting access to GMail.&lt;br /&gt;&lt;br /&gt;Thanks so much Richard for putting all this work into something for the&lt;br /&gt;community, very admirable of you.&lt;br /&gt;&lt;/blockquote&gt;No problem gronfeldt! I hope this problem hasn't put you off. It's not too good that he couldn't access GMail, as it definitely works (for me, at least). A couple of things make it more difficult than it should be I suppose, so here are the instructions based on version 0.7.0.&lt;br /&gt;&lt;br /&gt;First of all, navigate to https://mail.google.com. All ok so far.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_nzN39P0Ykuk/SLR9md4Yw1I/AAAAAAAAAmU/5Q09ejFSlFk/s1600-h/01enter_address.png"&gt;&lt;/a&gt;&lt;div style="text-align: left;"&gt;Once the page loads, you will need to allow Google to set cookies. By default not all domains are allowed to set them, as this is a privacy problem and, on a limited memory device, a memory problem too. So select the options icon, then the cookie add icon. This is explained in &lt;a href="http://code.google.com/p/quirkysoft/wiki/Bunjalloo#Edit_Prefs"&gt;the Bunjalloo wiki&lt;/a&gt; in more detail, just in case.&lt;/div&gt;&lt;br /&gt;Allow the google.com top-level domain by selecting the radio button and clicking Accept. This means mail.google.com and www.google.com will both be able to do the cookie thing, which is required.&lt;br /&gt;&lt;br /&gt;Now enter your user name and password as usual. Once entered, click the sign on button.&lt;br /&gt;&lt;br /&gt;Now comes the tricky/buggy bit. There's a bug *somewhere* in Bunjalloo which causes the sign-on process to stop. You'll reach a redirect page and nothing seems to be happening (no more page loads), and it is because of the bug. I'm not sure why, but redirects screw up occasionally. Hitting refresh, or the "moved here" link fixes the problem though, and the sign on carries on... until it stops again :-)&lt;br /&gt;&lt;br /&gt;Here it is due to the lack of javascript. So click the "no javascript" or "mobile device" link to finally log in to gmail&lt;br /&gt;&lt;br /&gt;That's it! Wasn't it easy? ;-) Next time cookies will be allowed, so you will only have to log-on/refresh/click. I'll keep trying to improve this as it is currently rather annoying, but hey! it (mostly) works. Shame SSL is so slow :-(&lt;br /&gt;&lt;br /&gt;There are 2 places with room for improvement here. First, cookies are currently only partially implemented. They should be stored to disk as well as in memory, obeying the correct caching and expiry rules. This would mean that your log in session would be remembered between reboots. There's a lot of work needed there. Secondly, the redirection logic is broken. This is tricky to debug and has been plaguing Bunjalloo pretty much since I started so I would like to fix it "soon".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-395920015664996384?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/395920015664996384/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2008/08/gmail-in-new-bunjalloo-version.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/395920015664996384'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/395920015664996384'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2008/08/gmail-in-new-bunjalloo-version.html' title='GMail in new Bunjalloo version'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-6958090822081013890</id><published>2008-05-28T23:38:00.004+02:00</published><updated>2009-11-06T22:51:41.355+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Git'/><category scheme='http://www.blogger.com/atom/ns#' term='Google Code'/><title type='text'>Google Code, Git and Subversion II</title><content type='html'>There have been a &lt;a href="http://google-opensource.blogspot.com/2008/05/develop-with-git-on-google-code-project.html"&gt;couple&lt;/a&gt; of &lt;a href="http://google-opensource.blogspot.com/2008/05/export-git-project-to-google-code.html"&gt;posts&lt;/a&gt; on the &lt;a href="http://google-opensource.blogspot.com/"&gt;Google Open Source Blog&lt;/a&gt;. The second one is an in depth article about &lt;a href="http://google-opensource.blogspot.com/2008/05/export-git-project-to-google-code.html"&gt;mirroring git repositories to Google Code's (GC) subversion repo&lt;/a&gt;. Having tried this out in the past, and helped a blog-commenter through the steps to mirror his git repo in svn, I can't help but feel that the post causes more problems than it solves.&lt;br /&gt;&lt;br /&gt;First off, it's way too complicated! I'm quite experienced at using both subversion and git now, but I really cringe at that last set of commands to push to the svn mirror. Compared to "git push origin master" when using a native git repo, it makes me feel queasy. If I were the cynical type, I'd say that Google are just trying to make git look overly complicated compare to svn by forcing git to jump through hoops. Compare the command-fu there to a normal everyday "add, commit" work cycle and no wonder people have a bad impression of git.&lt;br /&gt;&lt;br /&gt;Subversion is a lossy repository format. Author information is lost, date information is munged. The svn repo just has the author who ran dcommit, not the guy wrote the patch. Nor will it preserve the correct date, just the time when you ran dcommit. The admin user may change subversion revprops (date, message, author) but that's more manual steps and more opportunity for messing up.&lt;br /&gt;&lt;br /&gt;If anything goes wrong while pushing to svn  - and it will, the Google svn servers fail every now and again, they're only mechanical - then your push-to-svn git branch gets hosed. Like "git reset git-svn" hosed, so you can just send one big patch. If you have to sync more than a few commits, it's a bit risky. The blog hints at this problem ("commit to a local repo and use svnsync"), but the fact is that it's all a bit slow, sucky and error prone.&lt;br /&gt;&lt;br /&gt;However, there's an easier way - cut &lt;a href="http://code.google.com/p/quirkysoft/wiki/SourceCode"&gt;Subversion out of the loop&lt;/a&gt;. On your GC page, go to Administer &gt; Tabs and fill in the Source field. Add a wiki file named Source, for example, and in it place instructions on how to clone your proper git repository from github.com, repo.or.cz, or wherever. Then just use svn for the wiki, GC for the downloads and the issue tracker.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/msysgit/"&gt;Git works OK on Windows too&lt;/a&gt;, apart from some strange CRLF problems. Yes, CRLF problems. In 2008. I know, it's crap.&lt;br /&gt;&lt;br /&gt;"Why not widen the audience?" the GOSB asks us. And I ask, why not &lt;span style="font-style: italic;"&gt;enlighten&lt;/span&gt; the audience as to the benefits of moving on to a next gen VCS? Open up the minds of the Subversion-users, whose patch sets will be both easier for them to create and easier for you to integrate via Git.&lt;br /&gt;&lt;br /&gt;Not that anyone ever sends me patches, grumble, grumble...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-6958090822081013890?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://google-opensource.blogspot.com/2008/05/export-git-project-to-google-code.html' title='Google Code, Git and Subversion II'/><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/6958090822081013890/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2008/05/google-code-git-and-subversion-ii.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/6958090822081013890'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/6958090822081013890'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2008/05/google-code-git-and-subversion-ii.html' title='Google Code, Git and Subversion II'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-8494399886195551875</id><published>2008-03-16T17:57:00.003+01:00</published><updated>2009-04-08T00:03:15.177+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bunjalloo'/><title type='text'>Forthcoming changes in Bunjalloo</title><content type='html'>An update on the status of Bunjalloo. I'm fiddling about with options and how to present them at the moment. Last release saw a change in the way I deal with configuration. Up until 0.5.4, the release zip would overwrite the config.ini, search.cfg and  allowed cookies file. It was pretty unlikely that many people actually changed these files, since the configurable things have been a bit limited and changing them required a bit of effort, but as options are added it is more and more likely. Well, now it will be possible to change the language and default download location from a configuration screen. The design is typically lo-fi, but seems to work okay.&lt;br /&gt;&lt;br /&gt;Next up is to make the list of pages allowed to set cookies editable. The default behaviour of all popular browsers - allow anyone to set any cookie - is not a very wise choice from a privacy point of view. So I've gone the other way and made the list of allowed sites whitelist-based. If you're not on the list, you're not setting cookies. However, in order to add a site to the list one has to use an external editor, which isn't too user friendly. A way to do this from a settings screen is on the list of things to do.&lt;br /&gt;&lt;br /&gt;If the release doesn't drag on, I also want to add an automatic updater, &lt;a href="http://code.google.com/p/quirkysoft/issues/detail?id=48"&gt;as suggested by Sarvesh&lt;/a&gt;. This will probably be semi-automatic - i.e. a button with "check for updates" - since the DS network is not the fastest and over zealous checking would be most irritating. This requires adding (at least) unzip support, so would be quite a big addition. It would also mean that zip files could be opened up from within Bunjalloo, which might be interesting.&lt;br /&gt;&lt;br /&gt;If I manage all that, which is not likely, I also want to add configurable quick searches. These are searches that are triggered by typing a single letter followed by the search term into the address entry text box. Currently these are hard wired in the search.cfg file (g, y and w for Gogle, Yahoo and Wikipedia), but a system similar to Firefox's quick search wouldn't be too tough to add.&lt;br /&gt;&lt;br /&gt;Of course if you would like to see any other features, or help speed up the addition of the above ones, patches are always welcome. I'd be interested to hear from anyone who has tried to compile the source code, and how it went.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-8494399886195551875?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/8494399886195551875/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2008/03/forthcoming-changes-in-bunjalloo.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/8494399886195551875'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/8494399886195551875'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2008/03/forthcoming-changes-in-bunjalloo.html' title='Forthcoming changes in Bunjalloo'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-6593714278970718555</id><published>2008-03-13T21:27:00.004+01:00</published><updated>2009-04-08T00:03:21.789+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Git'/><title type='text'>My top 6 git commands.</title><content type='html'>I've been using git for about 6 months now with my Google Code projects but I am by no means an expert. There's a lot to learn. While the documentation is complete, it can be overwhelming seeing all those options and commands.  So here are my 6 git commands that I use quite often when working with subversion repositories.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;1. git status&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;My most commonly used command by a fairly large margin. For a subversion user it can look a bit confusing at first. Why have two classes of changed files? Why not just commit all the changes? Hey, at least it can be in colour! But now that I understand the index and when to stage changes, it's absence in svn is sorely missed.&lt;br /&gt;&lt;br /&gt;Don't forget to add this alias - it saves a lot of typing.&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;&lt;span style="font-size:85%;"&gt;git config --global alias.st status&lt;/span&gt;&lt;/blockquote&gt;Now you can use simply &lt;span style="font-style: italic;"&gt;git st&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;2. git gui&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is a powerful mix of the status, diff, add and reset commands. By showing the changed files and letting you mix and match which ones to commit, creating meaningful patches and a logical check-in history is a lot easier. It also makes it harder to accidentally check in changes that are just for testing - though not impossible. Did I mention how much I really miss the whole staging area idea when I use subversion?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;3. gitk --all&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Having branches is nice, but if you can't visualize them it is pointless. This tool makes it dead simple to see what branches you have and, important for git-svn users and those who push to proper git repos, where you can see at a glance where the &lt;span style="font-style: italic;"&gt;HEAD&lt;/span&gt; is compared to your remote branches.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;4. git svn&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Usually in the form of git-svn dcommit. I've aliased that one to svnci:&lt;br /&gt;&lt;span style="font-family: courier new;font-size:85%;" &gt;&lt;blockquote&gt; git config --global alias.svnci "svn dcommit"&lt;/blockquote&gt;&lt;/span&gt;This makes working with SVN repositories a much nicer experience. Being able to see all the history at a glance, commit changes instantly and "rewrite history" are especially handy.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;5. git merge&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When I wrote my &lt;a href="http://quirkygba.blogspot.com/2007/10/using-git-with-google-code-hosting.html"&gt;HOWTO for using git with a Google Code repository&lt;/a&gt;, I mentioned that merging between branches was a bad idea. Well, that's not &lt;span style="font-style: italic;"&gt;strictly&lt;/span&gt; true. At the time I was ignorant to the fact that the merge performs a "fast forward merge" if there are no other changes on the merged-to branch.&lt;br /&gt;&lt;br /&gt;Eh?&lt;br /&gt;&lt;br /&gt;Basically, it meant that with git-svn, if you merge a branch into master, and master had not moved on since the other branch was created, it could cause master to lose its upstream svn remote trunk tracking. The solution is to use the --no-ff flag when merging.&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;git checkout master&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;git merge --no-ff mytopic&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;This creates an extra commit on master corresponding to the merge, which can now be dcommit'ed to subversion. Ideally the other branch would also be in subversion, otherwise the merge commit just says "merged branch 'mytopic'", with no real way of knowing what commits went into it.&lt;br /&gt;&lt;br /&gt;Of course should you lose your git repository there would be no way to know which revisions of which branches are merged into master (trunk), even if the branches are stored in the svn server. This is more a limitation due to svn than git, as svn has no built in merge tracking. One solution would be to push the git repository to a separate server too, just in case.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;6. git rebase&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So you've created a local branch that you'd like to "publish" in the subversion repository. Here's how you could go about it using git-rebase and a couple of other tricks. First find the svn revision that the git branch is based on:&lt;br /&gt;&lt;span style="font-family: courier new;font-size:85%;" &gt;&lt;blockquote&gt;sha1 = $( git rev-list --boundary &lt;span style="color: rgb(51, 102, 255);"&gt;$branch&lt;/span&gt;...master | grep ^- | cut -c2- )&lt;/blockquote&gt;&lt;/span&gt;That should hopefully give you the commit sha1 of the branch point. Convert it to a svn revision number:&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;&lt;blockquote&gt;revision = $( git svn find-rev &lt;span style="color: rgb(51, 102, 255);"&gt;$sha1&lt;/span&gt; )&lt;/blockquote&gt;&lt;/span&gt;&lt;/span&gt;Now create a branch in the subversion repository from trunk at that revision:&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;&lt;blockquote&gt;svn cp -r &lt;span style="color: rgb(51, 102, 255);"&gt;$revision&lt;/span&gt; &lt;span style="color: rgb(51, 102, 255);"&gt;$SVNREPO&lt;/span&gt;/trunk &lt;span style="color: rgb(51, 102, 255);"&gt;$SVNREPO&lt;/span&gt;/branches/$branch&lt;/blockquote&gt;&lt;/span&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_nzN39P0Ykuk/R9mTms6IWHI/AAAAAAAAAME/6rXw5dBSDFY/s1600-h/1.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://bp1.blogger.com/_nzN39P0Ykuk/R9mTms6IWHI/AAAAAAAAAME/6rXw5dBSDFY/s200/1.png" alt="" id="BLOGGER_PHOTO_ID_5177331539738384498" border="0" /&gt;&lt;/a&gt;If you run git svn rebase --all at this point, you'll have a new remote branch at the same point as the base of your git branch. Something like the image here. The hiccup now is that [branch] is not associated to the remote branch in any way. Here's where we need to rebase:&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new;"&gt;&lt;blockquote&gt;git rebase --onto remotes/&lt;span style="color: rgb(51, 102, 255);"&gt;$branch&lt;/span&gt; master &lt;span style="color: rgb(51, 102, 255);"&gt;$branch&lt;/span&gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_nzN39P0Ykuk/R9mTIc6IWGI/AAAAAAAAAL8/BFhKNRORWO4/s1600-h/2.png"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 228px; height: 97px;" src="http://bp0.blogger.com/_nzN39P0Ykuk/R9mTIc6IWGI/AAAAAAAAAL8/BFhKNRORWO4/s200/2.png" alt="" id="BLOGGER_PHOTO_ID_5177331020047341666" border="0" /&gt;&lt;/a&gt;This "moves" our local branch on top of the remote branch, keeping master as the parent of both. Running git-svn dcommit now will "push" the local changes on [branch] into the remote subversion branch. Ok, so maybe I don't use this command that often, but it is handy to know what you can use it for.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-6593714278970718555?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/6593714278970718555/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2008/03/my-top-6-git-commands.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/6593714278970718555'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/6593714278970718555'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2008/03/my-top-6-git-commands.html' title='My top 6 git commands.'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/_nzN39P0Ykuk/R9mTms6IWHI/AAAAAAAAAME/6rXw5dBSDFY/s72-c/1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-2223402744742429540</id><published>2008-02-25T22:29:00.002+01:00</published><updated>2009-04-08T00:03:36.604+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bunjalloo'/><title type='text'>Bunjalloo Update</title><content type='html'>Lately I've read some positive comments about my home-brewed web browser on a few different forums and news sites. It's nice to know that people find the software useful! I've also received some suggestions via email on how to make the browser even better for people.  One of the interesting things about having a homebrew browser is that it can do things that the official browser can't, like download files to the memory card or provide translations for languages other than the official 5.&lt;br /&gt;&lt;br /&gt;So with this in mind, I'm now working on improving the way Bunjalloo downloads files. Currently it's not very user friendly and requires you to download the file, then save it. This is pretty unintuitive - it'd be better to sniff out the MIME-type of file that the user clicks on, then either download and show it for supported image and text MIME types, or offer to save it to disk for "exotic" MIME types. Y'know, a bit like everyone else does it :-)&lt;br /&gt;&lt;br /&gt;As for translations, there's not much user interface to translate at the moment, but what is there has now been pulled out into resource files, defined per language. Currently only the languages supported internally by the DS are selectable, and the language displayed can only be altered by changing the DS's language option from the system settings. But this is only a beginning, if there is enough interest I can extend language support to those not built in to the DS via a configuration option. The actual translations into other languages need doing, so if you want to help out let me know. I have English and Spanish done, Italian, French and German are needed, as is Japanese.  Sadly Japanese won't work without changing the font, the one I have at the moment doesn't include the full range of universal characters.&lt;br /&gt;&lt;br /&gt;Speaking of helping out, keep that feedback coming. Star issues that you think are most important, report bugs, even write patches ;-) There's a new &lt;a href="http://groups.google.com/group/bunjalloo-discussion"&gt;mailing list/forum&lt;/a&gt; for discussing Bunjalloo if mailing me is too much hassle. I look forward to hearing from you!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-2223402744742429540?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/2223402744742429540/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2008/02/bunjalloo-update.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/2223402744742429540'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/2223402744742429540'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2008/02/bunjalloo-update.html' title='Bunjalloo Update'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-2535715653579617048</id><published>2007-12-31T16:01:00.000+01:00</published><updated>2009-04-08T00:06:53.788+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Elite'/><title type='text'>Another Elite AGB/DS Update</title><content type='html'>A hectic few weeks in RL (I'm now a dad) have meant that I have not been able to dedicate much time to coding. However, I've ironed out the last few DS specific bugs in my port of Elite AGB and it is now playable. The only major issue left to resolve is the sound. The XM player that I wrote for the GBA version is incompatible with the DS by design, due to the hardware differences. I have integrated &lt;a href="http://forum.gbadev.org/viewtopic.php?t=12997&amp;amp;highlight=libntxm"&gt;libntxm&lt;/a&gt; but it has a problem that causes notes to be cut short. The GBA sound effects use the GB sound hardware, which can be emulated on the DS using its PSG sound system. I got this working without too much hassle, but I get the feeling that it doesn't play nicely with libntxm either. The sound effects work when libntxm is not activated in the build, but adding it in causes the sounds to break.&lt;br /&gt;&lt;br /&gt;I think the best option at this point is to remove XM playback - remove the crappy music ;-) - until I port my own XM player to the DS. This way I can make a release soon-ish before I get really sick of the whole thing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-2535715653579617048?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://code.google.com/p/ds-elite/' title='Another Elite AGB/DS Update'/><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/2535715653579617048/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2007/12/another-elite-agbds-update.html#comment-form' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/2535715653579617048'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/2535715653579617048'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2007/12/another-elite-agbds-update.html' title='Another Elite AGB/DS Update'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-3893043427053030145</id><published>2007-12-14T20:21:00.000+01:00</published><updated>2009-04-08T00:06:25.705+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DS'/><category scheme='http://www.blogger.com/atom/ns#' term='Review'/><title type='text'>Blame Jeff for the delay...</title><content type='html'>There's a reason I've not released anything yet - &lt;a href="http://www.zincland.com/powder/"&gt;POWDER&lt;/a&gt;. Jeff Lait's devilishly addictive Rogue-like has me hooked. I played it on the GBA a couple of years back, but I've recently rediscovered it in the DS version, with its bigger screen and slightly nicer controls (X+Y are more comfortable than the Start + Select)&lt;br /&gt;&lt;br /&gt;Unlike Nethack and friends, Powder was designed for the GBA's d-pad controls - there are no diagonally moving monsters apart from the weak grid-bug - and this really helps the flow of the game. It is very &lt;span style="font-style: italic;"&gt;fast. &lt;/span&gt;There's also a high wheat to chaff rate - interesting items are abound. On the first few levels you'll have loads of great wands of zapping, potions of damage or healing, and swords of slicing. To decrease the frustration factor, your inventory is huge and you aren't penalised for carrying lots of items. Not very realistic, but immensely gratifying. There's nothing worse that having your movements hampered because your &lt;a href="http://en.wikipedia.org/wiki/Diogenes_syndrome"&gt;Diogenes syndrome&lt;/a&gt; kicks in and you can't bare to throw any of your junk away in case it's useful later.&lt;br /&gt;&lt;br /&gt;The dungeon layouts are good too, with the random generator spitting out some interesting set piece rooms every now and again. Woe betide the newbie adventurer who comes across an island of ghosts as shallow as the 4th level! The layout is optimised for the GBA's 512x512 tile mode and the wrap around is a cute idea that makes the levels seem bigger than they really are. The graphics are decent for a homebrew game, perhaps the only quibble is the contrast of the text on the items screen (white on grey) as it can be difficult to make out at times. The main character is novel in the way that your on screen player avatar shows what he is wearing and clutching in his mitts at all times. There's an air of Monty Python absurdity to it each time a new game starts off with the hero stood there, bright pink and in his Y-fronts.&lt;br /&gt;&lt;br /&gt;The gods of the game - in all there are 7 - play a crucial part to the way you decide to explore the dungeon. I don't mean just praying for food when you feel a bit peckish either a la Nethack, it is a bit deeper than that. Each of the 7 gods expects a specific behaviour from its desciples and failure to fulfil a god's wishes can end in tears. For example the god of the barbarians, H'ruth, expects plenty of killing and no magic use. If you are a wizard in training then it is very likely you'll piss H'ruth off. Luckily the wizard leader Belweir will protect you, so while H'ruth may poison the player, Belweir will cure the poison and provide gifts of magical items.&lt;br /&gt;&lt;br /&gt;The god system has a slight flaw in that the fighter god Klaskov is very easily pleased, so rampaging through the game casting a few damage spells is usually enough to get in his good books. I have no idea how to please the pacifist Pax - casting cure seems to work, but killing any innocent rodents usually ends up with a dead player. These aren't even defects really, indeed they could even be considered extra challenges - "easy" mode would be to play as a fighter, while "hard" would be trying to get through as a cleric. Though quite what the god &gt;&lt;0|V| expects is anyone's guess.&lt;br /&gt;&lt;br /&gt;Food plays an interesting role too. There's a saying "you are what you eat" and Powder covers this pretty well. Eating a char grilled fire snake will give you the ability to avoid fire attacks, while eating grid bug bodies leaves you immune to spark attacks. Unlike other rogue-likes the enemy corpses tend not to go rotten, so unless a baddie is obviously poisonous it is usually safe to eat it after defeating it. But don't go overboard if you plan on being a cleric - killing innocent Kiwis and scoffing them down is not very nice. Despite the lower starvation rate than other similar games, lately I've been getting snuffed out because in my hungry state my health wasn't regenerating...&lt;br /&gt;&lt;br /&gt;Some spoilers you say? OK, stop reading now if you want to discover these things for yourself!&lt;br /&gt;&lt;br /&gt;There's a whole dressing up sub-game hidden within the game. I've so far discovered that to dress as a Wizard you require the pointed shoes, plain robe and floppy hat. In your hands you can carry either nothing (not recommended) or a staff. The advantages... I'm not sure yet. It obviously pleases the gods. To dress as a Ranger, you need a leather tunic or the studded variety, hiking boots, a leather cap and either a bow or a torch in your hands. This get up seems to give you better searching abilities and may also help your ranged weapon attack damage... but it's difficult to say. The powder web site also mentions dressing as a Fighter. I've not discovered this one yet though, but I bet it requires a hefty warhammer and some sturdy iron boots.&lt;br /&gt;&lt;br /&gt;Anyway, let's hope I get over this addiction soon. And meanwhile, I really recommend you checking out the latest version. It's one of the unsung classics of the homebrew scene.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-3893043427053030145?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.zincland.com/powder/' title='Blame Jeff for the delay...'/><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/3893043427053030145/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2007/12/blame-jeff-for-delay.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/3893043427053030145'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/3893043427053030145'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2007/12/blame-jeff-for-delay.html' title='Blame Jeff for the delay...'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-7057532369845214847</id><published>2007-11-25T17:34:00.000+01:00</published><updated>2009-04-08T00:06:33.746+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Elite'/><title type='text'>WIP update - Elite DS</title><content type='html'>I got side tracked with &lt;a href="http://www.coranac.com/projects.php"&gt;grit&lt;/a&gt;, adding the ability to share a palette between various images. Now that this problem is solved (Cearn sent me an interesting program to merge image palettes after I sent him a patch against grit to do something similar) Elite AGB compiles for the DS. All that's left is to get it working! :-)&lt;br /&gt;&lt;br /&gt;At the minute the NDS file just shows 2 white screens; a familiar situation for anyone who has coded anything on the DS. So now to &lt;a href="http://code.google.com/p/quirkysoft/wiki/DebuggingNotes"&gt;start debugging&lt;/a&gt;...&lt;br /&gt;&lt;br /&gt;EDIT: heh. here's a screenshot of the first build running in &lt;a href="http://sourceforge.net/projects/desmume"&gt;desmume&lt;/a&gt;. &lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_nzN39P0Ykuk/R0tJDI1NTpI/AAAAAAAAABc/retaB7zoY5w/s1600-h/Screenshot-Desmume+64.102564.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://bp2.blogger.com/_nzN39P0Ykuk/R0tJDI1NTpI/AAAAAAAAABc/retaB7zoY5w/s200/Screenshot-Desmume+64.102564.png" alt="" id="BLOGGER_PHOTO_ID_5137280118205271698" border="0" /&gt;&lt;/a&gt;Yes, it is a straight GBA port.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-7057532369845214847?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/7057532369845214847/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2007/11/wip-update-elite-ds.html#comment-form' title='15 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/7057532369845214847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/7057532369845214847'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2007/11/wip-update-elite-ds.html' title='WIP update - Elite DS'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/_nzN39P0Ykuk/R0tJDI1NTpI/AAAAAAAAABc/retaB7zoY5w/s72-c/Screenshot-Desmume+64.102564.png' height='72' width='72'/><thr:total>15</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-5612250643914882190</id><published>2007-11-19T22:38:00.000+01:00</published><updated>2009-04-08T00:07:27.589+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DS'/><category scheme='http://www.blogger.com/atom/ns#' term='GBA'/><title type='text'>Another reason for GBA -&gt; DS ports</title><content type='html'>So I've started working on &lt;a href="http://code.google.com/p/ds-elite/"&gt;&lt;span style="font-style: italic;"&gt;Elite DS&lt;/span&gt;&lt;/a&gt;. First thing I did was to compile my old GBA code with the latest devkitArm r21. No problems there, fixed a buffer overflow and now it runs fine... on &lt;a href="http://sourceforge.net/projects/vba"&gt;VBA&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;My homebrew hardware for the GBA has gone the way of the dodo.&lt;br /&gt;&lt;br /&gt;Well, not quite, but my new laptop doesn't seem to have a parallel port! It has a plastic blob in the shape of a parallel port, but there's no way to pry the thing off - luckily they've remembered to etch the universal symbol for "printer" above it, to mock me. This makes the F2A linker thingy rather useless. One more reason to port all &lt;a href="http://geocities.com/quirky_2k1"&gt;my GBA projects&lt;/a&gt; over to the DS, eh readers?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-5612250643914882190?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/5612250643914882190/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2007/11/another-reason-for-gba-ds-ports.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/5612250643914882190'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/5612250643914882190'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2007/11/another-reason-for-gba-ds-ports.html' title='Another reason for GBA -&gt; DS ports'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-4208953287383140980</id><published>2007-11-12T22:01:00.000+01:00</published><updated>2009-04-08T00:08:04.436+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DS'/><category scheme='http://www.blogger.com/atom/ns#' term='Bunjalloo'/><title type='text'>Future efforts?</title><content type='html'>First, a rant.&lt;br /&gt;&lt;br /&gt;Even though I understand where he's coming from, I don't agree with a lot of Dragon Minded's comments. His latest about wannabe plugin authors, that &lt;a href="http://forum.gbadev.org/viewtopic.php?p=145210&amp;amp;highlight=#145210"&gt;"t&lt;span class="postbody"&gt;hey just wanted to do something easy to get their name on the project"&lt;/span&gt;&lt;/a&gt; seems a bit off - as far as I can see, DSO goes against the spirit of the GPL and actively discourages contributions. How can you do that on one hand and then expect people to use your plugin framework on the other? Or maybe he should just stop reading certain forums - people out for a free ride, downloading Nintendo games, are not going to make useful contributions to very much at all.&lt;br /&gt;&lt;br /&gt;Now the rest of the post.&lt;br /&gt;&lt;br /&gt;Bunjalloo has been open from day 1, and what help people have offered me has been gratefully received, so I don't want to abandon it. But the fact is that debugging Bunjalloo is most of the time a thankless task. The web is full of terrible HTML and hacky connection methods - witness the &lt;span style="font-style: italic;"&gt;simple&lt;/span&gt; google log on process. Web pages are increasingly reliant on Javascript and Flash. Things that we take for granted on a PC browser are a painful nightmare on the DS. It can only get worse as web standards are further extended for more powerful devices and more interactive content.  A kick in the nuts is that even mobile phones have better web browsers. This is mostly due to the tiny memory the DS has - but also because writing these things nowadays is more than a one man project. And I'm fed up!&lt;br /&gt;&lt;br /&gt;So, with your permission, I think I'll take a break from the web browser for a while. Let's leave the apps to the PC and concentrate on the games. After all it's what the DS was designed for, and I have some &lt;a href="http://geocities.com/quirky_2k1/games/elitea/shots.html"&gt;outstanding issues&lt;/a&gt; to &lt;a href="http://geocities.com/quirky_2k1/emulation/index.html"&gt;resolve&lt;/a&gt;...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-4208953287383140980?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/4208953287383140980/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2007/11/future-efforts.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/4208953287383140980'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/4208953287383140980'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2007/11/future-efforts.html' title='Future efforts?'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-6195608262845698241</id><published>2007-11-11T18:52:00.000+01:00</published><updated>2009-04-08T00:08:23.897+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bunjalloo'/><title type='text'>GMail now sort of works</title><content type='html'>I've now managed to read and send gmails from Bunjalloo :-)&lt;br /&gt;&lt;br /&gt;Sadly the log in process to a gmail account is a bit strange. It uses lots of server side 302 redirects, meta content refreshes, cache-control:no-caching and some other voodoo that I haven't yet figured out. It breaks w3m as well, so I'm not alone in my frustration.&lt;br /&gt;&lt;br /&gt;Luckily there is a work around - once logged in to the Google collective, you can navigate to http://www.google.com/xhtml and from there to the Mobile GMail portal. That works fine and has a better layout for the DS to boot.&lt;br /&gt;&lt;br /&gt;The issue page on googlecode doesn't work yet - so you can't post an issue from within Bunjalloo. That's next, meanwhile I'm going to put out a new release.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-6195608262845698241?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/6195608262845698241/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2007/11/gmail-now-sort-of-works.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/6195608262845698241'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/6195608262845698241'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2007/11/gmail-now-sort-of-works.html' title='GMail now sort of works'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-5538011199045022507</id><published>2007-11-05T23:11:00.000+01:00</published><updated>2009-04-08T00:08:23.897+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bunjalloo'/><title type='text'>HTTPS on the way..</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_nzN39P0Ykuk/Ry-XQhfh86I/AAAAAAAAAAw/MgSM7ogNaAY/s1600-h/bunjalloo-no-cookie-err.png"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://bp0.blogger.com/_nzN39P0Ykuk/Ry-XQhfh86I/AAAAAAAAAAw/MgSM7ogNaAY/s200/bunjalloo-no-cookie-err.png" alt="" id="BLOGGER_PHOTO_ID_5129484810722603938" border="0" /&gt;&lt;/a&gt;I've made some advances with HTTPS. I only started today and already Bunjalloo can show the GMail log on page! There is an &lt;a href="http://code.google.com/p/quirkysoft/issues/detail?id=10"&gt;issue that you might like to star&lt;/a&gt; to see when HTTPS finally gets added properly. Put the champagne down for the moment, because it seems my naïve approach to cookies doesn't stand up to the Google log in process. Currently I get told that my browser's cookie functionality is switched off :-/&lt;br /&gt;&lt;br /&gt;Logging on to read my mail is a #1 priority here. Closely followed by posting issues to the aforementioned issue tracker from Bunjalloo itself. I can already browse the subversion code, but I need to add issue posting to really start&lt;span style="text-decoration: underline;"&gt;&lt;/span&gt;&lt;a href="http://buzz.blogger.com/2006/10/chowing-down-on-dogfood.html"&gt;&lt;/a&gt; eating my own dog food. (Yuck.)&lt;br /&gt;&lt;br /&gt;The SSL library I'm using is &lt;a href="http://www.matrixssl.org/"&gt;MatrixSSL&lt;/a&gt;. It took me just a few hours to add and get running on the PC, plus a few more to debug for the NDS. I expected it to take &lt;span style="font-style: italic;"&gt;days&lt;/span&gt; not hours, so I was pleasantly surprised. Now I just have to remove all the damn printfs.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-5538011199045022507?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/5538011199045022507/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2007/11/https-on-way.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/5538011199045022507'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/5538011199045022507'/><link rel='alternate' type='text/html' href='http://quirkygba.blogspot.com/2007/11/https-on-way.html' title='HTTPS on the way..'/><author><name>Richard Quirk</name><uri>http://www.blogger.com/profile/16290285494071462742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='26' src='http://3.bp.blogspot.com/_nzN39P0Ykuk/SsY4qjgsAUI/AAAAAAAABKs/p5m2c1oXgZ0/S220/Untitled.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_nzN39P0Ykuk/Ry-XQhfh86I/AAAAAAAAAAw/MgSM7ogNaAY/s72-c/bunjalloo-no-cookie-err.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9675303.post-5358875980115501496</id><published>2007-10-29T22:10:00.000+01:00</published><updated>2009-04-08T00:08:23.897+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bunjalloo'/><title type='text'>Bunjalloo 0.4 beta</title><content type='html'>The first beta of the 0.4 series is out. I've finally added image support, which means I had to use  a lot of external libs. What is the best way to handle these? Well, zlib and libpng are under active development and maintenance so I've just added the DS Makefiles to my Subversion repository. That way I can just recompile with a new version if necessary.&lt;br /&gt;&lt;br /&gt;The gif_lib code needed a config.h for some NDS specific changes, so that has Makefiles and a header. Finally, I tried tinyjpeg, which was too limited, so opted for the jpegdecoder library. This needs some changes to the actual library for a couple of bug fixes - one show stopper for little endianness problems that only show up on hardware. As such, I've imported the whole library into my subversion's /external directory - the upstream release compiles OK, even works for some images, but shows cropped images for larger jpegs on a real DS.&lt;br /&gt;&lt;br /&gt;All these libraries install to the &lt;span style="font-style: italic;"&gt;de facto&lt;/span&gt; standard $DEVKITPRO/libnds directory.&lt;br /&gt;&lt;br /&gt;I really should document all this properly, but no one's asked me anything about compiling the code so I assume there's not much interest.&lt;br /&gt;&lt;br /&gt;Oh, this new release is compiled with  &lt;a href="http://quirkygba.blogspot.com/2007/10/murphys-law.html"&gt;devkitArm r21&lt;/a&gt;, so it's cutting edge!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9675303-5358875980115501496?l=quirkygba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://quirkygba.blogspot.com/feeds/5358875980115501496/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://quirkygba.blogspot.com/2007/10/bunjalloo-04-beta.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/5358875980115501496'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9675303/posts/default/5358875980115501496'/><link rel='alternate' type='text/html' href='http://q
