tag:blogger.com,1999:blog-96753032024-03-08T05:22:33.129+01:00Homebrew CodingDetails of what I'm wasting my time on at the moment, in particular what homebrew game or console project I'm working on.Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.comBlogger106125tag:blogger.com,1999:blog-9675303.post-19890439527657319782015-06-14T19:00:00.000+02:002015-06-14T19:00:00.876+02:00Blade Reminder App for Android<div dir="ltr" style="text-align: left;" trbidi="on">
In recent years the traditional double-edged safety razor has <a href="http://www.nytimes.com/2014/11/20/style/safety-razors-regain-popularity-for-men.html">been</a> <a href="http://www.economist.com/blogs/schumpeter/2013/08/male-grooming">gaining</a> <a href="http://www.forbes.com/sites/karstenstrauss/2015/05/05/not-your-grandfathers-razor-ikon-and-the-business-of-mens-grooming">popularity</a>.
<br />
<a href="https://www.blogger.com/blogger.g?blogID=9675303" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjO80iMMXpcx6Wtgjk3FpRb1FCBz_wv_2pnccU_fHpxd3vXILib5-jw1S3F4FTDQ_yEhj3mSFbqBVEbVzgQVzvITgFO1AEVwsTj8DW5dqsCFhjWYzHNUZGvPXs-1MUtcG3gGcDO2Q/s1600/razor.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="177" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjO80iMMXpcx6Wtgjk3FpRb1FCBz_wv_2pnccU_fHpxd3vXILib5-jw1S3F4FTDQ_yEhj3mSFbqBVEbVzgQVzvITgFO1AEVwsTj8DW5dqsCFhjWYzHNUZGvPXs-1MUtcG3gGcDO2Q/s320/razor.jpg" width="320" /></a></div>
<br />
<a href="https://www.blogger.com/blogger.g?blogID=9675303" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a><br />
I've also joined the ever-growing fanbase of safety razors.
And to help me keep track of when I last changed my razor blade I've created <a href="https://play.google.com/store/apps/details?id=es.quirk.bladereminder">this Android app called Blade Reminder</a>.
The app is pretty simple, showing a list of dates, number of times the blade's been used, and a comment
(in case I forget how well that day's face scraping went).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEird6qh4x7sK9mkTa-S7nrFCxs-h_uH12ZPX96Fe_ZGaB3_J676iRFALdFE0rdpMqO-zwNmomADN_HIXrutsgSYWg_bq7lMTKYU2SN9_zV19rePVB4kj4QwxTfYeKFOKBoMpjFBuw/s1600/device-2015-06-14-155628.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEird6qh4x7sK9mkTa-S7nrFCxs-h_uH12ZPX96Fe_ZGaB3_J676iRFALdFE0rdpMqO-zwNmomADN_HIXrutsgSYWg_bq7lMTKYU2SN9_zV19rePVB4kj4QwxTfYeKFOKBoMpjFBuw/s320/device-2015-06-14-155628.png" width="180" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLhSlP8pxjLqKaszUNgkWdnCZId1p8BPMzwlZQVhhKUR4Qmg-6UvGI3i7yypuT6AMfVM_CPdlvzhm4-FvueTmeQvVpfTwVxizYqlEKLw0DeHraiLld9PDB3Ob22ErhYqpICnSJdw/s1600/device-2015-06-14-155741.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgLhSlP8pxjLqKaszUNgkWdnCZId1p8BPMzwlZQVhhKUR4Qmg-6UvGI3i7yypuT6AMfVM_CPdlvzhm4-FvueTmeQvVpfTwVxizYqlEKLw0DeHraiLld9PDB3Ob22ErhYqpICnSJdw/s320/device-2015-06-14-155741.png" width="180" /></a></div>
<br />
So what's the appeal of the safety razor over more modern inventions?
I think most converts would agree that a big factor is the cost.
Multi-blade cartridge razors feel like such a rip off in comparison.<br />
<ul>
<li>DE blades cost less than 15€ for 100 (online)</li>
<li>Even offline in the supermarket they cost less than 3€ for 10</li>
<li>Compare that to the Mach 3, which costs 20€ or more for an 8 pack of blades</li>
<li>The initial outlay for a DE razor is more, but it's a sturdier piece of kit</li>
</ul>
You could make those Mach 3s last a couple of years too, if you don't mind shaving with a dull instrument most of the time.<br />
<br />
Cost isn't the only factor of course, since if you want to spend more then a good razor and badger brush can be pricey.
I think that once you get the technique down, the safety razor provides a shave that is comparable to a cartridge,
but is more comfortable to perform.<br />
<br />
Yes, there is a definite learning curve.
This difficulty could be another paradoxical reason for the increased popularity of the safety razor.
Requiring effort to use something makes people feel like they are not such failures when they finally do gain the necessary skill.
It's the "I like using this because it makes me feel less of a n00b"-effect.
<a href="http://www.psmag.com/navigation/nature-and-technology/surprising-appeal-products-require-effort-use-86567/">This article talks about the phenomenon of popular products that require effort to use</a>.<br />
<br />
Knowing when to change the blade in a DE razor is something that you have to learn.
It tends to take about a week of daily use before a used blade starts tugging at hairs rather than slicing through them.
Of course the duration of a blade depends on a lot of factors, such as how stubbly you are and the make of blades,
but 5 uses seems to be about average.<br />
<br />
At the point the blade starts to dull, one tends to instinctively press a fraction harder.
This extra pressure ends up causing nicks and razor burn.
By keeping track of the number of times you've used the blade, you get to know when you need to switch it out.
Or at least it makes you think about those things.<br />
<br />
That's where this app comes in! I started making this months ago, but I it has taken me this long to get round to releasing it.
As well as the main spreadsheet-like application I've also added a widget that shows the usage and date from the last time you used the app.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAlrkk5HY-8rgf3FzqcxiaOUO5xXJ1PqXkZdbaqbmdCnJVaGtt1AchUOaeNKVct8xFPjEPw1npH_LW4nM8WArhJrXHUbF1sPt0MMTVgdU04l2qwXDbE34XIYpNZiUTl9FVMIh5Ow/s1600/Selection_011.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAlrkk5HY-8rgf3FzqcxiaOUO5xXJ1PqXkZdbaqbmdCnJVaGtt1AchUOaeNKVct8xFPjEPw1npH_LW4nM8WArhJrXHUbF1sPt0MMTVgdU04l2qwXDbE34XIYpNZiUTl9FVMIh5Ow/s1600/Selection_011.png" /></a></div>
<br />
<br />
There's <a href="https://play.google.com/store/apps/details?id=com.rtsapps.shavingbuddy">another app on the Play store called "Shaving Buddy"</a> that does something similar actually.
However it has a lot more features than I needed, with photos and databases of gear and all sorts of bells and whistles.
If you prefer that approach, maybe check that app out too.<br />
<br />
Creating this app has made me realise just how much effort writing a proper Android app requires.
Compared to a game, I mean, which has its own strengths and weaknesses.
The tools and the libraries in the Android world have a lot of churn.
Google is notorious for throwing new libraries out and then abandoning the old working ones for these new-but-incomplete versions.
All the ancient documentation that's out there on blogs and tutorials causes confusion.<br />
<br />
Backwards-compatibility cruft is starting to accumulate too,
such as the official <code>android</code> command-line tool that still only creates projects for the old deprecated apache-ant-based build system.
It's a miracle anyone writes apps actually. The time required to do anything useful, let alone fancy, is overwhelming.
Even once it is done, I go back to code and struggle to remember what it all oes
(ContentObservers, ContentResolvers, Fragments, Cursors, Loaders, Adapters… argh!).
Maybe I just suck at this.<br />
<br />
According to <a href="http://www.kinvey.com/blog/2086/how-long-does-it-take-to-build-a-mobile-app">these guys, it takes 18 weeks to write an Android app</a>.
That includes server-side logic, "monetization strategies", and other complicated stuff I don't do.
In my defence, I wrote this app at night and on weekends between bouts of Monster Hunter 3 Ultimate with my son.
I didn't see any mention of <a href="https://youtu.be/6DlO1v5NhiM?t=235"><em>Defeating Brachydios</em></a> on that infographic.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqjTrYWLDgJfzty8qCKpdBMPYAFLSdzo7vgJXC2AAyMATD-S9k_kiGlH6bMWrYjaRlYTngbxlaAPHVC8GhpEQlPJ1mr0d5ta-tdC-QU7_9lcLAzVnug7A9jsMrkrqB_JsOxdwLUQ/s1600/brachydios.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqjTrYWLDgJfzty8qCKpdBMPYAFLSdzo7vgJXC2AAyMATD-S9k_kiGlH6bMWrYjaRlYTngbxlaAPHVC8GhpEQlPJ1mr0d5ta-tdC-QU7_9lcLAzVnug7A9jsMrkrqB_JsOxdwLUQ/s320/brachydios.jpeg" width="320" /></a></div>
<br />
<br />
Luckily we have a bunch of static analysis tools for Java to help prevent common mistakes,
and the Android lint tool helps you avoid incorrect use of the dodgier parts of the Android API.
In general writing an app "only" requires bolting together different libraries and functions until it does what you want.
When I found myself having to write too much code it either meant I was doing it wrong, or I just shouldn't be doing it at all.
The downside to this is that whatever you write today, the next platform version could make obsolete or incompatible tomorrow.<br />
<br />
Speaking of obsolete, maintaining backwards compatibility with the old 2.x or 3.x versions of Android seems pretty pointless nowadays.
About 85% of the people with Android devices have them running 4.0 and up, and this percentage will only continue to grow.
For my old 8-bit remakes I've kept backwards compatibility because when I started, Android Donut (aka 1.6) was still cutting edge.
The native C code APIs in Android have not changed at all in the last 5-6 years.
The lesson here is to write everything in C, it is future proof! :)<br />
<br />
Initially I planned to not use the support libraries, but this meant not taking advantage of back-ported functions from the Lollipop release.
I also worry that by sticking with the older code style - ActionBar and pals - the code will become stale once 5.x starts to get a foothold.<br />
<br />
A feature I have considered adding to the app was an online backup of some kind.
Right now I've included a simple backup option where you can export a CSV file of the data to
email to yourself or store on some remote storage service.
Aftewards you can re-import that file if you lose the data or want to update the entries on a new device.
This doesn't require permissions of any sort since it uses Android Intents.
It'd be better to use Google Drive, Dropbox or Owncloud, but this would all require more work as well as requiring the internet privilege,
so I've avoided doing that for now.<br />
<br />
Here's that <a href="https://play.google.com/store/apps/details?id=es.quirk.bladereminder">link to the app on the play store</a> again, try it out and rate it.
The <a href="https://github.com/richq/bladereminder">code is also on github</a>, so get those pull requests rolling in.</div>
Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com0tag:blogger.com,1999:blog-9675303.post-44466368415103732932015-05-31T14:42:00.000+02:002015-05-31T14:42:58.407+02:00Fixing bugs with GCC's -fsanitize<div dir="ltr" style="text-align: left;" trbidi="on">
New versions of gcc have <a href="http://developerblog.redhat.com/2014/10/16/gcc-undefined-behavior-sanitizer-ubsan/">added several options to check for undefined behaviour</a>, out-of-bounds behaviour, and other run-time bugs in a program.<br />
<br />
To use address sanitizer, you have to compile and link your code with the <code>-fsanitize=address</code> option.
Then run your program as normal. If there are any buggy bits, then the compiler-inserted runtime checks will throw a wobbly.<br />
<br />
Using the CMake build system I add the flag like this:<br />
<pre><code class="prettyprint">
</code></pre>
<pre><code class="prettyprint">include(CheckCCompilerFlag)
set(flag fsanitize=address)
set(CMAKE_REQUIRED_FLAGS -${flag})
check_c_compiler_flag(-${flag} ${flag}_is_ok)
if(${flag}_is_ok)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -${flag}")
endif()
</code></pre>
<br />
I had to set <code>CMAKE_REQUIRED_FLAGS</code> as otherwise the <code>check_c_compiler_flag</code> macro just uses <code>-fsanitize</code> on the compile stage,
skips it on the link stage, and the check subsequently fails with an undefined reference:<br />
<pre><code class="prettyprint">
</code></pre>
<pre><code class="prettyprint">CMakeFiles/cmTryCompileExec3487553727.dir/src.c.o: In function `_GLOBAL__sub_I_00099_0_main':
src.c:(.text+0x10): undefined reference to `__asan_init_v4'
collect2: error: ld returned 1 exit status
</code></pre>
<br />
Anyway… for an out-of-bounds read, a crash looked like this (I compiled in Debug to get line information):<br />
<pre><code class="prettyprint">
</code></pre>
<pre><code class="prettyprint">=================================================================
==16223==ERROR: AddressSanitizer: global-buffer-overflow on address 0x0000004833bc at pc 0x000000412a7a bp 0x7ffe5fb416e0 sp 0x7ffe5fb416d0
READ of size 2 at 0x0000004833bc thread T0
#0 0x412a79 in load_bg_palette chaos/gfx.c:306
#1 0x412824 in load_all_palettes chaos/gfx.c:292
#2 0x415d8d in load_bg chaos/main.c:23
#3 0x415e4c in chaos_main chaos/main.c:37
#4 0x407758 in main port/linux/main.c:52
#5 0x7f6c1551778f in __libc_start_main (/usr/lib/libc.so.6+0x2078f)
#6 0x406e08 in _start (build/linux-cmake/port/linux/chaos+0x406e08)
0x0000004833bc is located 0 bytes to the right of global variable 'palette1Pal' defined in 'gfx/palette1/palette1.c:16:22' (0x4833a0) of size 28
SUMMARY: AddressSanitizer: global-buffer-overflow chaos/gfx.c:306 load_bg_palette
Shadow bytes around the buggy address:
0x000080088620: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x000080088630: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x000080088640: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x000080088650: 00 00 00 00 00 00 00 00 f9 f9 f9 f9 00 00 00 00
0x000080088660: 00 00 00 00 00 f9 f9 f9 f9 f9 f9 f9 00 00 00 00
⇾0x000080088670: 00 00 00 00 00 00 00[04]f9 f9 f9 f9 00 00 00 00
0x000080088680: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x000080088690: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000800886a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0000800886b0: f9 f9 f9 f9 00 00 00 00 00 f9 f9 f9 f9 f9 f9 f9
0x0000800886c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Heap right redzone: fb
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
==16223==ABORTING
</code></pre>
<pre><code class="prettyprint">
</code></pre>
Chaos has run "valgrind clean" for a while, which means that there should be no out-of-bounds writes.
The nice thing about address sanitizer is that it seems to find extra problematic areas over valgrind, and the runtime overhead is less.
I've noticed that buggy code that does out-of-bounds reads on an x86 machine tends to work fine,
but when you do the same on Android running on an ARM processor it crashes right away.<br />
<br />
Hopefully armed with this new tool I'll be able to fix more bugs :-D<br />
<br /></div>
Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com0tag:blogger.com,1999:blog-9675303.post-9413006985163373822015-05-26T21:32:00.002+02:002015-05-26T21:32:51.637+02:00Chaos update notes<div dir="ltr" style="text-align: left;" trbidi="on">
A few weeks ago I released a new version of Chaos that had what looked to be some pretty bad bugs.
In fact the bug was <em>just</em> that the controls were enabled when the CPU is moving or casting,
but you could really mess things up by tapping the screen during their turns.<br />
<br />
This bug came about because I'd switched over to the latest <a href="https://github.com/kripken/emscripten">emscripten</a> build for the Javascript version.<br />
<br />
As you may recall, <a href="http://blog.quirk.es/2014/02/porting-my-chaos-remake-to-web.html">I had to make some changes to the code structure of Chaos</a> to avoid busy-loops deep in the guts of the game.
Emscripten previously required you to have just one "main loop". Since then, Emscripten has gone completely insane - in a good way.
The latest emscripten releases <a href="https://github.com/kripken/emscripten/wiki/Emterpreter">have a way to compile C code down to an emscripten-specific byte-code</a>, that is then run on an interpreter, which itself runs in the Javascript interpreter in the browser!<br />
<br />
What this marvellous change means is that the one-main-loop restriction is lifted.
You get better performance if you write code to use the preferred way,
but the interpreter-byte-code solution lets you keep the old semantics going if you don't mind taking the performance hit. Hurray!
So I reverted Chaos back to how it was in release 1.18 more or less.
That means no more co-routines to get around the loop restriction, and the code is easier to read and understand.<br />
<br />
As a side effect, I added the previously-mentioned game destroying bug by enabling controls in the "wait" code that was called everywhere.
The fix was easy - just remove the control polling/updates in the wait. But it broke the game for a lot of people :(
To try and prevent this from happening again, I've <a href="https://plus.google.com/communities/117026447232019845124">created a beta group on Google+</a> and I'll push updates here before making them live to everyone.<br />
<br />
I currently have 1 bug on my list - fix the glitched screen that happens after you minimize the game and return to the homescreen, then go back to the game.
I'm doing something wrong in the Android lifecycle and the GL screen is not reset correctly.<br />
<br /></div>
Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com0tag:blogger.com,1999:blog-9675303.post-15304408552836705472014-09-20T17:02:00.001+02:002014-09-20T17:02:04.344+02:00Running Android apps in Chrome is great for developers<div dir="ltr" style="text-align: left;" trbidi="on">
This week <a href="https://twitter.com/vladikoff">@vladikoff</a> released a tool that builds on Google's own Android-apps-on-ChromeOS work to allow anyone to run Android applications in Chrome on Linux!
I've tried it out on Xubuntu 14.04 and it works quite well.
With a few tweaks this is a better way to test applications than the slow Android emulator.<br />
<br />
Unfortunately this doesn't work in Chromium - currently version "37.0.2062.94 Ubuntu 14.04 (290621) (64-bit)" - but did work in the latest Chrome for Linux (Version 37.0.2062.120 (64-bit)).<br />
<br />
After installing Chrome from the official Google download site, here is how I installed ARChon:<br />
<br />
<pre><code class="prettyprint">sudo apt-get install npm nodejs-legacy
sudo npm install chromeos-apk -g
wget https://bitbucket.org/vladikoff/archon/get/v1.0.zip
unzip v1.0.zip
</code></pre>
Then load the unpacked extension as shown on <a href="https://github.com/vladikoff/chromeos-apk/blob/master/archon.md">the archon page</a>.<br />
<br />
While most news has been about running Flappy Birds or whatever other app (try <a href="https://play.google.com/store/apps/details?id=com.watabou.pixeldungeon">Pixel Dungeon</a>),
as a developer I was interested in debugging my own Android apps. To do this I needed to install these apps first.<br />
<br />
It's actually pretty easy to install an APK - first create a manifest and the extension structure. For <a href="https://play.google.com/store/apps/details?id=chaos.app">Chaos</a> I do this:<br />
<br />
<pre><code class="prettyprint">chromeos-apk -a ~/projects/chaos-portable-build/android/port/android/bin/chaos-debug.apk
</code></pre>
Then from within Chrome, load the unpacked "extension" (ie. the Android app/game) the same way as the main archon runtime. It'll appear on the <code>chrome://extensions</code> page.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOx903kCFWnXZ5GFRiE3B1SgdmSd4tXKeSNEb8m9HuuQnnrkCxNlXsKFvd6SpQdmSX-FzPpAkuT44TvyELt3yMryHbF-lHIG0x2yAX8iufPKPGPts8k_1Zcco8ZIue2lorgXbMpw/s1600/extension.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOx903kCFWnXZ5GFRiE3B1SgdmSd4tXKeSNEb8m9HuuQnnrkCxNlXsKFvd6SpQdmSX-FzPpAkuT44TvyELt3yMryHbF-lHIG0x2yAX8iufPKPGPts8k_1Zcco8ZIue2lorgXbMpw/s1600/extension.png" height="82" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">App as a extension in Chrome</td></tr>
</tbody></table>
Running your own APK may work.. or maybe it has a few problems. In order to debug things you should add <code>enableAdb</code> in the manifest.json file, in the arc_metadata section:<br />
<br />
<pre><code class="prettyprint">"enableAdb": true,
</code></pre>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZUvpYgYpZYJO3BkjVQDC9xjMWX09qg0EtleRsIuLYO3T0Ng-rUxiA6_NAMenfsUAGDOe7g2fFAe_Pasr6d9lDP3BDkweCiW7NrGYdXjJdhvJ8N6pHg1U2fideymVuMz4puVBEgw/s1600/enable_adb.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZUvpYgYpZYJO3BkjVQDC9xjMWX09qg0EtleRsIuLYO3T0Ng-rUxiA6_NAMenfsUAGDOe7g2fFAe_Pasr6d9lDP3BDkweCiW7NrGYdXjJdhvJ8N6pHg1U2fideymVuMz4puVBEgw/s1600/enable_adb.png" height="227" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">enable adb in manifest.json</td></tr>
</tbody></table>
After clicking Reload on the extensions page you can run <code>adb logcat</code> and see the output of your app. This may help you find out why it crashes so much. Heh.<br />
<br />
Some things I've found are that NDK works if you compile for x86, but the GLES emulation has a few niggles.
For example GL_EXTENSIONS reports that the runtime supports <code>GL_OES_draw_texture</code> but when I used <code>glDrawTexiOES</code> it crashed.
Also I disabled some GL capabilities that the game doesn't use, but as the runtime doesn't support these capabilities it also crashed.<br />
<br />
Finally, in another app I'm making, I noticed that sharing has a few buglets.
On a regular Android device you can request information about an intent to share data like this:<br />
<br />
<pre><code class="prettyprint">Intent shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.setType("text/plain");
ResolveInfo info = getApplicationContext().getPackageManager().resolveActivity(shareIntent, 0);
</code></pre>
When no application to share with is available for "text/plain" then it returns null. On ARC it returns an object, but the <code>info.resolvePackageName</code> is null.
There are probably a load of small interoperability bugs like this, which is why this wasn't officially released by Google yet.<br />
<br />
Either way, this is a great way to test out Android apps if you don't have a phone handy. It's much better than the emulator, finally approaching the simulator approach that everyone has been clamouring for. Get it now before the lawyers at Google send Github a DMCA takedown notice ;-)<br />
<br />
<br /></div>
Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com0tag:blogger.com,1999:blog-9675303.post-27187268601026594762014-09-10T11:57:00.001+02:002014-09-10T11:58:09.557+02:00Toggle Javascript Enabled in Firefox for Android<div dir="ltr" style="text-align: left;" trbidi="on">
<a href="https://addons.mozilla.org/en-US/android/addon/toggle-javascript-enabled">The add-on for Firefox that I mentioned last time</a> is finally available on the Mozilla add-ons site.
This adds a enable/disable JavaScript toggle option to the Tools menu on Firefox for Android.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimIlq_mUa_ycspZXV5iwbgNq0sVPtCxPMOgZmc-3jzhFMmFWQ4Hzp6nCMPfgGRx3vUtKUvyUDdbZndCXRIQ9hqqHF2xayLOupFHZ1IsTES286XXrIl7qlMKy6XADX6hw_GNqRmdA/s1600/screenshot-clipped.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Screenshot of JavaScript toggle in the Tools menu" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimIlq_mUa_ycspZXV5iwbgNq0sVPtCxPMOgZmc-3jzhFMmFWQ4Hzp6nCMPfgGRx3vUtKUvyUDdbZndCXRIQ9hqqHF2xayLOupFHZ1IsTES286XXrIl7qlMKy6XADX6hw_GNqRmdA/s1600/screenshot-clipped.png" height="315" title="JavaScript toggle in the Tools menu" width="320" /></a></div>
<br />
<br />
The code is <a href="https://github.com/richq/toggle-js-addon">on github</a>
if you want to see how to make a simple Firefox Add-on.
It took me longer than it should have to write this, as I had trouble finding documentation on the
technique to read/write a global preference.
The code (in JavaScript, ironically enough) is about 120 lines. Only
30 of those are really the meat of the add-on.<br />
<br />
Comments and ratings would be helpful. I use this add-on every day to save on bandwidth and battery.
The one feature I may add is to have the page reload when you enable JavaScript again, but even that might be too much feature-creep.</div>
Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com0tag:blogger.com,1999:blog-9675303.post-64838694913716693582014-08-30T10:27:00.000+02:002014-08-30T10:27:16.534+02:00Summer 2014 Roundup<div dir="ltr" style="text-align: left;" trbidi="on">
Crikey, I've not posted here for a while.<br />
<br />
Since the <a href="http://blog.quirk.es/2014/02/porting-my-chaos-remake-to-web.html">last post 6 months ago</a> here's what I've been up to, in no particular order:<br />
<ul>
<li>Several releases of <a href="https://play.google.com/store/apps/details?id=chaos.app">Chaos</a> to fix a slew of bugs (<a href="https://sites.google.com/site/chaosbattleofwizards/">other versions</a>)</li>
<li>A couple of releases of <a href="https://play.google.com/store/apps/details?id=war.of.the.solstice">Lords of Midnight 8-bit version</a> to remove an Android permission</li>
<li>A new release of the <a href="https://github.com/richq/android-ndk-profiler">Android NDK Profiler</a> with contributions from Sjoerd Meijer to fix some major bugs and add executable support</li>
<li>Patches for <a href="https://github.com/richq/folders2flickr/">folders2flickr</a>, which is a handy command line tool to backup photos to flickr</li>
<li>Updates to my <a href="https://addons.mozilla.org/en-US/thunderbird/addon/smiley-fixer/">Thunderbird "Smiley Fixer" plugin</a> for a new type of mess-up I came across in Outlook-generated emails.</li>
</ul>
Apart from that, I have recently become a member of the flock of sheeple using a smartphone/NSA-tracking-device
after I purchased a <a href="http://www.gsmarena.com/motorola_moto_g_4g-6355.php">Moto G 4G</a>
and hooked it up to a massive 100Mb (count 'em) per month data plan.
I checked the previous few months' usage on my 2005-era Nokia phone and
it was costing me about 1€ per month in SMS messages, and I only sent 3.<br />
<br />
For the same price (1€ per month) I got a pre-paid data plan on <a href="http://www.simyo.es/">Simyo</a> here in Spain,
and with internet-based messaging apps I can send all the messages I wanted at no additional cost.
I had to pay about 10€ up front for a new micro SIM, but it came with 10€ of pre-paidness anyway.
The only bummer is that I could have achieved the same 100Mb deal for free from our ISP,
but they only give out a 2nd mobile line to new customers.
Apparently if you're an old-time customer and threaten to cancel they'll give you the 2nd line,
but I'm worried they'll call my bluff!<br />
<br />
The reason I mention all this is that having now used an Android device as a phone daily,
rather than just having it at home in WiFi-only mode (I'm looking at you HTC Magic and your 4-hour battery life),
has made me think of a couple of things that I could code up.<br />
<br />
The first is a native Android application,
a boring one with nothing to do with games.
There are enough games on Android already, right?
The second thing is a <a href="https://github.com/richq/toggle-js-addon">tiny Firefox-for-Android addon</a> to disable Javascript,
which I think should have been in this mobile Firefox by default anyway.
The former needs a bit of polishing still, while the latter is in the queue at Mozilla Towers awaiting review.
</div>
Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com0tag:blogger.com,1999:blog-9675303.post-11668050449505064202014-02-16T23:10:00.002+01:002014-02-16T23:10:39.383+01:00Porting my Chaos remake to the web<div dir="ltr" style="text-align: left;" trbidi="on">
Today I've uploaded a new version of Chaos to the Android Play store, updated the <a href="https://sites.google.com/site/chaosbattleofwizards/download">Game Boy Advance and Nintendo ports</a>
and also managed to make <a href="http://quirk.es/chaos/chaos.html">Chaos run in your browser</a>. Here's a bit of waffle on how I went about that last part.<br />
<br />
Over the years the remake I made of the ZX Spectrum classic <a href="http://www.worldofspectrum.org/infoseekid.cgi?id=0000894">Chaos</a> has undergone about 3 rewrites.<br />
<ul>
<li>the first version I wrote for the Game Boy Advance from scratch. The Speccy version was inspiration, but it wasn't an accurate remake.</li>
<li>the next version was a lot closer to the original, created by carefully reading through the Z80 code to get all the gameplay spot on</li>
<li>I rewrote the game for the Nintendo DS as an independent code base in C++, which also compiled against the SDL library so I could test on a PC</li>
<li>for the Android port I went back to the 2nd version's C code, making sure that this time the same codebase compiled for the GBA, DS, SDL and Android NDK without tons of <code>#ifdef</code> statements</li>
</ul>
All this means that the code is portable, or at least it has had its most unportable edges smushed off,
currently compiling and running on 4 different platforms (GBA, DS, Android, SDL).
It uses GNU autotools as the build system. This is not pleasant, but autotools has more working features than any other build system,
and it makes it possible to cross-compile the code.<br />
<br />
For the last year or two I've been keeping an eye on the <a href="http://www.emscripten.org/">emscripten</a> project too.
Emscripten uses the <a href="http://clang.llvm.org/">Clang</a> compiler to compile C or C++ code to JavaScript. This can then run in any modern web browser.
I thought that it would be fun to get Chaos cross-compiled to JavaScript.<br />
<br />
Emscripten even has some SDL support for graphics and sound.
This it achieves by cleverly translating SDL function calls to the equivalent HTML5 canvas calls and wrapping the web audio API.
I assumed this all meant it would be easy to get the job done.
Sadly my lack of game design chops meant it was a lot more work than I initially expected.<br />
<br />
Let's see how I made my life difficult.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgT2CqEsEwYu4rzf880fDZZIkBR037tAGolLEgqXOak8STBgOqZlhXMy1-q4Zvz9iFk54EW3O6oi9-rIwvO5HNKLoLUp95-u3iA6revas0-uwBAuonklzUyd0TVUChc3htqXF2moQ/s1600/do-nothing.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgT2CqEsEwYu4rzf880fDZZIkBR037tAGolLEgqXOak8STBgOqZlhXMy1-q4Zvz9iFk54EW3O6oi9-rIwvO5HNKLoLUp95-u3iA6revas0-uwBAuonklzUyd0TVUChc3htqXF2moQ/s1600/do-nothing.png" height="148" width="320" /></a></div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
On the GBA you have complete control over the hardware your program is running on.
As only one program can run at a time, and the GBA has no operating system to keep track of things, you can use 100% of the CPU.
In fact if you aren't careful you can waste the battery by "spin-waiting" when you need to wait for input from the user or when your game isn't doing much.
Spin-waiting means code that just loops on the same instructions over and over until a condition changes.
It is easy to understand, but inefficient as it still executes instructions.<br />
<br />
<br />
<br />
The GBA has a way to say "OK, I'm not doing anything for a while, please turn off the processor and wait for the next video frame to tick by".
In this special low-power waiting mode the GBA uses less battery, so using this technique is a good idea.<br />
<br />
On the GBA I had full control for Chaos, and I had to add these waits in when the game wasn't doing much or was waiting for user input.
I wrote code that stopped wherever it was to hang around and wait for the next thing to do.<br />
<br />
Now back to game design. A classic game loop has 3 jobs - running the game logic, drawing the graphics and going neither too fast nor too slow.<br />
<br />
<pre style="background-color: black; color: white; font-weight: bold;"><span style="font-family: monospace;"><span style="color: yellow;"><b>while</b></span> (<span style="color: #ff40ff;"><b>true</b></span>) {
do_stuff();
render_screen();
wait_a_bit();
}</span></pre>
<br />
Things can get complicated - <em>wait_a_bit</em> in particular goes off the deep end when <em>do_stuff</em> contains complex physics models -
but that's the basic idea, and for Chaos it would be more than enough.
What turned out to be the problem with my code was that as well as the main loop, which was similar to the above snippet,
I also had lots of mini-game-loops scattered throughout the code.<br />
<br />
Imagine what happens when you want to move a wizard off a horse or centaur.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgLv-lUFmQGyWdPLCKeqfHFFLXWApO2FtHsy7AioslkYriw1cuppOyyeJEP2V5l8TTo5QIm5YtNpspERjRRatSGDKFyFIZ2bXzZExma5p9LSa3KTa9EhP4akqKPBpr9ANzKwj99g/s1600/centaur.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgLv-lUFmQGyWdPLCKeqfHFFLXWApO2FtHsy7AioslkYriw1cuppOyyeJEP2V5l8TTo5QIm5YtNpspERjRRatSGDKFyFIZ2bXzZExma5p9LSa3KTa9EhP4akqKPBpr9ANzKwj99g/s1600/centaur.png" /></a></div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi39dv_hI-l5oR2xeQa_f62B9MLM2_nfc6z1h0T5EU-W_GTaLWalMDzxAfVIMdyTyblGifmmT6sKJ9hsZRdbhC0nuuUkK6diH8Bp6uY9FpIFEHO3_4PyUDekN3vvzrL0tE6C3rxlg/s1600/dismount.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi39dv_hI-l5oR2xeQa_f62B9MLM2_nfc6z1h0T5EU-W_GTaLWalMDzxAfVIMdyTyblGifmmT6sKJ9hsZRdbhC0nuuUkK6diH8Bp6uY9FpIFEHO3_4PyUDekN3vvzrL0tE6C3rxlg/s1600/dismount.png" /></a><br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<br />
In Chaos the game stops to ask you if you want to dismount.
This stopping-to-ask was another game loop stuck right in the middle of the code for selecting a creature to move.
On the GBA, DS, SDL, and Android ports this wasn't much of a problem.
On the GBA and DS I have full control of what's going on.
For the Android/SDL ports I use threads, mutexes and signals to coordinate things,
essentially emulating the way the GBA behaves anyway.<br />
<br />
When it came to a JavaScript port this just didn't cut it.
JavaScript <em>requires</em> that the browser controls the "wait a bit" part of the game loop, and it has no C-style threads with shared state.
When you compile C code with emscripten, instead of the <code>while</code> loop posted above you need something more like this:<br />
<br />
<pre style="background-color: black; color: white; font-weight: bold;"><span style="font-family: monospace;"><span style="color: lime;"><b>void</b></span> one_frame(<span style="color: lime;"><b>void</b></span>)
{
do_stuff();
render_screen();
}
<span style="color: lime;"><b>int</b></span> main(<span style="color: lime;"><b>void</b></span>)
{
emscripten_set_main_loop(one_frame, <span style="color: #ff40ff;"><b>0</b></span>, <span style="color: #ff40ff;"><b>0</b></span>);
}</span></pre>
<br />
Here <code>emscripten_set_main_loop</code> makes sure it calls your <code>one_frame</code> function once for each game loop at the rate you ask it.
The rate here is 0, 0 - which possibly means "whenever you like".<br />
<br />
When the game is deep in the "do stuff" part of the main loop, and it needs to do the "wait for a bit" thing…
well, in JavaScript you can't do that.
The code would have to return all the way back to the main loop, pass control back to the browser,
then carry on where it was when the browser returns control.<br />
<br />
Being a lazy sod, I didn't want to have to rewrite <em>everything</em>.
In fact, at first I couldn't see how I could rewrite anything to make the game work with in this environment.<br />
<br />
Then I thought about that previous phrase -
<strong>the code would have to return all the way back to the main loop … then carry on where it was when the browser returns control</strong> -
and I realised that what I needed here were <a href="https://en.wikipedia.org/wiki/Coroutine">coroutines</a>.<br />
<br />
What a coroutine lets you do is yield control from the middle of a function,
but when the program calls the function again instead of starting from the start of the function, it continues on from where it yielded last time.
A language such as Lua has this built in with the <code>yield</code> keyword, making it trivial to do.
In C, everyone who needs coroutines uses <a href="http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html">Simon Tatham's coroutine macros</a>.<br />
<br />
I still had to come up with a way to call any routine that needed to wait again, and it still needed a bunch of changes.
But the basics were there, and I wouldn't need to rewrite everything all at once.<br />
I came up with fake <em>asynchronous</em> functions - these were not really asynchronous,
but the code adds each function to a list that the program would later call one by one from the main loop when this loop was ready.
If the function returns 1 it means that the main loop needs to call the function again, but if it returns 0 then the function has finished and the program should take this function off the list of pending items.<br />
<br />
Coupling this with the coroutines meant I could have fake thread-like behaviour on a single main loop.
I had to be a bit careful since, as with regular threads, the code could have "race conditions".
If the code changed a variable after adding an asynchronous function to the pending queue, but before the main loop calls the function,
then it might not do what I expected.
But at least the race conditions were deterministic here, unlike regular threads which can have subtle timing problems.<br />
<br />
<a href="https://www.blogger.com/blogger.g?blogID=9675303" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a><a href="https://www.blogger.com/blogger.g?blogID=9675303" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a>Another change I had to make was to switch from using SDL sound mixed in a buffer using the older API, to use the SDL_mixer library.
This cut down on code, so for that alone it was a good idea, and made sound effects in the browser work without further changes!
The sounds are OGG files, converted from the WAV file originals.
I didn't need to change the build system much for this as I was already generating OGG files for the Android version.<br />
<br />
The emscripten C compiler/linker has a flag <code>--preload-file</code> that creates the equivalent of a virtual drive with the contents of a directory.
I have emscripten generate chaos.js, and using <code>--preload-file sfx/</code> for the sfx directory creates a chaos.data file with all the generated OGG files encrusted in it.
From there, using the bog standard SDL mixer API just works. Incredible.<br />
<br />
Saving and loading was a little bit trickier.
I wanted the game to save and load its options and game state using native JavaScript calls to <a href="https://developer.mozilla.org/en/DOM/Storage">DOM Storage</a>. The <a href="https://github.com/kripken/emscripten/wiki/Interacting-with-code">emscripten wiki</a> shows a simple example of how to call a pointless <code>my_js</code> function from C code. This example doesn't accept arguments or return values, but it was a start.<br />
<br />
I wanted functions in C that had the following prototypes:<br />
<br />
<pre style="background-color: black; color: white; font-weight: bold;"><span style="font-family: monospace;"><span style="color: lime;"><b>void</b></span> js_save(<span style="color: lime;"><b>const</b></span> <span style="color: lime;"><b>char</b></span> *key, <span style="color: lime;"><b>const</b></span> <span style="color: lime;"><b>char</b></span> *data);
<span style="color: lime;"><b>char</b></span> *js_load(<span style="color: lime;"><b>const</b></span> <span style="color: lime;"><b>char</b></span> *key);</span></pre>
<br />
And in JavaScript would use the localStorate API in the following way:<br />
<br />
<pre style="background-color: black; color: white; font-weight: bold;"><span style="font-family: monospace;">js_save = <span style="color: cyan;"><b>function</b></span>(key, data) <span style="color: cyan;"><b>{</b></span> <span style="color: yellow;"><b>window</b></span>.localStorage.setItem(key, data); <span style="color: cyan;"><b>}</b></span>
js_load = <span style="color: cyan;"><b>function</b></span>(key) <span style="color: cyan;"><b>{</b></span> <span style="color: yellow;"><b>return</b></span> <span style="color: yellow;"><b>window</b></span>.localStorage.getItem(key); <span style="color: cyan;"><b>}</b></span></span></pre>
<br />
Simply declaring those C prototypes meant I could call out to JavaScript from C. I still had to declare the JS code somewhere.
The pieces to do that are "emscripten libraries" and the <code>--js-library</code> compiler switch. After digging into the test suite, I came up with this first go:<br />
<br />
<pre style="background-color: black; color: white; font-weight: bold;"><span style="font-family: monospace;">mergeInto(LibraryManager.library, <span style="color: cyan;"><b>{</b></span>
js_save: <span style="color: cyan;"><b>function</b></span>(key, data) <span style="color: cyan;"><b>{</b></span>
<span style="color: yellow;"><b>window</b></span>.localStorage.setItem(key, data);
<span style="color: cyan;"><b>}</b></span>
js_load: <span style="color: cyan;"><b>function</b></span>(key) <span style="color: cyan;"><b>{</b></span>
<span style="color: yellow;"><b>return</b></span> <span style="color: yellow;"><b>window</b></span>.localStorage.getItem(key);
<span style="color: cyan;"><b>}</b></span>
<span style="color: cyan;"><b>}</b></span>);</span></pre>
<br />
I placed that in a file <code>library.js</code> and added it to the emcc line to create the final JavaScript: <code>emcc -o chaos.js --js-library library.js</code>.<br />
<br />
Unfortunately - and I probably should have expected this - the <code>char *key</code> and <code>char *data</code> arguments that arrive at those JavaScript functions from the C-side are not JavaScript-strings.
They are JavaScript numbers, indices (or "pointers") into the array of data that emscripten uses for memory declared in the land of C.
To get a JavaScript string from the pointer, I used the aptly-named emscripten function <code>Pointer_stringify</code>.
Similarly, to return a JavaScript string back into a C function you need to convert it into a pointer. The way to do this seems to be using <code>allocate</code> together with <code>intArrayFromString</code>.
After reading emscripten's built-in SDL library wrapper, I came up with this final save/load code:<br />
<br />
<pre style="background-color: black; color: white; font-weight: bold;"><span style="font-family: monospace;">mergeInto(LibraryManager.library, <span style="color: cyan;"><b>{</b></span>
js_save: <span style="color: cyan;"><b>function</b></span>(key_, data_) <span style="color: cyan;"><b>{</b></span>
<span style="color: cyan;"><b>var</b></span> key = Pointer_stringify(key_);
<span style="color: cyan;"><b>var</b></span> data = Pointer_stringify(data_);
<span style="color: yellow;"><b>window</b></span>.localStorage.setItem(key, data);
<span style="color: cyan;"><b>}</b></span>,
js_load: <span style="color: cyan;"><b>function</b></span>(key_) <span style="color: cyan;"><b>{</b></span>
<span style="color: cyan;"><b>var</b></span> key = Pointer_stringify(key_);
<span style="color: cyan;"><b>var</b></span> result_ = <span style="color: yellow;"><b>window</b></span>.localStorage.getItem(key);
<span style="color: cyan;"><b>var</b></span> result = allocate(intArrayFromString(result_), <span style="color: #ff40ff;"><b>'i8'</b></span>, ALLOC_NORMAL);
<span style="color: yellow;"><b>return</b></span> result;
<span style="color: cyan;"><b>}</b></span>,
<span style="color: cyan;"><b>}</b></span>);</span></pre>
<br />
During the porting, one of the issues I had was fading-out the screen.
Fading out to black is a classic effect that a lot of old 16-bit games used.
While the screen is in its faded out state you can set up the layout without having half-drawn graphics show up.
On the GBA, there are hardware registers to fade between layers and this is fast and efficient.
With the SDL version I did a brute-force palette change that required updating all the pixels on the screen for each level of fading.
While it worked OK in the native build, it turned out to be annoyingly slow when compiled to JavaScript.
The fade effect would take around 5 seconds to complete, instead of less than a quarter of a second.
I changed to use SDL_SetAlpha to alpha-blend a black rectangle over the current screen.
This worked well in the native SDL build, but did not do anything in the JavaScript SDL canvas.<br />
<br />
After a bit of searching and grepping, I figured out how to <a href="https://www.blogger.com/pullrqst">add this feature in</a>, since the SDL library in emscripten almost had it right.
With that SDL_SetAlpha worked and didn't slow the fading transition down to a crawl.
The maintainers have since merged this change into the stable version of emscripten too. Karma++.<br />
<br />
So here it is: <a href="http://quirk.es/chaos/chaos.html">Chaos in your browser</a> :-)<br />
<br />
The same code compiles and runs more-or-less identically on the GBA, Nintendo DS, Android, SDL, and now (thanks to emscripten) in the browser.<br />
<br />
<a href="https://www.blogger.com/blogger.g?blogID=9675303" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a><a href="https://www.blogger.com/blogger.g?blogID=9675303" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a>I've tested this in Firefox 24+ and Chromium ~32 on Ubuntu and Debian.
It also runs on Firefox and Chrome for Android, though Chrome does not play the sound effects for some reason.
It surprised me to see that the game seems to run slightly smoother on Chrome compared to Firefox, despite the advantages of <a href="http://asmjs.org/">asm.js</a>.
I think that this must be due to the HTML5 canvas methods performing better on Chrome/ium, as there's not a lot of CPU intensive stuff going on here.<br />
<br />
New features in this release compared to the last are a Spanish translation (a family effort with my son helping out), a better random spell selection by using the more balanced "shuffle bag" approach, and a cleverer AI that can go around obstacles.
The last 2 ideas were inspired by a comment on the Play store.
It was very annoying to get 3 Magic Swords in one game, and to see creatures fail to traverse a wall or span of gooey blob.
A shuffle bag means that spells are not as totally random - each has a weighting of how often it will appear now so there is more balance,
and certain spells cannot appear more than once.
The AI now uses that old standby A*. Despite play testing this for a while now, I expect a flurry of bug reports and another release next week ;-)</div>
<!-- Blogger automated replacement: "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi39dv_hI-l5oR2xeQa_f62B9MLM2_nfc6z1h0T5EU-W_GTaLWalMDzxAfVIMdyTyblGifmmT6sKJ9hsZRdbhC0nuuUkK6diH8Bp6uY9FpIFEHO3_4PyUDekN3vvzrL0tE6C3rxlg/s1600/dismount.png" with "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi39dv_hI-l5oR2xeQa_f62B9MLM2_nfc6z1h0T5EU-W_GTaLWalMDzxAfVIMdyTyblGifmmT6sKJ9hsZRdbhC0nuuUkK6diH8Bp6uY9FpIFEHO3_4PyUDekN3vvzrL0tE6C3rxlg/s1600/dismount.png" --><!-- Blogger automated replacement: "https://images-blogger-opensocial.googleusercontent.com/gadgets/proxy?url=http%3A%2F%2F2.bp.blogspot.com%2F-21WlRzXRujk%2FUwE2GBW3fGI%2FAAAAAAAABg8%2F4-2r2TX4DyY%2Fs1600%2Fdismount.png&container=blogger&gadget=a&rewriteMime=image%2F*" with "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi39dv_hI-l5oR2xeQa_f62B9MLM2_nfc6z1h0T5EU-W_GTaLWalMDzxAfVIMdyTyblGifmmT6sKJ9hsZRdbhC0nuuUkK6diH8Bp6uY9FpIFEHO3_4PyUDekN3vvzrL0tE6C3rxlg/s1600/dismount.png" -->Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com1tag:blogger.com,1999:blog-9675303.post-24012880357154084362013-12-15T09:30:00.000+01:002013-12-15T09:30:00.224+01:00The Lords of Midnight: 8 bit remake returns<div dir="ltr" style="text-align: left;" trbidi="on">
I have some good news regarding my old remake of <a href="http://thelordsofmidnight.com/">The Lords of Midnight</a> on Android.<br />
<br />
First a reminder of the context. You may recall that <a href="http://www.icemark.com/">Chris Wild</a> and <a href="http://en.wikipedia.org/wiki/Mike_Singleton">Mike Singleton</a> worked
together on an update of the Midnight saga with a planned release on iPhone and iPad.
That was before we all learned the sad news that Mike had passed away last year.<br />
<br />
After that, Chris finished off the game - albeit at an understandably reduced scope - and he released it on iOS and then later on other platforms.<br />
<br />
This new game is available at <a href="http://thelordsofmidnight.com/">http://thelordsofmidnight.com</a>, and is a much more ambitious update than my 8-bit-style nostalgic remake.
You really ought to check it out :-)<br />
<br />
Before this all happened, I had created an unofficial remake of LOM on the Game Boy Advance and then later ported it to Android.
It was pretty naïve of me, and Mike asked me nicely to remove these as they were using his copyrighted stuff, and would cause confusion for the upcoming official versions. This I did, and these ports have remained unavailable since.<br />
<br />
Then a couple of weeks ago Chris got in touch with me.
In a rather generous move, Mike's sons have given me permission to re-release the Android port.
They feel it is important for as many people as possible to play the games their dad made.
Because of this, <a href="https://play.google.com/store/apps/details?id=war.of.the.solstice">"The Lords of Midnight: 8 bit" - as it is now known - is available now on the Google Play store</a>!<br />
<br />
If you had installed the previous incarnation you may have noticed an update.
Apart from the usual Android build system updates and associated yak-shaving, the name has been changed to reflect this new deal.
I also fixed some graphical hiccups that were more obvious on my 7" tablet test device, as well as adding the obligatory higher resolution icons.
The other noticeable change is that there is now an extra splash screen that says that this port is released under licence
(from the Singleton family) with the address of the official website at <a href="http://thelordsofmidnight.com/">www.thelordsofmidnight.com</a>.<br />
<br />
I ought to state that this does not indicate a free for all on Mike Singleton's games.
The copyright and trademarks are still the property of the Singleton estate.
While I have been granted permission for the release of this one port, it is under licence with the understanding that the game remains free and that I "do no evil", so to speak.<br />
<br />
What a nice and unexpected early Christmas present, eh folks?<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://play.google.com/store/apps/details?id=war.of.the.solstice"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKn19NDyuJwxJTttqqQ1RxX5vpjo8NJ2AMaKQzPHjpYKNRpogSB9Kt9-k6H2jjplcbMpb9Yjzd-NJgT8niMFnhfGxYC9KvvEZEmSHJEbXVjXMnsTfaIAXJR3J_zplOUZ5KB8voPA/s1600/device-2013-12-15-001556.png" height="250" width="400" /></a></div>
<br /></div>
Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com0tag:blogger.com,1999:blog-9675303.post-42247428451155950722013-12-07T18:57:00.000+01:002013-12-07T18:57:06.957+01:00Blogger Themes That Break With NoScript<div dir="ltr" style="text-align: left;" trbidi="on">
<a href="https://www.blogger.com/blogger.g?blogID=9675303" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a><a href="https://www.blogger.com/blogger.g?blogID=9675303" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"></a><a href="https://www.blogger.com/blogger.g?blogID=9675303" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"></a>
Blogger Themes That Break With NoScript
TL;DR: here's a
<a href="javascript:window.location=window.location.protocol+"//"+window.location.host+"/feeds/posts/default?alt=rss&path="+window.location.pathname;">Blogger Feed</a> bookmarklet to fix some blogger blogs that fail to load if you're using the Firefox add-on <a href="http://noscript.net/">NoScript</a>. Read on for the usual waffle.<br />
<br />
I use <a href="http://noscript.net/">NoScript</a> with Firefox, and occasionally I'll find a link to a blog that just shows the NoScript icon and a handful of broken links.
For example, a recent post on hacker news linked to <a href="http://blog.leafsr.com/2013/12/gcc-poison.html">a security blog post</a>
describing a technique to avoid using dangerous C functions with <a href="http://gcc.gnu.org/">GCC</a>. With NoScript, all I saw was the following:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYEICt-fX1nHyMmeKFDJIoMIkipZ-cx-y4OZ84hhZsI77YPX0yX7Zy9Aj5aYs2qXNoV2TD68U3H4hlJFifnJB-X6D1lRAzuYoRMldIaKGJdvpfd00Ud_uYs_gP0FaEhBK2vXFjiQ/s1600/Selection_072.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYEICt-fX1nHyMmeKFDJIoMIkipZ-cx-y4OZ84hhZsI77YPX0yX7Zy9Aj5aYs2qXNoV2TD68U3H4hlJFifnJB-X6D1lRAzuYoRMldIaKGJdvpfd00Ud_uYs_gP0FaEhBK2vXFjiQ/s1600/Selection_072.png" height="152" width="400" /></a></div>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
This is because a new-ish Blogger theme is a big <a href="http://en.wikipedia.org/wiki/JavaScript">JavaScript</a> application monstrosity that loads the text of the article via an asyncronous call,
but does not gracefully degrade for those of us without scripts enabled.
The owner of this particular blog has since switched from Blogger to Wordpress, so it's moot in this case.<br />
<br />
A poster on <a href="https://news.ycombinator.com/item?id=6845367">HN wrote a bash shell script</a> that downloads the blog,
gets the corresponding feed and spits it out in HTML.
This is a good idea. However I think that copying the blog link over to a terminal,
running the script and then opening the resulting HTML page in the browser is a bit of a pain. Even for me.<br />
<br />
Enter some 90s technology - the <a href="http://en.wikipedia.org/wiki/Bookmarklet">bookmarklet</a>!<br />
<br />
<a href="https://www.blogger.com/blogger.g?blogID=9675303" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a><a href="https://www.blogger.com/blogger.g?blogID=9675303" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a>Simply drag the <a href="javascript:window.location=window.location.protocol+"//"+window.location.host+"/feeds/posts/default?alt=rss&path="+window.location.pathname;">Blogger Feed</a> bookmarklet onto your bookmark toolbar, or right click it and save as a bookmark.
Next time you are faced with a <em>NoBlog</em> you just click the button or bookmark and it'll take you straight to the blog's JavaScript-free RSS feed version of the post.
I imagine that this will work until Google shuts down Blogger and tries to force us all onto Google+.<br />
<br />
In addition, if you want to have an icon for the bookmarklet, here's a tip cribbed from <a href="http://superuser.com/a/151287">this superuser post</a>:<br />
<ol>
<li>Find a regular link (without JavaScript) for the website with the <a href="http://en.wikipedia.org/wiki/Favicon">favicon</a> you want.</li>
<li>Add that link to your bookmarks toolbar as a regular bookmark.</li>
<li>Finally, change the properties of the bookmark you just added and change the location to be the actual JavaScript bookmarklet you want (you want the location from the bookmarklet that doesn't have the favicon).</li>
</ol>
These steps turn the bookmark from step 2 into a bookmarklet with the desired favicon and JavaScript.
Here's a capture of the bookmarklet with the Blogger icon that I use:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHU25Usfz0tXjNT5Boe08ygP7_luESJsGQnMESSYRnhg0Hr0xGm6Vm23ca7Tp127uohgOSZFbU_Hu_gBNoltJiC2WDQGlDe5oShE0iCchpBR3sOozSpBYhBEzNjMfj3ytEt_qMCA/s1600/Selection_073.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHU25Usfz0tXjNT5Boe08ygP7_luESJsGQnMESSYRnhg0Hr0xGm6Vm23ca7Tp127uohgOSZFbU_Hu_gBNoltJiC2WDQGlDe5oShE0iCchpBR3sOozSpBYhBEzNjMfj3ytEt_qMCA/s1600/Selection_073.png" /></a></div>
<br />
<br />
<br />
Sadly, if the Blogger blog uses a Feedburner RSS redirect, then this trick doesn't work.
However if that's the case then you're probably better off not reading their particular brand of propaganda anyway.<br />
<br /></div>
Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com0tag:blogger.com,1999:blog-9675303.post-68869472164452791982013-09-29T22:39:00.000+02:002013-09-29T22:39:21.399+02:00Unlocking an HTC Magic: 2009 called, they want their unlocking guide updated<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: left;">
The <a href="http://www.gsmarena.com/htc_magic-2714.php">HTC Magic</a> running Android 2.2 has a locked <a href="http://en.wikipedia.org/wiki/Booting">bootloader</a>. This means that you can't install any other operating system, only the official one.<br />
<br /></div>
Last year HTC had a change of heart about locking the bootloader and provide a way on their website to unlock your phone.
Unfortunately, the HTC Magic ships with software that is too old to recognise the unlock command the website uses.
You need to first update this software (the "HBOOT") to a version that is unlockable by HTC.<br />
<br />
Go to <a href="http://www.htcdev.com/bootloader/">HTC Dev</a> and create an account. Select HTC Magic and click the unlock button.<br />
<ol>
</ol>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.htcdev.com/bootloader/"><img alt="HTC Dev" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEga-zoLVEHSp_XFJ8p0mrctjP7jg_g_XbDeQ96Jzpd8O2V7ocO0ouy44yfoucwFOEuP7qNXcf4U6QZPSVinrhwZXuNbVf5-kGI4toEW_g1uELA9IrZqfKb5pgoxfUIePz8f-MZuSg/s1600/htcdev_magic.png" height="171" width="400" /></a></div>
<br />
As shown on that screenshot, you are warned that the HBOOT will need to be updated.<br />
<br />
This takes you to the section to download the software, called RUU, that updates the phone's HBOOT.
RUU probably stands for <strong>R</strong>OM <strong>U</strong>nlocking <strong>U</strong>pdater, who knows.
Select the RUU corresponding to your model of Magic.
I used the one marked <i>Vodafone (AU/FR/DE/IT/NL/NZ/ES/UK/ RO/PTG/CH-GER/Mobilkom)</i>.<br />
<br />
This RUU software is a <a href="http://www.microsoft.com/WINDOWS">Microsoft Windows</a> <a href="http://en.wikipedia.org/wiki/Executable">executable file</a>.
In theory you have to use Windows to proceed.
However, I don't have a Windows machine available. I got creative.
You could probably use this technique on Windows if you have problems,
since it sounds like the RUU requires HTC Sync, drivers and other
gubbins.
If you can run the RUU on Windows, run that and it should update the
HBOOT. Follow the HTC Dev instructions, you're almost done.
If not, here is what you could do...<br />
<br />
According to <a href="http://forum.xda-developers.com/showpost.php?p=22613990&postcount=62">this xda-developers post</a> the executable unpacks a zip file as part of the process.
I figured that if I ran the executable with wine it might extract the file too.
The <a href="http://en.wikipedia.org/wiki/.Exe">EXE</a> didn't run to the first step though, but did show a progress bar before crashing out.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_G4OAzSECuxMe6u14YUTJtotEBesOEUZ7E_VFrhXrImFy-PrxyJ5PB7etgD6Jt9JzLUr9F7VD1R9LwtCA_zrPZS0MkoO4lqTINWR-MIbGL5aXAMac2RbpBG1jV3ppF0q4ehiqEQ/s1600/ruu-in-wine.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_G4OAzSECuxMe6u14YUTJtotEBesOEUZ7E_VFrhXrImFy-PrxyJ5PB7etgD6Jt9JzLUr9F7VD1R9LwtCA_zrPZS0MkoO4lqTINWR-MIbGL5aXAMac2RbpBG1jV3ppF0q4ehiqEQ/s1600/ruu-in-wine.png" height="241" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">RUU under Wine on Debian "wheezy"</td></tr>
</tbody></table>
I paused wine just before the program crashed by hitting ctrl-z, ran <code>find ~/.wine -name rom.zip</code> and bingo! There was the rom.zip I neeed.<br />
<br />
Copy this rom.zip file to an <a href="http://www.sdcard.org/">SD card</a>. The file must be named exactly <i>SAPPIMG.zip</i>. The file name is case sensitive.<br />
<br />
You have to format the SD card as fat32. Fat16 will not work. I should know, as originally I had the card as fat16.
I used gparted to format a 1Gb card to fat32.<br />
<br />
Start the phone in "HBOOT mode" - which you do by holding down the power and volume down buttons when switching it on. HBOOT
mode boots very quickly. All being well, after approximately 5 seconds
the blue light will go off and the screen will show some green text
(<span style="color: #38761d;">checking SAPPIMG.zip</span>, more or less).<br />
<br />
It will ask if you want to continue, hit action (the trackball) to confirm, and then the phone reboots.<br />
Now use the fastboot executable from the htcdev website to extract a token unique to your phone.
In Debian I had to use root to do this or it just hung waiting for find devices, so that's <code>sudo ./fastboot oem get_identifier_token</code><br />
<br />
This spat out the following:<br />
<pre><code class="prettyprint">/tmp$ sudo ./fastboot oem get_identifier_token
... INFO
INFO< Please cut following message >
INFO<<<< Identifier Token Start >>>>
INFO41BF2ABF132C78CC414238FC47D43442
INFO898C7C87E0CEB4D1C5D55FCDC17647E2
...
INFOBCF34E9487BE0F794BCAEA48646A3870
INFO2946D797752D6167278226973D86BE33
INFO<<<<< Identifier Token End >>>>>
OKAY
</code></pre>
<br />
Copy this chunk:<br />
<pre><code class="prettyprint"><<<< Identifier Token Start >>>>
41BF2ABF132C78CC414238FC47D43442
898C7C87E0CEB4D1C5D55FCDC17647E2
...
BCF34E9487BE0F794BCAEA48646A3870
2946D797752D6167278226973D86BE33
<<<<< Identifier Token End >>>>>
</code></pre>
<br />
Be careful not to include INFO or have trailing newlines. Paste it into the form on the page on the HTC website.
I have no idea of the security implications, so I've not included all of the token here - you get the idea hopefully. You need all the random numbers and letters and the << >>> lines.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZOK3T3vbVVqadEg6jQRRXLF6HfVGodv-N64LyCCkDkRJhPXkC0NehRXTytmVC_4vbz42xdEutapJKDKRkUNGpc1p-raaTnRPkBCFzTeELEMciuJpoLe4SWjI1tBGm0G8utnKAZA/s1600/htc-token.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZOK3T3vbVVqadEg6jQRRXLF6HfVGodv-N64LyCCkDkRJhPXkC0NehRXTytmVC_4vbz42xdEutapJKDKRkUNGpc1p-raaTnRPkBCFzTeELEMciuJpoLe4SWjI1tBGm0G8utnKAZA/s1600/htc-token.png" height="71" width="400" /></a></div>
<br />
HTC will email you a binary file, which you flash to the phone:<br />
<br />
<code>sudo ./fastboot flash unlocktoken Unlock_code.bin</code><br />
<br />
The following image shows the unlock screen. It's taken with a <a href="http://en.wikipedia.org/wiki/Nintendo_3DS">Nintendo 3DS</a> in low light, hence the terrible quality.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsnzRoWcCfSq7JN1YgadUD0fQI34CMnDGCUzrHgqa2P9l4WJoyCe_kHmbZWIbwBU3066PfYf_BtulCaIP0eMtEk0xvkWoDhxH0BihhseZMbbm-Q5iQNSXdIjTCQijcj5a1avS0rA/s1600/HNI_0094_MPO.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsnzRoWcCfSq7JN1YgadUD0fQI34CMnDGCUzrHgqa2P9l4WJoyCe_kHmbZWIbwBU3066PfYf_BtulCaIP0eMtEk0xvkWoDhxH0BihhseZMbbm-Q5iQNSXdIjTCQijcj5a1avS0rA/s1600/HNI_0094_MPO.JPG" height="240" width="320" /></a></div>
<br />
<br />
Press Volume UP to take the red pill, er, I mean unlock the bootloader... then press the power button.
The phone will wipe all of your data. Oh no.<br />
<br />
That is all. You have unlocked the phone. If you boot into HBOOT again (power, volume down) it should now display UNLOCKED against a fetching fuchsia background.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcHv66b-nEbAMjG-abEgLPBhSzFzF5tXR1wS9Ze4MLC_FIwKu4D5M6v6YTJl9siQUvjZMkoSh_qpn8nVrgLs9tK_SHOJ6nzG4MNyTk6CRPW_jFgU6xGtOeRP0_G_dwIcbpiFqI4g/s1600/HNI_0095_MPO.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcHv66b-nEbAMjG-abEgLPBhSzFzF5tXR1wS9Ze4MLC_FIwKu4D5M6v6YTJl9siQUvjZMkoSh_qpn8nVrgLs9tK_SHOJ6nzG4MNyTk6CRPW_jFgU6xGtOeRP0_G_dwIcbpiFqI4g/s1600/HNI_0095_MPO.JPG" height="240" width="320" /></a></div>
<br />
<br /></div>
Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com0tag:blogger.com,1999:blog-9675303.post-61465146722709466512013-07-25T21:18:00.001+02:002013-08-17T19:54:15.964+02:00Geocities 2.0?<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjejKLQ_LUEFHw09wasy3l3M3yk2INP3-NfxsoGOcWq7wbMSe9kj8-EGpwWVDrLsFbGkVabhoi0AiV-gK9TgVt4tbZhl24Kk6g8T8TFn6GROOpOcrOxkPl9vy6Z6vq0z7VSMJnqQA/s1600/sites.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjejKLQ_LUEFHw09wasy3l3M3yk2INP3-NfxsoGOcWq7wbMSe9kj8-EGpwWVDrLsFbGkVabhoi0AiV-gK9TgVt4tbZhl24Kk6g8T8TFn6GROOpOcrOxkPl9vy6Z6vq0z7VSMJnqQA/s1600/sites.png" height="155" width="200" /></a></div>
After killing off Reader, I think that <a href="http://sites.google.com/">Google Sites</a> is going to be the next to get the axe.
I just recieved an email that pointed me to <a href="https://support.google.com/sites/answer/3156640?hl=en">this Sunsetting Adsense</a> help page.
Rather than sunsetting Adsense, I get the feeling Google is getting itchy to get rid of Sites completely. It probably doesn't fit in with Google+ or something.<br />
<br />
Back in 2009 or so, when Geocities closed down, I asked a question on superuser.com about alternatives for easy-to-host websites.
The top answer, by the internet's Jon Skeet no less, was "Use Google Sites! It'll never shut down!".
You can thank the hive mind on Stackipedia for deleting the question, and now Google Sites has its head firmly in the noose.<br />
<br />
On the side bar to the right you might see that I host my old GBA remakes and the Chaos stuff on Google Sites. Now might be a good time for me to look for a new home for 'em.<br />
<br />
Ah! While I'm ranting: in other related news about removing information from the web, Yahoo Groups have removed their RSS feeds.
I kept track of the Gooey Blob group via the RSS feed.
I realized it had gone way because the pretty good <a href="http://tt-rss.org/">Tiny Tiny RSS</a> warns you about dead feeds,
unlike Google Reader which swallowed all the RSS errors.<br />
<br />
<b>Update 2013-08-17</b>: now Google Code has removed the generic RSS feed too :-( Pages like https://code.google.com/feeds/p/android-ndk-profiler/updates/basic used to show all updates for that project. No more. For now you can still subscribe via RSS to individual Issues, Wiki and Download updates using https://code.google.com/feeds/p/android-ndk-profiler/downloads/basic for downloads, https://code.google.com/feeds/p/android-ndk-profiler/svnchanges/basic?path=/wiki/ for the Wiki changes and https://code.google.com/feeds/p/android-ndk-profiler/issueupdates/basic for issues. It's only a matter of time until these are removed...</div>
Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com0tag:blogger.com,1999:blog-9675303.post-28775221638121338512013-06-28T22:00:00.000+02:002013-06-28T22:00:04.830+02:00The inevitable bug fix releaseAfter releasing a version with new features, it turns out it also contained 1 show-stopping bug. To fix things, 1.15 of Chaos is out.<br />
<br />
Enabling constant saves fell foul of a memory leak in the bit of code that bridged the Android stuff and the older C code.
This meant that the game crashed after about 5-10 minutes of playing. My testing obviously wasn't thorough enough.<br />
<br />
I've resurrected the stress-test mode on the debug builds of Android now (<code>CFLAGS=-DHAS_STRESS_TEST</code>, configure-fans).
In the last release this didn't even compile. Shows how naffly tested it was.
I ran the stress test on the SDL/PC version, but not on Android.
These versions share about 90% of the code, but the bug was right in the Android glue that only running the game on a device or emulator can test.<br />
<br />
The stress mode pits 8 computer-controlled players against each other with no hold-ups, forever. Or until there's a crash at least.
Things are looking a lot better now, as it has run for hours with no crashes since the fix. Previously it wouldn't get past about 6 minutes of play.<br />
<br />
The fix was a classic memory leak. I needed to delete arrays allocated in the C code.<br />
<br />
<pre style="background-color: black; color: white; font-weight: bold;"><span style="font-family: monospace;">JNIEnv *env;
jbyteArray jb;
<span style="color: lime;"><b>int</b></span> size;
<span style="color: cyan;"><b>/*</b></span><span style="color: cyan;"><b> allocate a new byte array </b></span><span style="color: cyan;"><b>*/</b></span>
jb = (*env)->NewByteArray(env, size);
<span style="color: cyan;"><b>/*</b></span><span style="color: cyan;"><b> do stuff with jb ... </b></span><span style="color: cyan;"><b>*/</b></span>
(*env)->DeleteLocalRef(env, jb); <span style="color: cyan;"><b>/*</b></span><span style="color: cyan;"><b> !! this was missing </b></span><span style="color: cyan;"><b>*/</b></span></span></pre>
<br />
I had misunderstood who was responsible for this allocated memory.
I thought that the virtual machine's garbage collection took care of it, but the evidence indicates that it requires manual intervention.<br />
<br />
Lessons learned: 1) automatic tests are great, 2) but not if you don't run them!Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com0tag:blogger.com,1999:blog-9675303.post-82238449951492493612013-06-17T23:00:00.000+02:002013-06-17T23:00:02.000+02:00Chaos 1.14<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-size: small; font-weight: normal;">The last time I updated Chaos was well over a year ago, so it was about due for an update.</span><br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<span style="font-size: small; font-weight: normal;">As well as the usual bug fixes, this release has one new feature: automatic saving.
Players have asked for this both by email and on the comments in the Android market for a while and it makes quite a difference.<br />
<br />
At the end of every turn, the game is now saved.
If the game is stopped then next time you start there's a "Continue" option on the first screen.<br />
</span><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWKwdbYSs07sSqzc07uT5yjVU2SpfH9pkqu22K6n9EftEEzOb_Lk2hPAIUlFTFEx3O6NraJ6Bk-q_HSxJy4R7sMy-mSCPKr9KRJZ4I6xbLSXml-Z16Lq2A3S74VvRl9MMHBZu_Sw/s1600/continue.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWKwdbYSs07sSqzc07uT5yjVU2SpfH9pkqu22K6n9EftEEzOb_Lk2hPAIUlFTFEx3O6NraJ6Bk-q_HSxJy4R7sMy-mSCPKr9KRJZ4I6xbLSXml-Z16Lq2A3S74VvRl9MMHBZu_Sw/s1600/continue.png" height="250" width="400" /></a><span style="font-size: small; font-weight: normal;"><br /><br />
I've also updated<a href="https://sites.google.com/site/chaosbattleofwizards/"> the GBA and NDS versions</a> to include this restore feature.
Whether or not saves actually work can depend on the flash cart you use, so watch out for that.<br />
<br />
The game saves all data in a plain text format that you can copy
around.
I've changed the way options are saved to also use text. Previously I
just dumped out the in-memory representation for the options into a
file.
This should fix the problems that people have had where sound effects
don't work - in fact they were disabled by default.
It was due to reading a 0 first time round and this disabled the sound
option.<br />
<br />
--<br />
<br />
Another change is that <a href="https://sites.google.com/site/chaosbattleofwizards/download">the source code for the game</a> is now available again.<br />
<br />
The state of Android over the last year or so has worried me.
It has become a <a href="http://en.wikipedia.org/wiki/Mos_Eisley">wretched hive of scum and villainy</a> rivalled only by the dark days of the Windows 98/XP platforms.<br />
<br />
The best way to prevent falling victim to spyware is to use software where you can audit the source code yourself.
Or at least say "no" when programs require extra permissions.
Chaos requires no extra permissions and now you can review the code too.<br />
</span></div>
Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com1tag:blogger.com,1999:blog-9675303.post-72472704756818200722013-04-27T22:05:00.000+02:002013-05-24T21:18:55.790+02:00Extracting contacts and calender data from a Nokia 2690<div dir="ltr" style="text-align: left;" trbidi="on">
After resisting the inevitable march of progress, my wife upgraded to an Android phone recently. She had been using a Nokia 2690.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKtd8STV1udUfFo7YM1bokfiYSZwVhz7NNrhJhbI8L-S5hRXHUQhs-_oKzNT3poorxAd1t1Z7V_Ap4Iusr1fsxsN4Q13Wt6vYMwKrVwUZID4CR2nOZjZh18FvN4cVxFHXy2bcStQ/s1600/Nokia-2690.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKtd8STV1udUfFo7YM1bokfiYSZwVhz7NNrhJhbI8L-S5hRXHUQhs-_oKzNT3poorxAd1t1Z7V_Ap4Iusr1fsxsN4Q13Wt6vYMwKrVwUZID4CR2nOZjZh18FvN4cVxFHXy2bcStQ/s1600/Nokia-2690.jpg" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Image from Wikipedia</td></tr>
</tbody></table>
<br />
You may think "pfft, what an ancient phone!", but it has a USB connection and a microSD slot. Besides, I still use a 6100.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcUHnGnaIA0bvTaRPqec5K-ZusbBr2I2EcEdk9udPeFGxOEcmhk3udue80a8d5woOHrOHqiCtpI3Nqq_q1vdw2TDDyUeTJvXkonP6x6fKBMgx6-xNvboue_oAEaM8qYhHF1r_kmw/s1600/220px-Nokia_6100.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcUHnGnaIA0bvTaRPqec5K-ZusbBr2I2EcEdk9udPeFGxOEcmhk3udue80a8d5woOHrOHqiCtpI3Nqq_q1vdw2TDDyUeTJvXkonP6x6fKBMgx6-xNvboue_oAEaM8qYhHF1r_kmw/s1600/220px-Nokia_6100.jpg" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><b>Attribution: <span class="licensetpl_attr" style="font-size: larger;">Cessax / Güstrow (<a class="extiw" href="http://de.wikipedia.org/wiki/User:Cessax" title="de:User:Cessax">Cessax</a> at <a class="external text" href="http://de.wikipedia.org/">de.wikipedia</a>)</span></b></td></tr>
</tbody></table>
<br />
It supports infrared, which must have looked cutting edge back in 2003, but surprisingly few new laptops incorporate it in 2013.
Luckily my 3 contacts won't be too difficult to copy across manually in the unlikely event I actually use one of these Orwellian tracking devices known as "smartphones".<br />
<br />
Anyway, back to the topic on hand.
After swapping the SIM card over, the Android contacts application refused to read the contacts or calender information.
I think the reason was because these had been stored in the actual phone memory instead of on the SIM.<br />
<br />
My initial searches seemed to show that Nokia's Windows-only PC suite was the common way to copy this information from the phone to some usable format.
Curses.<br />
<br />
I tried searching the internet for terms like "transfer contacts nokia phone android ubuntu".
The results were long-dead forum posts copied across multiple spammy domains, blogspam about Ubuntu phones,
adverts for cheap feature phones, and review after review of the latest flavour-of-the-week Android device.
This is the internet we have created in 2013 - full of unanswered questions wrapped in adverts, advertorials with more adverts, spam and money grubbers.<br />
<br />
A beacon (mmm, bacon) of hope was a post on one forum that said "I've tried wammu but it didn't work". Aha!<br />
<br />
Wammu it turns out is a GTK front-end application that ties into the Gammu command line utility to work with dozens (hundreds?) of mobile phones.
And best of all it is Free Software. Jackpot!<br />
<br />
On Ubuntu it's easy to install<br />
<pre><code class="prettyprint">sudo apt-get install gammu
</code></pre>
<br />
Once that was done, I connected the aging Nokia device via USB cable to my laptop and set it to "PC sync mode".
That caused a new device to show up in the /dev directory - <code>/dev/ttyACM0</code>. Wooo!<br />
The gammu configuration I needed was <a href="http://wammu.eu/phones/nokia/5007/">on their wiki</a>, but the connection string did not work.
After fiddling around with wammu it seems like <code>dku2</code> is the correct value for the connection type, and the advertised dku2phone doesn't exist.<br />
<br />
<pre><code class="prettyprint">~$ cat .gammurc
[gammu]
port = /dev/ttyACM0
connection = dku2
</code></pre>
<br />
Once I had the phone details showing up in the wammu GUI I was almost there.
I couldn't figure out how to save from wammu to a useful format - vCard seems to be the standard here.
Luckily using gammu was easier and the man page has this example that does the job:<br />
<br />
<pre><code class="prettyprint">sudo gammu backup gammu_contact_backup.vcf -yes
</code></pre>
I had to use sudo as I wasn't allowed to open /dev/ttyACM0 otherwise, and I couldn't be bothered faffing with groups for this one-off operation.
This extracts all of the contacts and stores it in the vCard format.
It came as a surprise to me that gammu chooses the type of data and the output format based on the backup filename extension, so using ".vcf" is required.<br />
<br />
To extract the calender information, I had to use the ".vcs" extension.
This causes gammu to export calender information and save it in the vCalendar format.<br />
<br />
<pre><code>sudo gammu backup gammu_calendar_backup.vcs -yes
</code></pre>
Once extracted, I copied these onto a suitable sdcard for the mrs's new android phone
(which is a <em>normal person's</em> unlocked-but-freedom-hating Samsung S3 Mini, if you were wondering. Not my choice, but doesn't seem too shabby.)<br />
<br />
The contacts app imported the vCard file no problem.
From the android app's menu (didn't Google try and get rid of menus? Maybe Samsung have more idea about what works) there's an "import from SD card" option.
This goes off and finds the vCard file itself and reads all the contacts in.<br />
<br />
For the vCalendar file it didn't work as I expected. There are no "import" options in the calender app.
Instead, I used the file navigation app (included by default) - and opened the vCalendar file there.
It gave me the choice of what application to open the file with, I chose the calender app, and that was that.<br />
<br />
Unfortunately I didn't manage to get the SMS files off in a way that the Android apps could understand.
I don't think there's a standard interchange format there, each phone does it their own way.<br />
<br />
I dread to think what will happen in a few years time when I want to repeat this process to get the stuff off the Samsung phone though.</div>
Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com1tag:blogger.com,1999:blog-9675303.post-57678147577442915932013-04-20T10:31:00.000+02:002013-05-24T21:19:12.548+02:00Life After Google Reader<div dir="ltr" style="text-align: left;" trbidi="on">
A few weeks ago, Google announced that they would be <a href="http://googlereader.blogspot.com/2013/03/powering-down-google-reader.html">shutting down Google Reader</a> on 1st July.<br />
I used Reader for 2 things: keeping up with podcast episodes and keeping an eye on rarely-updated blogs.
I didn't subscribe to anything with more than 1 post per day, as I couldn't keep up with so many new articles.<br />
<br />
Once I recovered from the shock and disappointment of Reader itself going away, I came to the conclusion that none of the alternatives are really there yet.<br />
<ul>
<li><a href="http://www.feedly.com/">Feedly</a> - requires a browser plugin, and is still based on your Reader account details</li>
<li><a href="http://theoldreader.com/">theoldreader.com</a> - threatening a freemium model</li>
<li>rss2email/tiny-rss - you have to run your own server - the only option that makes sense long-term - but it <em>is</em> a lot of hassle</li>
<li>Just about everything else shows large photos on their homepage and thinks that social media buttons are a good idea. I don't think we'd get along.</li>
</ul>
Since the spring-cleaning announcement I have gone cold turkey on Reader.
My RSS-reading solution is now to imagine we're in early 2005 again and use a local client ☹<br />
<br />
The client I'm using is <a href="http://www.newsbeuter.org/">newsbeuter</a>.
It's a text terminal application (this is a good thing) and has podcast queuing integration too.
It can import an <a href="http://en.wikipedia.org/wiki/OPML">OPML</a> file, which is a list of the feeds that you subscribe to.
Reader has a <a href="https://www.google.com/reader/subscriptions/export?hl=en">URL to export your feed list as OPML</a> too, so migrating is not difficult.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-IGJLg_2NAzRkHLh3QYKEkrV0o3RzQE3ohY5L6HmXAw5yLfNTSrBgQh_RRyltGTJfv649cLraziBexVD6OV39_7HtIstGKpB502t3cSPGr3N2sM0q0mgZOAv2fKgTE8ehF2irMg/s1600/Screenshot-newsbeuter.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-IGJLg_2NAzRkHLh3QYKEkrV0o3RzQE3ohY5L6HmXAw5yLfNTSrBgQh_RRyltGTJfv649cLraziBexVD6OV39_7HtIstGKpB502t3cSPGr3N2sM0q0mgZOAv2fKgTE8ehF2irMg/s1600/Screenshot-newsbeuter.png" height="182" width="640" /></a></div>
<br />
<br />
One nice feature newsbeuter has is the ability to export and import a list of articles that you've already read.
This means that, using a git repository on bitbucket, I can synchronise read articles in a crude way between PCs.
Fortunately I had mostly weened myself off Reader on portable devices, as my Google password is too annoying to type in.<br />
<br />
The real downside is that refreshing articles is pretty slow. A couple of tweaks help here.
Instead of reloading all feeds in one thread, newsbeuter supports multiple threads.
4 seems to speed things up a bit, I couldn't notice much difference using more than this.<br />
<br />
Here's my .newsbeuter/config file:<br />
<br />
<pre><code class="prettyprint">bind-key k up
bind-key j down
reload-threads 4
reload-only-visible-feeds yes
</code></pre>
This is far from ideal, but better than relying on free internet services that could disappear at any moment.
The irony of this blog being hosted on blogger is not lost on me. I fear for its future too.</div>
Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com1tag:blogger.com,1999:blog-9675303.post-75576169442153704132013-01-26T19:35:00.001+01:002013-01-26T19:35:26.598+01:00Update to android-ndk-profiler<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d7/Android_robot.svg/75px-Android_robot.svg.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img alt="Android Robot" border="0" src="http://upload.wikimedia.org/wikipedia/commons/thumb/d/d7/Android_robot.svg/75px-Android_robot.svg.png" title="Android Robot" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Image from <a href="http://commons.wikipedia.org/wiki/File:Android_robot.svg">Wikipedia</a></td></tr>
</tbody></table>
I've just updated my <a href="https://code.google.com/p/android-ndk-profiler">profiling library for native code on Android</a> to version 3.2.
This version is the first "final" release since I moved the code from the subversion repository on <a href="http://code.google.com/">Google Code</a> over to <a href="https://github.com/richq/android-ndk-profiler">github</a>.
I have kept the main project hosting on Googlecode still as <a href="https://github.com/blog/1302-goodbye-uploads">Github recently removed the ability to host pre-compiled downloads</a>.
Not sure what to do with issues yet, but pull requests are welcome :-)<br />
<br />
There are no huge changes, but I have made a switch from the old ad-hoc include mechanism to use the <a href="http://developer.android.com/tools/sdk/ndk/index.html">NDK</a> module system.
This should make it a lot easier to set up the profiling code in an Android.mk file.
I've updated the <a href="https://code.google.com/p/android-ndk-profiler/wiki/Usage">usage page</a> with details of how to do this.
For some reason the HTML documentation for the NDK is not online anywhere,
the best you can do to view the module documentation without downloading the NDK itself is probably <a href="https://raw.github.com/flyskywhy/android-ndk-r7b/master/docs/IMPORT-MODULE.html">this page</a>.<br />
<br />
The switch over to github meant I could also start using <a href="http://travis-ci.org/">Travis CI</a>,
which is a great <a href="http://en.wikipedia.org/wiki/Continuous_integration">continuous integration</a> service for public repositories.
I haven't read much about this anywhere, but it seems like a well thought out service, and it was really simple to set up.<br />
<br />
<br />
<br />
</div>
Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com0tag:blogger.com,1999:blog-9675303.post-65934455604319185682013-01-24T20:57:00.000+01:002013-05-24T21:19:56.165+02:00Command line and Gnome Desktop integration tips for Vim<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
Here are a couple of ideas that I find handy when working with Vim.The first tip is how to check what the last search term was in Vim from the command line.
A silly idea that I've found more useful than I thought it would be.<br />
<br />
For this to work, you need <code>set nocompatible</code> so that Vim writes out its state information to a <code>viminfo</code> file on exit.
The line in the viminfo file that stores the last search looks like this:<br />
<br />
<pre><code class="prettyprint"> ~Msle0~/search_term
</code></pre>
<br />
The m, s, l and e characters describe which magic, smartcase, line/char offset, or from the end or start flags Vim had set when you searched.
For example, the third character is an 's' or an 'S' depending on whether smart case is on (S) or off (s).<br />
<br />
Here is a script, which I call <code>last_vim_search</code>, that shows you what the last search term stored in the viminfo file was:<br />
<br />
<pre style="background-color: black; color: white; font-weight: bold;"><span style="font-family: monospace;"><span style="color: cyan;"><b>#!/bin/bash</b></span>
<span style="color: cyan;"><b>lvs</b></span>=<span style="color: #8080ff;"><b>$(</b></span><span style="color: #ff6060;"><b>awk -F/ </b></span><span style="color: yellow;"><b>'</b></span><span style="color: #ff40ff;"><b>/^~[Mm][Ss][Ll][eE]0~\// { print $2; }</b></span><span style="color: yellow;"><b>'</b></span><span style="color: #ff6060;"><b> ~/.viminfo</b></span><span style="color: #8080ff;"><b>)</b></span>
<span style="color: yellow;"><b>if </b></span><span style="color: yellow;"><b>test</b></span> <span style="color: #8080ff;"><b>$#</b></span> <span style="color: yellow;"><b>-eq</b></span> <span style="color: #ff40ff;"><b>0</b></span> <span style="color: yellow;"><b>;</b></span> <span style="color: yellow;"><b>then</b></span>
<span style="color: yellow;"><b>echo</b></span><span style="color: #ff40ff;"><b> </b></span><span style="color: #8080ff;"><b>$lvs</b></span>
<span style="color: yellow;"><b>exit</b></span>
<span style="color: yellow;"><b>fi</b></span>
<span style="color: yellow;"><b>grep</b></span> <span style="color: yellow;"><b>"</b></span><span style="color: #8080ff;"><b>$lvs</b></span><span style="color: yellow;"><b>"</b></span> <span style="color: yellow;"><b>"</b></span><span style="color: #8080ff;"><b>$@</b></span><span style="color: yellow;"><b>"</b></span></span></pre>
</div>
<br />
The snippet of awk searches for the matching pattern, splits on the "/" character, and spits out the last used pattern.<br />
<pre><code class="prettyprint">$ last_vim_search
\<pattern\>
</code></pre>
<br />
As an added bonus, if I pass arguments to the script then it searches whatever arguments I passed in using grep.<br />
<pre><code class="prettyprint">$ last_vim_search *c
file.c:123: ....
file.c:456: ....
</code></pre>
<br />
The second tip is how to integrate Vim with the "Recent Documents" feature from the Gnome Desktop.
Frequently I find myself editing a text file in Vim, and then having to attach it to an email or upload it to a web form.
Having the file you want to upload in the recent documents list helps a lot in these situations,
as it is quicker to get to than having to navigate the file chooser to the correct location and selecting the file there.
Unfortunately only "Gnome-ish" applications update the recent documents list, and terminal Vim is not one of these.
This tip fixes that situation, and lets Vim update the recent list too.<br />
<br />
For this to work, you will need the python-gtk bindings.
Debian and Ubuntu at least installs python-gtk by default with Gnome.
Also your version of Vim needs to have Python support compiled in.
If not, you could adapt the python snippet to run in its own script.<br />
<br />
<pre style="background-color: black; color: white; font-weight: bold;"><span style="font-family: monospace;"><span style="color: cyan;"><b>"</b></span>
<span style="color: cyan;"><b>" add text files that I edit to Gnome's recent file list</b></span>
<span style="color: cyan;"><b>"</b></span>
<span style="color: yellow;"><b>function</b></span>! <span style="color: #ff6060;"><b>s:</b></span>RecentAddFile<span style="color: #ff6060;"><b>()</b></span>
<span style="color: cyan;"><b>python <<EOF</b></span>
<span style="color: #8080ff;"><b>import</b></span> vim
<span style="color: #8080ff;"><b>import</b></span> gtk
n = vim.current.<span style="color: cyan;"><b>buffer</b></span>.name
f = <span style="color: #ff40ff;"><b>'file://'</b></span> + n
gtk.recent_manager_get_default().add_full(f,
{<span style="color: #ff40ff;"><b>'mime_type'</b></span>: <span style="color: #ff40ff;"><b>'text/plain'</b></span>, <span style="color: #ff40ff;"><b>'app_name'</b></span>: <span style="color: #ff40ff;"><b>'vim'</b></span>, <span style="color: #ff40ff;"><b>'app_exec'</b></span>:<span style="color: #ff40ff;"><b>'vim'</b></span>})
<span style="color: cyan;"><b>EOF</b></span>
<span style="color: yellow;"><b>endfunc</b></span>
<span style="color: yellow;"><b>autocmd</b></span> <span style="color: lime;"><b>BufReadPost</b></span> *.txt <span style="color: yellow;"><b>call</b></span> <span style="color: #ff6060;"><b><</b></span><span style="color: #ff6060;"><b>SID</b></span><span style="color: #ff6060;"><b>></b></span>RecentAddFile<span style="color: #ff6060;"><b>()</b></span></span></pre>
<br />
This makes use of the "recent documents" GTK API.
It's only short and doesn't really need much explanation.
The <code>python <<EOF</code> marks the start of the embedded snippet of python code, the rest is all vimscript.
The <code>autocmd BufReadPost</code> bit means that when Vim reads in a txt file it will call the function to add the file to the recent list.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCWmol_2-Bsh_EnXK6J0qQhClXMPEmlsas5TFkdsy-jtLHTsYecEymSVCQjqv_YUt2mqjLpZw4WJQOp2R3HMePUUCD2g4I_4Voqee-TErPl7a5oDavrWVlOVVamMrRVQtkS0XYDg/s1600/recent-docs.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCWmol_2-Bsh_EnXK6J0qQhClXMPEmlsas5TFkdsy-jtLHTsYecEymSVCQjqv_YUt2mqjLpZw4WJQOp2R3HMePUUCD2g4I_4Voqee-TErPl7a5oDavrWVlOVVamMrRVQtkS0XYDg/s1600/recent-docs.png" /></a></div>
<br />
<br />
The python code uses Vim's own API to get the current file name, which it turns into a URL by prepending "file://".
The gtk call adds the URL to the recent document list.
There's a simpler "add_item" method too that doesn't need the options passed in via the dictionary argument,
but it doesn't seem to work in this context.<br />
<br />
You could tweak the code to only add files in your home directory - as is it will add help pages as recent docs too.
With different autocmd lines you could also add other file types to the recent history.<br />
<br />
And now for something completely different... check out this great Super Meat Boy plushy that my better half made for eldest son. That's love :-)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEGTGQiawdHFsJhQzQ2du-F7Fbe-A4_Ri6oBCA2ig8WPEqYz2KUJZIkOGJu5UA9PAZRwRSnhCosjYZ2itJ1EEDQGJnoo0Aubqk4xPh2QYIl6e5Ht4sfWeS8Ao0jTvgXog7-6chtA/s1600/HNI_0009.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEGTGQiawdHFsJhQzQ2du-F7Fbe-A4_Ri6oBCA2ig8WPEqYz2KUJZIkOGJu5UA9PAZRwRSnhCosjYZ2itJ1EEDQGJnoo0Aubqk4xPh2QYIl6e5Ht4sfWeS8Ao0jTvgXog7-6chtA/s1600/HNI_0009.JPG" height="300" width="400" /></a></div>
<br />
<br />
<span style="font-size: x-small;">PS. This weekend I'm hoping to have time to put the final touches on a new android-ndk-profiler release. The current beta-ish version seems to be working OK if you want to try it out.</span><br />
<br /></div>
Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com0tag:blogger.com,1999:blog-9675303.post-29047608731129413102012-11-23T21:27:00.002+01:002013-05-24T21:21:19.799+02:00Two problems with android-ndk-r8c<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
<div style="text-align: left;">
I've been trying to get back in to Android development,
and the first thing to do was update all the build tools to the latest releases.
This revealed 2 irritating problems in the current NDK when using ndk-build.</div>
<br />
The first one is that your native code now rebuilds all the time. Whenever you run ndk-build,
it compiles <em>everything</em> from scratch again.
<a href="http://code.google.com/p/android/issues/detail?id=39810">This is a known bug</a> that looks like it will fixed in an update in the near future, but it is a bit irritating.
The cause is that the object directory is a dependency of each object file,
which means make will execute the rule to create the directory before it builds the objects.
But writing the objects into the directory causes the modification time of the directory to change,
forcing a rebuild of the depending objects.
A vicious cycle that causes make to think your objects are always out of date.
How nobody spotted this bug before release is a mystery to me.
Anyway, the fix is easy - open up <code>android-ndk/build/core/definitions.mk</code> and change line 289 to the following:<br />
<br />
<pre><code class="prettyprint">$1: | $$(__ndk_file_dir)
</code></pre>
That adds in a | symbol before the $$.
It's a <a href="http://www.gnu.org/software/make/manual/html_node/Prerequisite-Types.html">GNU Make feature</a> designed specifically for this problem.<br />
<br />
The second issue is not such a clear cut bug. It is definitely a
regression,
but whether the bug is in the NDK or the Eclipse Android plugin is <a href="http://code.google.com/p/android/issues/detail?id=39752">up for debate</a>.
This only affects you if you are trying to support older versions of
Android and use native code.<br />
<br />
When you want to support old releases and still use the latest SDK,
you must specify the minimum SDK in your manifest XML file and specify
the latest target platform in the project.properties file.
Sadly with the r8c release the NDK part of the build spits out a warning
like this:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgE8mh8jEUATCUHPRrRkjv1Y_lYbSeVwXLV-NiIW3Iz8P78nY-gQAWD_c4iPibFLIGswkQMsHAqQg5zIHo5em6J-PgkR0Hkxj2U0FZHPGJKhmbjjXNNGjdDirZEI48OyB1KBi0Bmw/s1600/eclipse-ndk-error.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgE8mh8jEUATCUHPRrRkjv1Y_lYbSeVwXLV-NiIW3Iz8P78nY-gQAWD_c4iPibFLIGswkQMsHAqQg5zIHo5em6J-PgkR0Hkxj2U0FZHPGJKhmbjjXNNGjdDirZEI48OyB1KBi0Bmw/s640/eclipse-ndk-error.png" width="640" /></a></div>
<br />
<pre><code class="prettyprint">WARNING: APP_PLATFORM android-8 is larger than android:minSdkVersion 4 in AndroidManifest.xml
</code></pre>
Eclipse sees this warning and prevents you from launching the emulator with the usual "Run" command.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrUVigfZw3NfJnPNgZqRP5C0-xbHok4UtloGQgnIlHIVIBfXBgs4A5A1qM4lKlpJYdOPUVO2TFmtxqPD5UTw-GSTSO9D7wC1EUZ3fAXLjpu4XxKFConMNR26HzbmmCDtJGN7us5Q/s1600/eclipse-no-launch-errors.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="125" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrUVigfZw3NfJnPNgZqRP5C0-xbHok4UtloGQgnIlHIVIBfXBgs4A5A1qM4lKlpJYdOPUVO2TFmtxqPD5UTw-GSTSO9D7wC1EUZ3fAXLjpu4XxKFConMNR26HzbmmCDtJGN7us5Q/s400/eclipse-no-launch-errors.png" width="400" /></a></div>
<br />
The easiest workaround is to add <code>NDK_NO_WARNINGS=1</code> to the ndk-build invocation of your native part of the build.
Right click your project and select Preferences > C/C++ Build.
Uncheck the default option and change it to <code>ndk-build NDK_NO_WARNINGS=1</code>.
This is just a workaround - if you have other warnings in your build
then maybe you need to fix them :-) but as far as I can tell,
the only other warning that could appear would be if you built with <code>NDK_DEBUG</code> set to something other than <em>true</em> or <em>false</em>.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZZRth73eU6Yew7cKv4vHLz8UtKX13MwyYrRIYz40fq6i-cl0L5epmPMgSjnX1dIgB7OjwAM5ZY6UJWcvCjuUlXCo9wTZ4uM7X9NCxT0kh-8sOa1AZhw9EZmKSjp9TEc1VT-THtw/s1600/cpp-settings.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="308" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZZRth73eU6Yew7cKv4vHLz8UtKX13MwyYrRIYz40fq6i-cl0L5epmPMgSjnX1dIgB7OjwAM5ZY6UJWcvCjuUlXCo9wTZ4uM7X9NCxT0kh-8sOa1AZhw9EZmKSjp9TEc1VT-THtw/s640/cpp-settings.png" width="640" /></a></div>
<br />
Of course you mustn't actually use any new Android features at run time, or the application will crash.<br />
<br />
Anyway I hope that helps someone out.<br />
<br />
Oh, bit of editorialising now.
It's interesting to see Google introduce Clang in this version of the NDK too.
I fully expect them to bit-by-bit remove all the GPL code in the NDK and SDK, and GCC is the biggest piece there.
Then they'll release the SDK binary-only with secret sauce.
Similar to the way Chrome is a closed version of Chromium that includes Flash,
and Google and co develop Android behind closed doors before releasing it to the Open Handset Alliance,
but devices all ship with closed-source <a href="https://developers.google.com/android/nexus/drivers">proprietary drivers</a>.
Currently the SDK is one of the few parts of Android that's <a href="https://android.googlesource.com/platform/sdk/">developed in the open</a>. I can't see that lasting, especially after Google added <a href="http://www.pcworld.com/article/2014089/google-targets-android-fragmentation-with-updated-terms-for-sdk.html">the recent "no fork" clause</a> to the terms.<br />
</div>
Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com4tag:blogger.com,1999:blog-9675303.post-68454634883278426822012-09-29T19:45:00.000+02:002012-09-30T16:06:59.554+02:00A new MP3 player and other product placements<div dir="ltr" style="text-align: left;" trbidi="on">
After the last post on that EZ Flash cartridge I bought for the GBA, this installment is another tale of rampant <em>consumer</em>ism
all about another new toy I've recently bought - a Sandisk Clip Zip MP3
player. Ah, and I also bought Batman Lego 2, which has been a great
success with my eldest son. It's not a bad game, far better than the
horribly bugged DS Star Wars Lego at least. Probably a bit easy for most of us older gamers. It came with this
amusing Lex Luthor figure, made of tiny pieces that disappear under the sofa with surprising ease:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-tAqEJJs-k2Or9yqiRufeLf-JJa9iI5c1ab0j6sQ4UMsqtWY_Eti2blZQwpOOQqDt66CHkoe90Z1jWVqhxxMHOfzMZr52lKvdcmRoG_G8sZAIsirAPTavRa-5y1YEJqqS6kugJw/s1600/luther.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Lex Luthor, awwww" border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-tAqEJJs-k2Or9yqiRufeLf-JJa9iI5c1ab0j6sQ4UMsqtWY_Eti2blZQwpOOQqDt66CHkoe90Z1jWVqhxxMHOfzMZr52lKvdcmRoG_G8sZAIsirAPTavRa-5y1YEJqqS6kugJw/s320/luther.jpg" title="Lex Luthor, awwww" width="320" /></a></div>
<br />
<br />
Speaking of <strong>consumer</strong>,
I really despise the way that the word has taken over the American
technology press. Nobody reads, listens or watches anything anymore -
they only <em>consume</em>. We now consume books, consume music, consume
films, consume TV shows. Consume, consume, consume. Arrrgghh! It's
actually made me stop listening to the <a href="http://twit.tv/tnt"><em>Tech News Today</em></a> podcast. Heh, I feel like I ought to be writing "wake up sheeple!" at this point. You get the idea.<br />
<br />
So then, MP3 player. Eager readers may recall that <a href="file:///2009/07/creative-zen-mozaic-on-ubuntu-904.html">3 years ago I got a Creative Zen Mozaic</a>
to replace another Creative model that was starting to fall apart. The
Zen has been a pretty good MP3 player, it has a nice user interface and
after fiddling I could use <a href="http://gnomad2.sourceforge.net/">gnomad2</a> to transfer MP3s across to it. Sadly, what really lets it down is its on/off/lock switch.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeDwz7iwATXYW3MedzmXjYURBUXB9Z7Nu_5A-GrvKd17yRSrHwWj2Z0aWHrsK6ZyynZq3T5MLNdcdDeDJJxREmejIT0eJHV6uP9U8ev1gaduW0Vf7IRMuENLlLObvgc2sjdeonsQ/s1600/creative-button.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="Creative on-off-lock switch" border="0" height="207" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgeDwz7iwATXYW3MedzmXjYURBUXB9Z7Nu_5A-GrvKd17yRSrHwWj2Z0aWHrsK6ZyynZq3T5MLNdcdDeDJJxREmejIT0eJHV6uP9U8ev1gaduW0Vf7IRMuENLlLObvgc2sjdeonsQ/s320/creative-button.jpg" title="Creative on-off-lock switch" width="320" /></a></div>
<br />
<br />
This
switch is vital. You press down to turn the device on or off, with the switch springing back to the middle when you let go, or you press it up to
lock the screen, whereupon the switch clicks into place. If the screen is not locked then the backlight remains
on, wasting precious battery life. As you can almost make out on that
crappy photo, the button and surrounding plastic have been worn away by
constant use over the years, and now the switch lever itself is below
the level of the surrounding plastic, making it tricky to move. In
addition, the underlying springyness part and electronic contact of the switch has become flakey - it
sometimes doesn't register changes from on to off or to lock at all.
This seems to be a fundamental flaw in the design of the Zen Mozaic - I
already had to send one back to the manufacture after only a few months
of use as its switch packed in completely - and a bit of a shame,
because besides that it is a good player.<br />
<br />
Having said all that, I have been wanting to try out <a href="http://rockbox.org/">Rockbox</a>
for a while now, and the Creative devices have never been supported by
this interesting Free firmware for digital audio players. Some advances
have been made on a couple of the newer Creative devices, but not for
the older Mozaic model. Even for those it does sort-of work with, it is still early days. By comparison, the
Sandisk MP3 players are very well supported. I decided to take the plunge. BTW, the Zip is rated as "unstable" by the project, but only because it lacks
documentation screenshots and a couple of games are not formatted correctly for
its smaller screen. The music playing side of things works great.<br />
<br />
I couldn't find a Sandisk Clip Zip for sale in any of the major
retailers here in Madrid. They only seem to sell Apple, Samsung and Sunstech devices (big in India, apparently). The bottom has really fallen
out of the MP3 player market, it seems. I ended up buying from Amazon. The UK version was surprisingly the cheapest, and with no charger included, 3pin or otherwise, it made no difference to me.<br />
<br />
Once you buy a Zip and figure out how to get the
player out of the box it comes in (pro tip: use a stanley knife, nobody
is peeling that glue apart) the actual Sandisk build quality feels
nastier than the Creative one. The buttons on the front face are a bit
hollow-plasticky sounding, and the socket to plug in the headphones
doesn't inspire confidence. It needed an ungodly shove to get the 3.5mm
jack in there. I haven't dared take it out again, just in case the whole
thing comes apart in my hands. On the plus side, it weighs next to
nothing. Not that I exactly needed a trolley to wheel around the old
Mozaic, which was itself a lightweight compared to the even older Micro,
but the Zip feels like it's hollow it is that light.<br />
<br />
I didn't
spend much time with the Zip's stock original firmware (OF) - pretty
much just long enough to confirm that the Zip turned on and played
tracks correctly. Interestingly the OF lets you choose whether to use
the device in MSC or MTP mode - that's massive storage, or media
transfer protocol. The Mozaic had this partly built in, but only let you
use up to 2Gb as regular storage, not the whole device.<br />
MSC means
the device is seen as a regular mounted disk and is typically what USB
drives and cameras use. After you finish transferring files, you have to
remember to unmount the device so that you don't lose any partially
written data. MTP has a more proprietary history, being a Microsoft
invention that up until recently was not a standard. In recent Ubuntus
at least MTP has been quite well supported. It has the advantage of not
needing to unmount after transferring files, and on really modern
devices the software on the device itself can still read and write to
the storage even if the computer it is connected to wants to do the
same. With traditional MSC only one "thing" can use the drive at a time.
This is one reason why newer Android versions have switched to MTP over
having a mounted drive visible on external computers.<br />
<br />
All that
said, I tried MTP on the Sandisk, and though Gnomad2 recognized it, it
gave a funny error ("-1" not recognized or something). And transferring a
file with a "?" in the name cause the Sandisk to lock up! Ulp. So I
quickly reverted to regular MSC mode. Besides, Rockbox mostly installs
as regular files on the player's drive, so having it in regular USB mode
would be an advantage there.<br />
<br />
Installing Rockbox is really, really
easy! I was expecting it to be a crazy ordeal involving partition
tables or something. You do have to download the OF, since the Rockbox
installer patches this to boot either the OF or the Rockbox code when
you turn the device on, but apart from that you literally just plug the
Zip in, start the installer, and click "Install". When you unplug the
gizmo it says "updating firmware" for a minute or so, then reboots into
the Rockbox UI!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjk3pK2yPYGUPrz_FHpugltYOuuJeu0PskxbjowtGYw2SgBuUrMg0LYIEXwMsZvDBh_iwjq8n4NPY1Ni3Qagipb_wrTuExMurCB_XUg-9twKbRszmuw8HO2VKl-OtPQ2XxCDX660Q/s1600/rockbox-install.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="284" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjk3pK2yPYGUPrz_FHpugltYOuuJeu0PskxbjowtGYw2SgBuUrMg0LYIEXwMsZvDBh_iwjq8n4NPY1Ni3Qagipb_wrTuExMurCB_XUg-9twKbRszmuw8HO2VKl-OtPQ2XxCDX660Q/s320/rockbox-install.png" width="320" /></a></div>
<br />
<br />
Rockbox
is Free Software. And like a lot of Free Software, it has a user
interface that is rather "designed by programmers". This means you can
do tons of things, it has a million options and tweaks, and everything
is consistent with the model the programmers had. But it is initially
overwhelming and looks a little bare-bones. You can see a couple of the
default screens on <a href="http://phoneboy.com/4340/rockbox-rocks">this blog post</a>.
The Zip has a smaller screen than the Zen Mozaic, but the Zip OF had a
fair amount of gratuitous bells and whistles. It "looked nicer" than
Rockbox, I think you could say. However, one immediately irritating
thing Rockbox fixes that the OF did was to rebuild its MP3 database
index every time you unplugged the thing from the USB. Every f-ing time!
The whole database! This took several minutes - the <a href="http://forums.sandisk.com/t5/Sansa-Clip-Zip/Refreshes-media-every-time-i-charge-it/td-p/284266">sandisk forum response</a> is "buy a charger", or (hilariously) "it must be the antivirus software you have". Ha ha.<br />
<br />
I
use my MP3 player for 3 things: listening to music at work, listening
to podcasts on my daily commute, and listening to music before falling
asleep at night. For the music-at-work thing, I think things will be OK.
I like the fact that Rockbox aggressively switches off the backlight
and does so even without being locked. Having to constantly lock/unlock
the Zen to get the backlight off is probably what wrecked the switch in
the end.<br />
<br />
For the daily commute, podcast support is improved over
the Zen. First off, the bookmarks are created automatically when you
stop a track and automatically resume (or asks you) if you play the same
track. On the Zen you have to manually create bookmarks, and manually
select them from the bookmark menu. Secondly, you can set the "skip
length", so that instead of skipping to the next track when you press
">>" it can skip any number of seconds. I have this set to 30
seconds, which is perfect for skipping the otherwise-great <a href="http://podcast.ubuntu-uk.org/">Ubuntu UK Podcast's</a>
incredibly irritating and remarkably unfunny "Tomorrow’s Technology
Today" segment, for example. Or for skipping adverts, I don't always
want to "consume" these.<br />
<br />
When I plug the MP3 in before going to
bed, I set a sleep timer for 15 minutes. That way if I doze off, it
doesn't play all night and waste the battery. On the Zen this could be
placed on a shortcut and was easy to enable or disable. When set to
"off" that was it, the sleep was off. When it was set to "15 minutes" it
reset to 15 minutes each time you switched it back on.<br />
<br />
On Rockbox
it works a little differently and has 2 options and a "start/cancel"
button. One option controls the default time, and the other determines
if the timer should reset when you switch the Zip back on again. This is
actually not that helpful, and I couldn't seen any way to make it so
that you could have it either off, or on-and-always-resetting-on-reboot -
you always have to fiddle with 2 options. e.g. if you have
reset-on-start "on", but cancel the timer, then rebooting will start the
timer again. You have to go in and press "cancel" again, which is 3
menus deep and can't be placed in a shortcut. But at night, you want the
timer on if you reboot (because you haven't fallen asleep and want to
restart the player for another 15 mins).<br />
<br />
So my first
hack-on-the-code patch was to make it work more like the Zen. I added 0
minutes to the list of default times, and if you select that it cancels
the timer. Now, when I turn the Zip on for the commute, I set the timer
to 0 minutes. And at night, I set the timer to 15 minutes. The "set
default time" option can be placed on a shortcut, which means there's no
need to dive deep into the options every time.<br />
<br />
A bit of RTFMing revealed that you can <a href="http://download.rockbox.org/daily/manual/rockbox-sansaclipzip/rockbox-buildch13.html#x16-31900013.1.1">hide entries on the main menu</a>.
This makes it a little less overwhelming, and I immediately got rid of
the options I knew I'd never use, like FM radio and voice recorder. It's
a shame that this is not more configurable - on the Zen you can hide
menu items and "pull up" sub-menu items into the top menu, but I don't
think the Rockbox code is really designed in a way to allow this level
of flexibility. Another customization I made was on the "database" menu,
which is the Rockbox name for where all the track filtering options
are, like list songs by artist, album, genre, etc. This is really
overloaded with zany selections I'll never use. I mean "order by
composer" as a main menu item? Really? The database menu navigation
configuration is a plain text file, and is easy to hack up to something a
bit easier to manage - of course the devs recommend not doing this. But
I'm a professional, don't try this at home :-) I even added <a href="http://www.rockbox.org/wiki/DataBase#Examples">the podcast menu item</a> mentioned on the wiki.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhT-ceEsuql48C5mzo-pWXVWN631mqT-puwy5qLpSSuPt9JQYXhvoXlxScNo1E8t6UAKWcCx6fs0-UIei6jcGrwxTuNWuoKRzsmcBkAOJAFecFua-ca06aKa4v8NE17FSA97xft4A/s1600/rockbox-main.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="272" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhT-ceEsuql48C5mzo-pWXVWN631mqT-puwy5qLpSSuPt9JQYXhvoXlxScNo1E8t6UAKWcCx6fs0-UIei6jcGrwxTuNWuoKRzsmcBkAOJAFecFua-ca06aKa4v8NE17FSA97xft4A/s320/rockbox-main.jpg" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfr6gK8qXZSaCtnQoUcFr1pDKFHcDTNs875QeGsZ1oME6LOs1cOD5PERlUARhqhb3bl8rC3xrtnTN0BBip8U-SEsumcoL9JwWchfyuis5_NcH0zw8KH7J-f1MpBUbd7lfsA2lprQ/s1600/rockbox-main-screen.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfr6gK8qXZSaCtnQoUcFr1pDKFHcDTNs875QeGsZ1oME6LOs1cOD5PERlUARhqhb3bl8rC3xrtnTN0BBip8U-SEsumcoL9JwWchfyuis5_NcH0zw8KH7J-f1MpBUbd7lfsA2lprQ/s1600/rockbox-main-screen.png" /></a></div>
<br />
As you can see on those images, I've set the text to resemble the
classic green-on-black that is well known for being the greatest
combination.<br />
<br />
One acronym that comes up time and time again on the
Rockbox Wiki but took me a while to find out what it meant is "WPS". WPS is short for the "While Playing
Screen", which is the screen shown while a track is playing.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8D6X4LwcBP1ptO3ECGeYsOSsqYZoLqjBDGkzMfHPqhx6ZeZz4ATj817Bbs3R_W9zHA-Tb673pNNMOT0t9yON5ZjCuEdbKQpirPDoucQu4GlA1nXXPgBGvRL_I9xphnh-gUSptTQ/s1600/rockbox-play.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="On device screenshot" border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8D6X4LwcBP1ptO3ECGeYsOSsqYZoLqjBDGkzMfHPqhx6ZeZz4ATj817Bbs3R_W9zHA-Tb673pNNMOT0t9yON5ZjCuEdbKQpirPDoucQu4GlA1nXXPgBGvRL_I9xphnh-gUSptTQ/s320/rockbox-play.jpg" title="On device screenshot" width="310" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzaMB3NPHMZsj5pTHIfSbo23j3wDOo7ZVhNhqUNZFVW0PHPRYXq5FBWaYgzFo4F1y-4jiR_PppBXXDd0_Q61NR_HAp4ShTCAu9HYLhZqZLqBpytIu2rZC1-1Ty0tJYGU2yVxAp5Q/s1600/rockbox-wps.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzaMB3NPHMZsj5pTHIfSbo23j3wDOo7ZVhNhqUNZFVW0PHPRYXq5FBWaYgzFo4F1y-4jiR_PppBXXDd0_Q61NR_HAp4ShTCAu9HYLhZqZLqBpytIu2rZC1-1Ty0tJYGU2yVxAp5Q/s1600/rockbox-wps.png" /></a></div>
<br />
<br />
There are dozens of skins for this screen, as well as the rest of
Rockbox. You can mix and match skins. I found the default WPS skin a
little hard to read, and a simpler design with big letters works better
on the small screen. Here the functionality over looks of Rockbox trumps
the Zen WPS. In less pixels, the custom screens manage to pack in a lot
more info, such as bitrate, file type, genre, and the clever "next
track" text.<br />
Rockbox playlists are just text files! This is
something I've always wanted on the Zen, since creating "complex"
playlists on the device is fiddly, and Gnomad2 is not much better. Now I
can create a list of tracks using <code>find</code> and edit that list
in Vim, the text editor of champions. For example, to create a list of
all the Super Furry Animals tracks, I can now do the obvious...<br />
<br />
<pre><code class="prettyprint">cd /media/SANSA\ CLIPZ/Playlists/
find ../MUSIC/Super\ Furry\ Animals/ -type f | sed 's/^\.\.//g' | sort > SFA.m3u8
</code></pre>
<br />
Then in Vim move the lines around to get all the albums in
chronological order. Doing that any other way always caused me to miss
out on some tracks, like forgetting the Ice Hockey Hair EP or something.
No danger now. Here, <a href="http://www.youtube.com/watch?v=mpXNSQ2NXPg">go and watch this '96 performance of "Something for the Weekend" on Later with Jools Holland and be nostalgic</a>.<br />
<br />
What
else? Oh, I've been saying "MP3" in this post, but the Zip with Rockbox
also plays .ogg files too. And .flac, and a million other formats -
including video game formats like MOD, SID and NSF. The Zen was limited
to MP3 and some Windows-specific codecs that nobody uses. One thing that
using MSC rather than MTP does really force you to do is make sure that
your MP3 ID3 tags are all correct. I used tagtool to fix file names,
and id3v2 to get rid of empty or rubbish ID3 tags that transferring the
files off my Zen had created. After that, it turns out that the FAT32
file format can't handle some "special" characters, including ?, : and
". I used a line like this in bash to fix the mess ups for each
unsupported character:<br />
<br />
<pre><code class="prettyprint">find . -name '*:*' | while read file ; do mv "$file" "${file//:/_}"; done
</code></pre>
<br />
Then there's all the "under the hood" stuff that Rockbox improves
over most things - battery level that seems really accurate (the Zen
only ever seemed to have 3 stages: 100%, 75%, 0%), random number
generator for shuffling tracks that puts Nethack to shame, loads of
equalizer knobs and buttons, etc, etc.<br />
<br />
Compiling and testing
custom versions of Rockbox is pretty similar to GBA development, except
that instead of an emulator the Rockbox authors have created a
simulator. Here you build the source for a native (e.g. x86) version of
the source code, and executing the resulting binary simulates the device
running on your computer in its own little window. This makes testing
custom menus and firmware builds a lot easier, since there's no need to
copy stuff across, uplug, and reboot. Once you want to test on the real
thing, you need to use a GCC cross-compiler for ARM. Unlike devkitARM,
which is distributed in binary form to quickly get you up and running,
there's a "rockboxdev.sh" script that downloads, patches and compiles a
suitable version of GCC and associated tools. This takes a while, but
Just Works (or at least it did for me). After that, you run an
autotools-like "configure" script and choose the device you want to
build from the list of dozens, then run "make" to build the source code
for your player.<br />
<br />
Testing a custom build - once you have alread
installed via the installation tool - involves copying your
"rockbox.sansa" file onto the USB-mounted partition for your device. You
don't even have to overwrite the original rockbox.sansa file that is on
there. You can call it "custom.sansa", and run it from the File menu
just once to test how it goes. When you're happy with the fix, overwrite
the original file and you're done. The current firmware detects it has
been replaced and reboots automatically.<br />
<br />
There you have it. <a href="http://www.rockbox.org/">Rockbox</a>. Totally recommended. Simple to install on supported devices,
highly tweakable, easy to hack on, and has loads of useful features. Who
thought MP3 players could do so much? :-)</div>
Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com2tag:blogger.com,1999:blog-9675303.post-2283229575621951622012-09-19T22:27:00.000+02:002012-09-19T22:27:11.506+02:00EZ Flash IV For GBA <div dir="ltr" style="text-align: left;" trbidi="on">
<br />
<div style="text-align: left;">
I've always used an ancient GBA flash cartridge that needed a
parallel port connection to work. Since it is virtually impossible to
buy a new laptop with a parallel printer port, I decided to buy a new
flash cart that worked via USB. This will save me <a href="http://quirkygba.blogspot.com.es/2010/12/changes-in-chaos-14.html">digging out my old Windows 98 laptop</a>.</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi70fNGc6RDPkb0eWiaHBg_F6AoHvGF6h_eZH70JuGQeMimj7Zdw320kV4K1Bh-nz-LMHxLkx1mq8scYHIne1DcRpBvNnFj3pfHeDJrqSutSvVGjR-DvfViiaIiOeGTxOyzSopo4A/s1600/cart-breakdown.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="136" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi70fNGc6RDPkb0eWiaHBg_F6AoHvGF6h_eZH70JuGQeMimj7Zdw320kV4K1Bh-nz-LMHxLkx1mq8scYHIne1DcRpBvNnFj3pfHeDJrqSutSvVGjR-DvfViiaIiOeGTxOyzSopo4A/s320/cart-breakdown.jpg" width="320" /></a></div>
<br />
<br />
<br />
The
idea is that you copy the ".gba" files onto the microSD card using
whatever method you like. I plugged it into a card adapter and plugged
that into the port on the side of my laptop. Hilariously Linux managed
to mount the card read-only, which was quickly followed by a lot of
searching for what could be the cause of the "mount: block device
/dev/sdc1 is write-protected, mounting read-only" message. Turns out I
had the lock switch in the "locked" position, making the card read only.
Durrr..<br />
<br />
The build quality of the cartridge is pretty bad, sadly.
The shell is a couple of bits of plastic with a slot for its own micro SD card
adapter. The microSD fits snugly into the adapter, a bit too snugly
initially as I had to give it a fair old shove to get it in there. The
adapter then fits equally as tightly into the cartridge itself. Once
it's in you need to apply a little too much force to get the adapter out
again. I'm worried something will give sooner rather than later.<br />
<br />
On
a phat DS: everything seems to work. I didn't realise this at first,
but the cartridge boots up into DS mode, from where you can select GBA
games from the menu and they boot in GBA mode.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNGIxmLxcdElolvkvnYej1dMLx04UaLmHe1rYP04v9TyesOtUXdYJQjm54fEpvyDag4yJ9sfCDlwOc34F_tUTp22OyrE4Lf1xhaxk6AqRr_9QeuUAwkamMcOvGlSlRbNIQQJQglg/s1600/IMG_2831.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNGIxmLxcdElolvkvnYej1dMLx04UaLmHe1rYP04v9TyesOtUXdYJQjm54fEpvyDag4yJ9sfCDlwOc34F_tUTp22OyrE4Lf1xhaxk6AqRr_9QeuUAwkamMcOvGlSlRbNIQQJQglg/s320/IMG_2831.JPG" width="320" /></a></div>
<br />
<br />
On
a GBA SP: everything works too, though my "GBA Rogue" port didn't
launch :-( I tried a new build of <a href="https://sites.google.com/site/gbaremakes/home/emulation">PocketBeeb</a> I've been semi-working on
and that <em>did</em> boot on the GBA and DS, so I think perhaps it is a problem with
really old homebrew. I also tried an English-patched ROM of Fire Emblem
6, and that worked too. Launching large games takes a while though - I
guess this is because they get copied from the microSD onto internal RAM
that the actual GBA reads. When I say a while, it takes maybe 10-20
seconds.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirccn6RhpmaRpBFgpqgrGjawm7jrv8ijo1HlF6nT9n8yvfdxjNlyMiQkQ3w4NrmzPUoZpvNTQ7NdVKZ3Izy9pnfaMOjyrWaSmvswnDMP7S1wg-LQv9MaYQK9i_6BEakTqnR9YusA/s1600/IMG_2832.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirccn6RhpmaRpBFgpqgrGjawm7jrv8ijo1HlF6nT9n8yvfdxjNlyMiQkQ3w4NrmzPUoZpvNTQ7NdVKZ3Izy9pnfaMOjyrWaSmvswnDMP7S1wg-LQv9MaYQK9i_6BEakTqnR9YusA/s320/IMG_2832.JPG" width="320" /></a></div>
<br />
<br />
The
cart boots up into Chinese on the GBA the first time you run it, which
threw me a bit. The fourth option down changes the language to English
though. One thing I'm not sure about is what the point of overwriting
the flashcard "NOR RAM" is - I think this is similar to the old-style
GBA carts, but all it seems to do is corrupt the main menu.<br />
<br />
Saving seems to work OK too.<br />
<br />
Ah,
just tried <a href="http://www.zincland.com/powder/index.php?pagename=release">Powder</a> 117 on the DS - it doesn't boot there, but it did
boot on the GBA SP. So there are some compatibility problems with
homebrew games it seems. Unless Powder does something odd on start up,
like checking the hardware type, causing a crash (I don't think it does
though). I might try building it from source with a newer devkitARM, see if that fixes things.<br />
<br />
All in all, not too bad. Better than having to use the
smaller capacity, slower and obsolete parallel-port based flash
cartridge that's for sure. Being able to load multiple GBA files is a
bonus - the only way to do that on the old cartridge was using pogoshell
(on Linux), FTP-ing the file over to the Windows 98 machine, then
writing the ROM there with the special software. "Clumsy" is the word.<br />
<br />
This new cart was a little pricey mind, costing €35 with a 2Gb card -
although the older GBA cart I cost me more back in 2001 I'm pretty sure -
but nowadays you don't have much choice about where to buy this stuff. I
got this one from r4ds-ds.com and it took about 2 weeks to arrive from
Hong Kong to here in Spain with the free shipping option.<br />
<br />
<br />
<a href="http://filetrip.net/nds-downloads/flashcart-files/download-ez4-client-2009-04-03-f4753.html" rel="nofollow">Here is a link to the latest firmware</a><br />
<div>
<br /></div>
<div>
<div>
<a href="http://ezflash.sosuke.com/viewtopic.php?f=12&t=17835&sid=aa830a57233c33e5b6d4a093177bc601" rel="nofollow">Here is a link to a forum post with some helpful information</a></div>
</div>
<br />
</div>
Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com0tag:blogger.com,1999:blog-9675303.post-22657232828595066562012-07-31T21:45:00.001+02:002012-07-31T21:45:00.710+02:00Why Some Remakes Are No Longer Available<div dir="ltr" style="text-align: left;" trbidi="on">You may have noticed that some of the remakes I wrote are no longer available. Here's the deal...<br />
<br />
Back in April I received an email from Mike Singleton - of "Lords of Midnight" fame - asking me to take down the 2 remakes of his games that I had ported to Android. I've had the <a href="https://sites.google.com/site/gbaremakes/">Game Boy Advance versions of these</a> up for some years but now Mike is creating an iOS version and it's understandable that he wants exclusivity of his own work - Android is too close to home here. A bit of a shame, but there you go.<br />
<br />
In his email, he points out the following:<br />
<blockquote>A word of advice also - it seems you have also made some versions of Elite. I know for a fact that David Braben is very sensitive about his copyright in this, so be very careful.</blockquote>In order to avoid any more problems I decided to pull down my Elite remakes too. In fact it felt good to know that I wouldn't see any more support emails asking for bug fixes ;-)<br />
<br />
I believe that GBA and Nintendo DS remakes have flown under the radar as they are niche platforms. Android and iPhone are higher profile since they are mainstream and seem to be more "legit".<br />
For example, in order to run homebrew on the GBA/DS you already need a piece of hardware that is associated with unauthorized copies of Nintendo games. Whereas the same remakes are easily downloadable by anyone for free from the app store without any extra hardware.<br />
<br />
As it stands if I use the material from the original games (graphics, models, game data), then it is a textbook copyright infringement. The rest is then a matter of time until the copyright holder happens to notice and asks me to take the game down. I think changing art assets, place name text and not naming it the same as the original are a minimum for this not to happen. But then a remake loses its charm. Plus I'm pretty crap at art anyway :-)<br />
<br />
The current status is that I've left my "Chaos" remake up on the Android store, plus the GBA remakes whose copyright seems to be in a state of limbo. I don't think anyone would care about the rights to Castle Master anymore, and Cyclone's author was last seen designing toys for Fisher Price. <a href="http://en.wikipedia.org/wiki/Julian_Gollop">Julian Gollop</a> has been quoted as saying he has released his early games to the public domain, so Chaos should be OK. He is still actively creating new games - I bought the <a href="http://www.metacritic.com/game/3ds/tom-clancys-ghost-recon-shadow-wars">rather underrated Ghost Recon</a> game on the 3DS that he produced - so maybe even this is risky.<br />
<br />
Anyway that's the story. At least I can say "it was all my own fault", not like poor <a href="http://simianzombie.com/?p=2277">ant512 who recently had to pull down his Earth Shaker remake</a> - he sensibly asked permission from the original author - because the Boulder Dash copyright holders don't want anyone to make a 2D game involving dirt, rocks and diamonds but them.</div>Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com1tag:blogger.com,1999:blog-9675303.post-19888284040242384132012-02-22T22:26:00.001+01:002012-04-20T08:18:49.422+02:00On Doomdark's Revenge<div dir="ltr" style="text-align: left;" trbidi="on">According to my records today marks 8 years to the day since I released my GBA remake of <i><a class="zem_slink" href="http://en.wikipedia.org/wiki/Doomdark%27s_Revenge" rel="wikipedia" target="_blank" title="Doomdark's Revenge">Doomdark's Revenge</a></i>. A few people have asked me "are you going to release an Android port of your remake?" - to mark the anniversary the answer is <b>yes!</b> and <strike>here it is</strike>! [Edit - or rather, there it was. I have removed these remakes at the request of Mike Singleton himself, who is working on his own Android versions]<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUJo5g3pt5frs8C7iTvW0K8L-V804rr4QExl-BHW-DuPzsSMrMAIhBEhz9_SbdjuqWHdNZ21wGAQ4S_wErKnvRZXiQE1vnMmDy2IO1sIcFOyC53r00swS7nvAmDYv7KSjvSdDEsQ/s1600/device-2012-02-22-211359.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="213" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUJo5g3pt5frs8C7iTvW0K8L-V804rr4QExl-BHW-DuPzsSMrMAIhBEhz9_SbdjuqWHdNZ21wGAQ4S_wErKnvRZXiQE1vnMmDy2IO1sIcFOyC53r00swS7nvAmDYv7KSjvSdDEsQ/s320/device-2012-02-22-211359.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">"Is that Don Quijote?" asked my wife</td></tr>
</tbody></table><br />
In addition to an Android port, I've gone back and fixed several show-stopping bugs that were in the GBA remake. The updated GBA version is <strike>on <a href="https://sites.google.com/site/gbaremakes/home/downloads">my remakes site</a></strike>.<br />
<ul><li>Lords artificial intelligence is no longer completely broken</li>
<li>Several crash bugs fixed</li>
<li>The game is faster (and smaller) thanks to using the right compiler flags</li>
</ul>In the Android version I've changed the controls slightly compared to the original LOM remake. In particular, Google has now deprecated the Android menu button. I don't think this means they'll send someone round with a screwdriver to pry it off your old HTC Desire or whatever, but that we developers should stop using it. Up until now I'd always used Menu like the GBA Start button, but seeing this trend I didn't use it here and I've gone back to my LOM remake and removed the use of Menu there too. I don't think anyone will really miss my poor use of the Menu button, it was always a bit of a mystery what it was going to do.<br />
<br />
While working on this, I spotted a bug in <strike>The War of the Solstice</strike> that caused it to crash on versions of Android prior to 2.1. Both remakes share a lot of common Android Java code, so fixing this in one remake also fixed the other. <a href="http://android-developers.blogspot.com/2010/07/how-to-have-your-cupcake-and-eat-it-too.html">The lazy loading technique described in this blog post</a> makes supporting older versions much less hassle.<br />
<br />
In the near future, I am going to update the source code downloads on my GBA remakes site so it reflects the latest versions of everything. One thing at a time.<br />
<br />
Back to that AI bug... A keen gamer brought it to my attention back in 2009, but I was busy doing other stuff at the time. Here's what he had to say:<br />
<blockquote>However the AI seems not to work correctly. Using the Spectrum version thelords would usually catch up with their liege or head for their foe or weapon. Using your version there is no Anvildrak, Imgorarg or Kahudrarg heading for Luxor and I have yet to see any pair or group of lords. Instead I've seen several single lords right next to the Frozen Wastes.</blockquote>At the time I wrote back saying that the bug was probably in the code that decided which way a CPU-controlled lord moves, but I didn't investigate further. Now I fired up <a class="zem_slink" href="http://www.gnu.org/software/gdb" rel="homepage" target="_blank" title="GNU Debugger">GDB</a> and stepped through the AI code. At the same time I also stepped through a suspiciously similar looking bit of Z80 assembly in the original game using <a href="http://fuse-emulator.sf.net/">fuse</a>'s built-in debugger. After comparing notes I immediately saw what the problem was - instead of going <i>towards</i> their targets, my code was sending the lords <i>away</i> from them! What a mess-up, but the fix was simple.<br />
<br />
Another "bug" in my remake was a kind of meta-bug. Instead of compiling the code with optimizations on, I had compiled with gcc's defaults. This meant the 2004 remake was much larger and slower than it should have been. The binary came in at over 100kb! This new version is 77kb big - still over twice as much as would have fit in the Speccy's RAM you'll notice - and noticeably faster.</div>Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com5tag:blogger.com,1999:blog-9675303.post-17262712730717522532012-01-21T22:38:00.000+01:002012-05-03T08:27:57.146+02:00How to recruit on LOM<div dir="ltr" style="text-align: left;" trbidi="on">
I've had an email about how to recruit on my [edit - no longer available] Android Lords of Midnight remake - "the War of the Solstice". That means other people are probably stuck too and haven't asked. Here are the basics.<br />
<br />
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.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge6do7F82yI8KWJBpf5A5H4HkumhdOdv2dHgnpUTy2CeUhjfEcre0O6aU3ZryM9GHBLRoznYG9rWnH9Ipyf42AOBPGM6ySVj5YJvhKZknpXs55mZq53QT-4uOFlxfwkc3jQ0x97w/s1600/lom-main.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge6do7F82yI8KWJBpf5A5H4HkumhdOdv2dHgnpUTy2CeUhjfEcre0O6aU3ZryM9GHBLRoznYG9rWnH9Ipyf42AOBPGM6ySVj5YJvhKZknpXs55mZq53QT-4uOFlxfwkc3jQ0x97w/s320/lom-main.png" width="320" /></a></div>
<br />
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.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtCDa6TncuNwwsW_vSCmt00X0InSJTrCNnBOeQMoAQoD9K6eiBIZUU688DXA8COGWcFO39JRjORbOdbvt5b9cW5CJHmiMeYlPulEW8cyXfXEf1XIBoxk9_Q27UGcyHggb7CQNKHQ/s1600/lom-right.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtCDa6TncuNwwsW_vSCmt00X0InSJTrCNnBOeQMoAQoD9K6eiBIZUU688DXA8COGWcFO39JRjORbOdbvt5b9cW5CJHmiMeYlPulEW8cyXfXEf1XIBoxk9_Q27UGcyHggb7CQNKHQ/s320/lom-right.png" width="320" /></a></div>
<br />
On this screen, touch the right hand part of the text. This brings up the "Seek" screen, where you can do the recruiting.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzRvftOpF6J14fLQhbPcTHwjQNFchJVsoet7oQMLtD97Qv0P-BTuX27Y6iMk8t6RqkJEoa8T1C93HLx0FhVTVH1upUTUmzbKS9eXF3yPue9o9gEo7SCUldJjVLZ0N45nRZDb8Miw/s1600/lom-recruit.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzRvftOpF6J14fLQhbPcTHwjQNFchJVsoet7oQMLtD97Qv0P-BTuX27Y6iMk8t6RqkJEoa8T1C93HLx0FhVTVH1upUTUmzbKS9eXF3yPue9o9gEo7SCUldJjVLZ0N45nRZDb8Miw/s320/lom-recruit.png" width="320" /></a></div>
<br />
On here, touch the option to recruit the Lord of Shadows. That's it!</div>Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com1tag:blogger.com,1999:blog-9675303.post-86813768323832934692012-01-13T22:28:00.000+01:002012-01-13T22:28:45.297+01:00Silly Predictions For Android Versions In 2012<div dir="ltr" style="text-align: left;" trbidi="on"><span class="zemanta-img separator" style="clear: right;"><a href="http://commons.wikipedia.org/wiki/File:Android_chart.png" style="clear: right; display: block; float: right; margin-left: 1em; margin-right: 1em;"><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" /></a><span class="zemanta-img-attribution" style="clear: both; float: right; margin-left: 1em; margin-right: 1em; width: 300px;">Image via <a href="http://commons.wikipedia.org/wiki/File:Android_chart.png">Wikipedia</a></span></span>Last week Google released the <a href="http://developer.android.com/resources/dashboard/platform-versions.html">latest numbers with the percentage of each Android version accessing the Android Market</a>. 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.<br />
<br />
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 <a href="http://www.archive.org/web/web.php">Wayback Machine</a>. I've lumped minor releases together, so 2.3.1 and 2.3.2 are in the 2.3 bucket.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfB5CvuAw80ZdfaExzMPstB-y5T3azW2oXb-8ivaqrmeB-x2Tf6DEa186E_pRJlriyBIMA1WRndY5C4H8Vp3MxK6GXt_LSxCtA_V8s7ftzlp2ypsrM9HH5pva59atbSmKSVjUy2g/s1600/android-versions.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfB5CvuAw80ZdfaExzMPstB-y5T3azW2oXb-8ivaqrmeB-x2Tf6DEa186E_pRJlriyBIMA1WRndY5C4H8Vp3MxK6GXt_LSxCtA_V8s7ftzlp2ypsrM9HH5pva59atbSmKSVjUy2g/s1600/android-versions.png" /></a></div><br />
<br />
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.<br />
<br />
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.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAQIQUM1adM3mHOFzwvMXE2wHrJ_E-NGjGpRytuoFmGRdDXILXWMLWY9DscK3rwjAtxQao_x5wBnFWWzI6LDUVoeMucA8-PoVGBKI-EW8wcL8GMhjH_X5qgk4R7limVt639-Lm0Q/s1600/android-versions-future.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAQIQUM1adM3mHOFzwvMXE2wHrJ_E-NGjGpRytuoFmGRdDXILXWMLWY9DscK3rwjAtxQao_x5wBnFWWzI6LDUVoeMucA8-PoVGBKI-EW8wcL8GMhjH_X5qgk4R7limVt639-Lm0Q/s1600/android-versions-future.png" /></a></div><br />
<br />
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.<br />
<br />
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 :-)</div>Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com0tag:blogger.com,1999:blog-9675303.post-33924863928581753952011-11-27T21:32:00.001+01:002011-11-27T21:33:06.683+01:00Non-ARM Android Apps<div dir="ltr" style="text-align: left;" trbidi="on">I've had 2 requests now for my Lords of Midnight remake on x86-based Android devices. A while ago <a href="https://github.com/richq/scons-android/commit/f86dfd159daf4b49370d769279e2fea8c2a677ed">I updated the scons-android build system I use to support multiple architectures</a>, 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.<br />
<br />
<br />
Back in July, <a href="http://android-developers.blogspot.com/2011/07/multiple-apk-support-in-android-market.html">Google added multiple APK support to the Market</a>. 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.<br />
<br />
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 <i>does</i> 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".<br />
<br />
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.<br />
<br />
With this in mind, I've uploaded a new version of <a href="https://market.android.com/details?id=war.of.the.solstice">War of the Solstice</a> and <a href="https://market.android.com/details?id=chaos.app">Chaos</a> 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! ;-)<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfaIvZvd52sYJ2lKMJEcTWPGn9xIhOpc1OuauGe4gY6BO8lLCgwVUwEJMgpEu5t5Z8RFkjNiHnzE3pOB8DSHq1KJREpVdAWcBEXK5WPiKE2doTUAA0LrvLMi5cB91baZr-jyY0sA/s1600/upload-chaos-x86.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfaIvZvd52sYJ2lKMJEcTWPGn9xIhOpc1OuauGe4gY6BO8lLCgwVUwEJMgpEu5t5Z8RFkjNiHnzE3pOB8DSHq1KJREpVdAWcBEXK5WPiKE2doTUAA0LrvLMi5cB91baZr-jyY0sA/s1600/upload-chaos-x86.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Screenshot of the strange Android Market upload warnings</td></tr>
</tbody></table>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 <i>and</i> 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.</div>Richard Quirkhttp://www.blogger.com/profile/16290285494071462742noreply@blogger.com0