2011-08-02

Windows XP End of Support Countdown Gadget

Windows XP End of Support Countdown Gadget The Windows XP End of Support Countdown Gadget gives you a nice countdown until Windows XP, and, more importantly, IE6 will actually finally be unsupported.

It, however, leaks memory. A lot of memory; about 1kb/second. Noting that it's running all the time, and not important, this is rather inconvenient.

FTFY. Can't redistribute a patched "binary" as the original is not redistributable.


2011-06-05

Java stacktraces straw man

It's a sad fact of life that many developers spend a good deal of time staring at stack traces.

My personal favourite situation is when you get to:

Exception in thread "main" java.lang.NullPointerException
    at com.goeswhere.dmnp.linenos.B.foo(B.java:13)

..and, line 13 is:

  System.out.println(first.substring(1) + second.toUpperCase() + third.toLowerCase());

Basically, the end of any happiness.


LineNos can fix this:

$ java -Xbootclasspath/p:linenos.jar -javaagent:linenos.jar=com/goeswhere com.goeswhere.dmnp.linenos.B
Exception in thread "main" java.lang.NullPointerException
    at com.goeswhere.dmnp.linenos.B.foo(B.java:13), attempting to invoke toUpperCase #4
    at com.goeswhere.dmnp.linenos.B.run(B.java:9)
    at com.goeswhere.dmnp.linenos.B.main(B.java:5), attempting to invoke run #2

This is implemented entirely as a Java Agent; it requires no VM modifications and is portable anywhere that supports instrumenters transforming classes (i.e. everywhere that matters).


It works by adding extra line numbers for each call on a line. Currently it adds call-number*1000 to the line number, so that it's debuggable and easier to do in two phases, but this makes it much less efficient.

i.e., assuming Java allowed labels for line-numbers, it does:

13:
8013: System.out.println(
1013: [secret StringBuilder construction (used to implement String concatenation)]
2013: first.substring(1) 
3013: +
4013: second.toUpperCase()
5013: +
6013: third.toLowerCase()
7013: [secret StringBuilder#toString()]);

Thus, the real stacktrace looks like:

Exception in thread "main" java.lang.NullPointerException
    at com.goeswhere.dmnp.linenos.B.foo(B.java:4013)
    at com.goeswhere.dmnp.linenos.B.run(B.java:9)
...

It additionally overrides StackTraceElement#toString() to decompile the named class and report the invocation that's on that line, i.e. lookup line 4013 in the above bytecode, and report that it's an invocation of toUpperCase, thus giving the intended result.


It has no run-time performance penalty beyond the extra time to load classes, and the increase in the size of line-number table (actually, I have no idea how this affects performance, but I can't imagine it's much). Printing a stacktrace is slower, however (although, it probably wouldn't be much slower in a real implementation). Also, it's a straw-man, so leaks memory, but this isn't an important part of the implementation.

A much better implementation would be to store the [Class<>, line-number] -> hint mapping instead of the whole file and doing decompilation; or to replace the entire line-number table with a bytecode number table (i.e. 1->1, 2->2, 3->..), and do it all at print-time. Patches welcome.


In summary: Dear Oracle, please make the JVM do this by default. Lots of Love, Faux.


2011-05-25

The Goat Inventory Tracker

The year is 1516. The Royal Mail has just been founded.

You're an enterprising goat farmer. You want to service requests for goats by mail. You have multiple paddocks. Paddocks contain multiple goats.


one of the only two cute goat photos on the entire internet, (c) 2011 abbsworth, used without permission

An order comes in for some goats. You spring into action!

Firstly, you need to select some goats to send out.


For this, you've designed a tool called the Goat Inventory Tracker. It deals with all the management aspects, so you can do what you love most; breeding goats.

You decree, Goat Inventory Tracker, Allow Me To Pick From My Goats!

The Goat Inventory Tracker shows you each of your goats across all of your paddocks, and asks you if you would like to include it. If you do, it takes the goat and places it in a pending crate.

When you're done selecting goats, you can look into the pending crate and check everything is what you want. If it helps, you can preview your shipping log as if you had no outstanding goats.

This is important, as you're required to maintain various arbitary constraints by the local land baron.


the other only cute goat photo on the entire internet, (c) 2011 Loredana Preston, used without permission

Now that you're happy, you can decree Goat Inventory Tracker, Seal This Box!

This will, obviously, seal the box of goats, and place it near the post box with a shipping note of your choice.


You repeat this procedure for a couple of days. During this time, loads of boxes pile up near the mail point.

You don't like mess.

You decree, Goat Inventory Tracker, Allow Me To Rearrange My Boxes!

You are then able to reorder, change the shipping note of, merge, and completely change or split your boxes.


Postman Pat, Postman Pat, Postman Pat and his black and white cat.  EARLY IN THE MORNING, JUST AS DAY IS DAWNING...

Once you're happy with your outstanding orders, you can decree Goat Inventory Tracker, Summon The Postman!

The postman will arrive, and will then check he can load your boxes into his wagon. Due to safety concerns, the postman isn't allowed to pile your boxes on top of other people's boxes, or allowed to re-order other people's boxes. This means that if he has any boxes in his van already, you'll need to do some work first.


No worry; you just decree Goat Inventory Tracker, Pile My Boxes Atop These Lowly Boxes! It will.

Sometimes your boxes won't fit nicely on top of the other people's, at which point the Goat Inventory Tracker will panic, and you'll need to reshape your boxes. Remember that the Goat Inventory Tracker has many tools for dealing with boxes, as explained above.

Once you're done piling your boxes, the postman will be happy and will leave with your boxes, and you have entered them into your account book.


You've made some money, you've made your customers happy, and you've done basically no work. Excellent. Back to breeding goats.

Continue reading...


2011-04-22

Tiny Windows utilities

I have a set of tiny utilities that I use on a daily basis but have never bothered to release.

Updated: The binaries are on github releases, and also a local mirror: tinies v002 archive.

All are in the tinies v001 archive, in both x64 and legacy format. Symbols, source and signatures are available. No installer is available; just drop them into your All Programs -> Startup folder.


shiftfocus.exe adds an extra set of hotkeys for focusing windows. Ctrl+win+arrow focuses the window to that side of the current window.

This makes the most sense with Aero's Snap turned on. If you have two windows "half-maximised" on a screen (i.e. one has been win+left'd, and the other win+right'd), then you can switch between them using ctrl+win+left and ctrl+win+right.


topkey.exe adds win+w to toggle a windows' always-on-top flag, and win+returnctrl+win+return (as win+return is stolen by accessibility from Win7) to create a new command prompt "in the current directory". (This works for Explorer windows, and things that have the directory at the start of the title, i.e. Notepad++.)


mousex.exe allows you to use an xbox360 controller as a mouse. Different analogue sticks are different sensitivity. A/B for left/right click. Shoulder analogue controls for the scrollwheel.


And, for more niche users:


powerstatustray.exe shows which drives are spun-up, and notifies you when a drive spins up or down. (Yes, actually, this one was released before.)


keydump.exe shows what you can keylog by binding globally to DirectInput. Most keylogging preventers/detectors completely ignore this, and/or only work through blacklisting, which is laughably pointless. It doesn't bother translating numbers into keycaps, but it's obvious whether it's working and whether it's been detected.


Others, to date:
  • aukiller: Legacy XP application.
  • foobar2000-loader.exe: Demo of pre-loading a dll into an application via the debug api.
  • keytoputty.exe: Take input and send it to a running instance of putty, i.e. to allow input during full-screen applications.
  • loaddlls.exe just calls LoadLibrary on all it's arguments.
  • noelev.exe: Legacy implementation of setting __COMPAT_LAYER=RunAsInvoker.
  • quickkey.exe: Legacy XP application.
  • unrequireadmin.exe: An even less healthy implementation of noelev.exe.


2011-04-11

Sometimes people really do just want to help...

Late last year we were playing TrickyTrucks.

TrickyTrucks is okay fun single-player, but what really makes it fun is the competition. For this, it has built in scoreboards, per track. Attempting to beat certain people's times on tracks is the fun.

What it lacks is a cross-track scoreboard, i.e. some kind of championship, and/or notifications of people beating your scores. Even Audiosurf, one of the... most entertainingly engineered indie games recently, got this right.

I implemented one.

After some initial beta testing (and ensuring I was near the top of the championship), I messaged the TrickyTrucks author with the source of the scraper and of the web interface, asking for permission to link to the website on the official forum, so others could join us in competing for the championship title.

An aside, on licensing: Both of these components were released under the BSD. That allows anyone, including the TrickyTrucks author, to use the code for any purpose, including incorporating it into his official website. The component split was done such that there was a neat interface for him to implement on a non-scraper backend. The best result for me would be for there to be an official API and an officially hosted version of the site, such that I never had to do anything ever again to continue appreciating it.

An aside, on development costs: Reverse engineering binary protocols is a nightmare. Especially so with only access to a read client (with no source). Especially so when there's no way to get the server to return things consistently or with user-specified plaintext. Especially when the protocol has (what you believe to be) NIH compression. Don't ever, ever try and pay someone to do this unless they really, really want to.

He replied that this would be fine, but only if I removed the link from the website to the source. I, grudgingly (given it was already in the wild), did so and posted on the forum.

His response? Delete the post, and change the server to have some additional, weak protection against 3rd-party clients.

What. The. Hell.

(Eventually he sent me details of an API to use, but I'd lost interest by then.)


This post brought to you by libspotify being incompatible with most 3rd party DLLs, probably due to the copy protection on their DLL. Copy protection. On something that requires a paid account, verified against their server. Please tell them what you think about this on my GetSatisfaction thread (apparently this is what passes as a bug tracker these days).

This prompted me to waste ALL WEEKEND porting foo_input_spotify to libdespotify. foo_input_spotify will increase the value of their product. Why are they making my life miserable? Perhaps it's unintentional. Time will tell.


2011-04-07

History cleanliness in git

This post is for documentation only. It was going to be a rebuttal to jwh's Mercurial fanboyism but I realised while writing it and re-reading his post that I have absolutely no idea what he's talking about, nor can I work out how to get hg to tell me.

Given a repo of:

My proposals for alternatives to this simple workflow are as follows. These all result in the same order of code going into the master branch, but have different histories. (Actually, I think there's still mistakes in there but I'm tired of staring at the horrible procedural script that generates it, so it'll do).

1. A flat history, made by rebasing everything on top of master instead of merging:

2.Only merges on master, giving you the illusion of a neat history...

...but, underneath, loads of ugly information available:

3. A hybrid, supercommits, whereby you keep a flat history but you maintain where branches were:

...or, with the history information visible:


Thoughts:

Serious concurrent projects like git itself use the 'only merges on master' approach. I strongly agree that they shouldn't be flattening the history; it's nice to be able to see groups of patches as they go into master, and to navigate the history of "feature commits", instead of the history of "developer changes".

The flat model seems to work much more like how I think about software development:

  • You start working on something.
  • You do your normal develop, commit, developer-test, commit cycle.
  • Master moves on a bit while you're messing around. The fact that you happened to start developing before a specific commit on master, instead of just after it (so it would be the root of your branch) is reasonably irrelevant; you may as well move the branch-root (or branch point) up to the top of master.
  • Additionally, if you do a real merge, you need to test your changes. This leads to more developer testing, and possibly more commits.
  • What do you do with these commits? Assuming your merge with master is still local you can fix it (this is git, you can fix anything), but it's inconvenient.
  • When you've rebased, you can continue committing on your rebased branch like normal, with confidence that when you merge it'll all be fine (as it'll be a fast-forward merge).

'Supercommits' is a hybrid of these two; you can use the rebase-onto-master workflow from 'flat', but you can logically group your set of commits into a... family? I like this idea, but haven't really implemented it in practice so can't really comment.

(Apologies for screenshots of text; I'm lazy, ansifilter was NOT WORKING and it's prettier than gitk.)


« Prev - Next »