Monday, December 31, 2012

Happy new year New Zealand

Happy new year to you all down there in Hobbit land!
You are by far the biggest consumer of my monologue in 2012 and I am honoured that you keep on reading.
Have a good one!

Fiscal cliff or the hill of empire?

The developed world faces financial crisis after financial crisis because the majority of inhabitants of these countries have a buy-now-pay-later attitude. Our love of cheap luxury and the ease at which we can get credit from banks now has most of the developed world held hostage to debt and, simply to maintain our tenuous position in life, we have to continue the cycle of earn and spend just a little more more than we garner.

The sub-prime mortgage crisis that pushed the world into its most recent major depression is an example of how living beyond ones means is a recipe for disaster. House repossessions and the resulting reduction to poverty of people that were just holding on to a standard of living has worsened the situation because the poor will always accept short-term and high-interest credit and there will always be a banker willing to tread another face into the dirt for a few pennies.

Fairly soon, certainly within the lifetime of my children, if not my own, I predict civil unrest and revolution in the western world where the number of people who are forced into poverty by unscrupulous banking practices will far outweigh the capabilities of those who have the power to enforce order. The resulting battle will drag what we like to think of as civilisation down into a place where we will be dominated by the new world superpowers of the east and Africa. Given the abilities of the inscrutable easterner to ignore human rights for their version of the greater good, that does not bode well for the west.

The empire of the west has passed its zenith and is in decline. It can no longer enforce dominance of its holdings and the heavy industry that it has lost for the cheaper options of its poorer neighbours has weakened it. People in the west believe that they have a god-given right to food and luxury, just as the Egyptians and the Romans did before their empires crumbled and the man in the street is more concerned with his own petty needs than the needs of his empire and so they make demands on the government asking "Why have you not provided for me?" at the same time as telling the government "You cannot tell me to do things I don't want to do! Let the slaves do it!" This leaves the Emperor in an untenable situation and he will eventually be deposed and the empire will fall.

Empires fall because of two things. Firstly, the empire expands to hold more territory than it can control given the resources it has to hand. Secondly, the empire farms-out much of its heavy industry to lesser powers that adopt it to improve their own lot. Developing a heavy industry is a business that goes hand-in-hand with empire because the Emperor must have ships for his troops and supplies and more importantly, the Emperor must have the best weapons for his troops. As soon as everyone else has those weapons and everyone else understands the technology, all advantage is lost and the empire will crumble.

Empires rise because of frontiers. Those who have the ability to breach the frontier become the next superpower. For the Egyptians, the frontier was how to feed millions. For the Romans it was how to move men and supplies fast and far, for the British it was how to mechanise an entire continent and the western world we have today is a holdover from that empire. The English Industrial Revolution laid the tracks upon which the entire western empire was able to expand and America, for all its denial of British governance is as much a product of the British Empire as Tony Blair was a product of Margaret Thatcher.

There is only one possibility for the Western Empire to survive and to grow. We, Europe and the United States must pull in all of our resources that are using up credit that we cannot pay back and from where we will be forcibly evicted if we don't act now. Foreign aid is a big drain and most of the people who receive it laugh at us behind our backs. It is obvious that unless we are willing to become what we despise, that is to say bloodthirsty dictators who crush all in our path, we can never hold on to the outskirts of our empire. We must stop giving not only our cash in hand but also all our credit business to foreign powers like China and Africa and hunker down to create jobs in heavy industry here at home, in the west to feed our own and to look after our own interests. If this doesn't happen, our daughters or granddaughters might be the victims of forced sterilisation and our sons and grandsons the indentured slaves of the new Mandarin and Saudi princes.

Where can an empire discover a new frontier to breach? The only way is up! The society that owns the high ground also owns the low. Getting out of Earth's gravity is hard and anyone running up a hill can be knocked down by a rolling log cheaply and easily. If you are first to the top then you win. If you're running up after someone else then you will loose! its as simple as that.

If you want your grandchildren to be on the high-society side of the new empire then you must push them to build the heavy industry of space. The United States Congress have consistently fiddled with foreign policy and holding on to empire while the Rome that was their space industry burned and crumbled before their eyes. They have given away the marvels of western technology by allowing cheap eastern labour to build our gizmo's and learn all our secrets without actually paying for the research. As a consequence our subjects of empire are soon to be more powerful than us.

Bring heavy industry, jobs and prosperity home to the west. Stop paying our enemies to build their armies against us, stop helping them to dominate our children and our grandchildren. Lift your children and grandchildren to the top of the next hill that Mankind must conquer. Lift them into space!


Saturday, December 29, 2012

Epson Printer software chip resetter.

My own war against printer manufacturers is on record. What about the vendors of so-called resetter software however?

The software provided by this site may or may not work - but BEWARE!!!

To obtain the download you need to sign up for a recurring SMS service with a WEEKLY 5 euro or 8 dollar fee. These services are ultimately difficult to stop once they have your details and are usually bogus and fraudulent themselves.

I suggest that if you can't find a chip resetter on ebay or build one yourself then do not go with this. It's a scam that will cost you more than buying a new cartridge.

Friday, December 21, 2012

Good guys with guns stop bad guys with guns...

http://www.bbc.co.uk/news/world-us-canada-20815130

Regarding Wayne LaPierre...

Uh, sorry, you asshole, where were all the good guys when those bullets ripped through the brains of those poor little kids? Where was all your rhetoric and bravado? You were probably sitting on the can or scratching your arse when all the real pain in the world was happening.

What gives a turd like this the right to pontificate on the merits of guns when the very thing that he defends is so patently and demonstrably beyond his control?

Wayne LaPierre, like all NRA fanatics is a cowardly piece of shit who has never had to face the reality of the tool that he so proudly espouses. If his babies or grandchildren had been massacred he would sing a different tune but sitting aloof in his place of tranquility and calm he can dispense his "wisdom of the gun" so that you can all bask in his self assured glow. Curse him.


Thursday, December 20, 2012

Taking back your neighborhood, by hacking.

My sister in law just posted on Facebook that she had returned to her car to find the window smashed and a "very nice man" nearby who, miracle of miracles, just happened to be a car-window repair man with all the kit he needed in the back of his van. This clown tried to charge her seventy five pounds or over a hundred dollars to repair the window. Last year she suffered injury when someone in her neighborhood threw a half-brick through her window as she was driving along. All this is a town where I grew up and have happy memories of it being a nice place where people would stop and help if you broke down, not rob and burn your car.

The police in the town where my sister in law lives are useless and regularly refuse assistance to people who have been robbed or attacked. She lives in "quiet" a little place in the south of England away from the urban nightmare of rabbit-hutch living in the big towns so the scale of bad behaviour in such a place is even more surprising.

It struck me that an old Android phone with a couple of cameras and software that enabled it to control other items via bluetooth such as an engine immobilizer and remote door lockers could do a number of interesting things such as phone police while on the move to report thefts. Take photo's of occupants and e-mail them immediately to a mailbox, wait until the car stopped and lock the occupants inside, sound horns and flash lights or many many other things that would discourage second offenses.

This sounds like the kind of project that hackers who want to take back their neighborhoods from thieves, vandals and con-artists could use to good effect.Anyone interested in working on such a project?



Wednesday, December 19, 2012

Friday, December 14, 2012

Wonderful news of more school shootings. A worthwhile Christmas tradition

Many Americans shout loudly about their "Right to bear arms" as laid out in the famous second amendment to the constitution. The ridiculous thing is that the wording of the second amendment does not say that any idiot can carry a gun! It specifically and pointedly says "A well regulated militia being necessary to the security of a free state, the right of the people to keep and bear arms shall not be infringed." 

The arcane use of language that qualifies this right as for those who are members of a militia has been conveniently ignored and the interpretation placed upon the last part of the sentence, after the comma.

This is the same as saying "Unless drunk, drugged or otherwise disqualified, all people may drive a car" and then supporting the rights of drunken drivers to indiscriminately mow down pedestrians by allowing them to say "Well, it's in the constitution!" as a valid defense.

Personally I see the increased incidence of horrific mass murders by maniacs with guns as a lesson to all caring parents in the US who should call for an immediate and outright ban on ownership of a gun by anyone not actually in a federal or state organised militia in perfect line with the wording of the constitution.

Merry Christmas to all gun nuts in the USA. Keep defending your rights and with a bit of luck you will have to suffer the sleepless nights when your angst ridden teenager borrows your gun to go to the Christmas party next year. Guns don't kill people, fuck-head maniacs who have easy access to guns kill little children as a Christmas treat.


Friday, December 07, 2012

Calling all readers AGAIN!

If you'd like a cute Christmas game go over to Snowman Tag on the Play store. Download the free version and review it for me but put one special word in the review text. Then mail me your review text and the key word and I will send you an ADVERTISING FREE version of the game. The FIRST mail with the identical review text will be eligible. All others are fails...

Mail your review text to snowman at bobpowell dot net.

Why Google Play SUCKS!

I just realised today why Google Play is such a useless marketing platform. There is no NEW APP DISCOVERY!
If you're looking for Angry Birds than fine, The front page is covered with it but no new apps show up. In fact, nothing is seen if it hasn't got a half a million downloads.
At lease Apple and Amazon have a new apps feature page.
Come on Google WAKE UP!

Wednesday, December 05, 2012

Monogame running slowly?

Well, however clever you think it might be, don't bother to call GC.Collect or GC.WaitForPendingFinalizers in the game loop.

Monday, December 03, 2012

Calling all readers!

Hello,
Whether you are a new or old reader of my blog or a user of my web-site you may be aware that I am writing apps at the moment.

My game BRAINS! is in what I think of as its final version. Its fun and fast and best of all, FREE.

Can I ask you a big favour? If you have an Android phone, would you please go download my game, try it out and then do one of two things.

#1 If the game functions for you please go to the Play store and review it for me.

#2 If for some reason the game does not function or you find a bug please send me mail to zombie at bobpowell dot net and tell me which model of phone you're using and describe the problem. I will work to fix the problem ASAP. Please don't just give it a bad review because that doesn't help make the product better.

You can also place a comment on this blog which I will answer immediately.

It is incredibly difficult to motivate the end users to review the game and even failures that are not the fault of the game seem to meet with one-star reviews. One of my other apps got a negative review because it relied on the GPS and the idiot user was using it INDOORS!! Go figure.

Thanks so much for your participation! Oh, and have fun running about being chased by zombies!

Bob.


Friday, November 30, 2012

Deep and meaningful? Screw that!

Everything I've done in my career had meaning and purpose. I've designed medical systems, musical instruments, written educational software and had literally billions of dollars worth of financial trades go through code that I wrote. I've eschewed games as a waste of time and only ever written "serious" software so now I find myself in a delightful situation of having no responsibility to improve someone else's badly written crap of fix other people's magnificent cock-ups. I'm writing entertainment that has no purpose than to occupy the time of the person using the game. Wow! What a relief! All I have to do is make something look good when you blow a hole in it!!

Wednesday, November 28, 2012

Cheating at Android localization

I tried to use Google's localization tool the other day. Is it just me that finds that darned thing utterly unusable? Blimey what a palaver! Anyway. I thought that in the spirit of doing things the quick and simple way I would do another quick macro to strip out the XML.

This macro takes a Strings.xml resource, strips out all the tags, copies the text only parts to the clipboard and shuts the file without saving it. You can then paste directly into Google's translate page and copy-paste the translated stuff back in the order it was created.

Of course, if I was less lazy I would do something more useful but this works for me, especially when I add a section to an Android app and want to propagate that to all the localized files.

Anyway, FWIW, enjoy (or not)


    Sub StringsForTranslation()
        DTE.ExecuteCommand("Edit.Find")
        DTE.Find.FindWhat = "<?xml"
        DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
        DTE.Find.MatchCase = False
        DTE.Find.MatchWholeWord = False
        DTE.Find.Backwards = False
        DTE.Find.MatchInHiddenText = False
        DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
        DTE.Find.Action = vsFindAction.vsFindActionFind
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.ActiveDocument.Selection.EndOfLine(True)
        DTE.ActiveDocument.Selection.Delete(2)
        DTE.ExecuteCommand("Edit.Find")
        DTE.Find.FindWhat = "<resources>"
        DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
        DTE.Find.MatchCase = False
        DTE.Find.MatchWholeWord = False
        DTE.Find.Backwards = False
        DTE.Find.MatchInHiddenText = False
        DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
        DTE.Find.Action = vsFindAction.vsFindActionFind
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.ActiveDocument.Selection.Delete(2)
        DTE.ExecuteCommand("Edit.Find")
        DTE.ExecuteCommand("Edit.SwitchtoQuickReplace")
        DTE.Find.Action = vsFindAction.vsFindActionReplaceAll
        DTE.Find.FindWhat = "<string name="
        DTE.Find.ReplaceWith = ""
        DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
        DTE.Find.MatchCase = False
        DTE.Find.MatchWholeWord = False
        DTE.Find.MatchInHiddenText = False
        DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
        DTE.Find.ResultsLocation = vsFindResultsLocation.vsFindResultsNone
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.Find.FindWhat = """>"
        DTE.Find.ReplaceWith = """ = """
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.Find.FindWhat = "</string>"
        DTE.Find.ReplaceWith = """"
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.Find.FindWhat = "<!--"
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.Find.FindWhat = "-->"
        DTE.Find.ReplaceWith = """ /*comment*/"
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.ActiveDocument.Selection.SelectAll()
        DTE.ExecuteCommand("Edit.Find")
        DTE.Find.FindWhat = "</resources>"
        DTE.Find.Action = vsFindAction.vsFindActionFind
        DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
        DTE.Find.MatchCase = False
        DTE.Find.MatchWholeWord = False
        DTE.Find.Backwards = False
        DTE.Find.MatchInHiddenText = False
        DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.ActiveDocument.Selection.DeleteLeft(2)
        DTE.ActiveDocument.Selection.SelectAll()
        DTE.ActiveDocument.Selection.Copy()
        DTE.ActiveWindow.Close(vsSaveChanges.vsSaveChangesNo)
    End Sub

Sunday, November 25, 2012

Localizing IOS apps from Android XML strings

I have been working on an Android app that I am now transferring to IOS. As one might expect, the method of localizing the strings is different and so I wrote this Visual Studio macro to take XML string resources from my MonoDroid apps written using Visual Studio and convert them to equivalent Localizable.strings files that might be used in MonoTouch.

Enjoy.


    Sub AndroidStringsToIOSLocalizable()
        DTE.ActiveDocument.Selection.PageUp(False, 99)        DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText)
        DTE.ExecuteCommand("Edit.Find")
        DTE.Find.FindWhat = "<?"
        DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
        DTE.Find.MatchCase = False
        DTE.Find.MatchWholeWord = False
        DTE.Find.Backwards = False
        DTE.Find.MatchInHiddenText = False
        DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
        DTE.Find.Action = vsFindAction.vsFindActionFind
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.ActiveDocument.Selection.EndOfLine(True)
        DTE.ActiveDocument.Selection.Delete(2)
        DTE.ExecuteCommand("Edit.Find")
        DTE.Find.FindWhat = "<resources>"
        DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
        DTE.Find.MatchCase = False
        DTE.Find.MatchWholeWord = False
        DTE.Find.Backwards = False
        DTE.Find.MatchInHiddenText = False
        DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
        DTE.Find.Action = vsFindAction.vsFindActionFind
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.ActiveDocument.Selection.EndOfLine(True)
        DTE.ActiveDocument.Selection.Delete(2)
        DTE.ExecuteCommand("Edit.Replace")
        DTE.Find.Action = vsFindAction.vsFindActionReplaceAll
        DTE.Find.FindWhat = "<string name="
        DTE.Find.ReplaceWith = ""
        DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
        DTE.Find.MatchCase = False
        DTE.Find.MatchWholeWord = False
        DTE.Find.MatchInHiddenText = False
        DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
        DTE.Find.ResultsLocation = vsFindResultsLocation.vsFindResultsNone
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.Find.FindWhat = "</string>"
        DTE.Find.ReplaceWith = """;"
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.ExecuteCommand("Edit.Replace")
        DTE.Find.FindWhat = """>"
        DTE.Find.ReplaceWith = """ = """
        DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
        DTE.Find.MatchCase = False
        DTE.Find.MatchWholeWord = False
        DTE.Find.MatchInHiddenText = False
        DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
        DTE.Find.ResultsLocation = vsFindResultsLocation.vsFindResultsNone
        DTE.Find.Action = vsFindAction.vsFindActionReplaceAll
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.ExecuteCommand("Edit.Replace")
        DTE.Find.FindWhat = "<!--"
        DTE.Find.ReplaceWith = "/* "
        DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
        DTE.Find.MatchCase = False
        DTE.Find.MatchWholeWord = False
        DTE.Find.MatchInHiddenText = False
        DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
        DTE.Find.ResultsLocation = vsFindResultsLocation.vsFindResultsNone
        DTE.Find.Action = vsFindAction.vsFindActionReplaceAll
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.ExecuteCommand("Edit.Replace")
        DTE.Find.FindWhat = "-->"
        DTE.Find.ReplaceWith = "= */"
        DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
        DTE.Find.MatchCase = False
        DTE.Find.MatchWholeWord = False
        DTE.Find.MatchInHiddenText = False
        DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
        DTE.Find.ResultsLocation = vsFindResultsLocation.vsFindResultsNone
        DTE.Find.Action = vsFindAction.vsFindActionReplaceAll
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.ExecuteCommand("Edit.Find")
        DTE.Find.FindWhat = "</re"
        DTE.Find.Action = vsFindAction.vsFindActionFind
        DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
        DTE.Find.MatchCase = False
        DTE.Find.MatchWholeWord = False
        DTE.Find.Backwards = False
        DTE.Find.MatchInHiddenText = False
        DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
        If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
            Throw New System.Exception("vsFindResultNotFound")
        End If
        DTE.ActiveDocument.Selection.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstText)
        DTE.ActiveDocument.Selection.EndOfLine(True)
        DTE.ActiveDocument.Selection.DeleteLeft(2)
        DTE.ActiveDocument.Save("Localizable.strings")
        DTE.ActiveWindow.Close(vsSaveChanges.vsSaveChangesNo)
    End Sub

Tuesday, November 20, 2012

iPhone or Android - Which is easiest?

Objectively I find that working with the iPhone APIs, Even in the context of Mono is far simpler than Android. I guess that having complete control over the hardware enables Apple to design a cleaner and more integrated set of APIs.

Converting my game from Android to IOS has largely been a job of removing all the complicated stuff I had to do to get it to run on Android.

Saturday, November 17, 2012

Facebook offensive?

Facebook makes money by providing a free service and showing paid adverts on people's pages. This is all well and good. They also have options to hide things that you don't want to see on your page. Particularly you can opt not to look at a certain advert or to see things from certain web-sites.

It seems that I have an odd demographic. I visit a lot of tech sites, I look at a lot of up-to-date programming and technical blogs, I read nerdy stuff that young men read and so Google which I checked, and probably Facebook which I cannot check, place me in the male 23-35 demographic.

As a consequence, on my Facebook pages, I have one account for professional contacts and another for personal and family, I get an endless stream of Singles and Dating adverts. I will usually get three or four singles ads with an admittedly pretty but uninteresting girl on them when I would rather see ads for technical stuff or travel. I therefore recently tried to reprogram Facebook into not putting ads for vacuous blondes or Chinese and Ukrainian girls by hiding every dating site as offensive to my tastes and clicking on ads for Norwegian fjord cruises and techno-toys. All to no avail.

So, this beggars the question that if I have declared on many occasions that site whateverdatingthing.com is offensive to me and that I do not wish to see advertising from them again, why do they invariably pop up again three days later? Facebook obviously doesn't care a whit about what I find offensive and has no intention to respect my demands. The stupid thing is that they are turning away business because I will never click on a dating site ad where I may possibly click on one for arduino controlled helicopters.

Wednesday, November 14, 2012

Thought Leader...

Anyone who has the temerity to put this on their own profile declaration should be immediately disqualified from the position.

Tuesday, November 13, 2012

Grumpy old woman

While I agree with this seniment for drivers, giving people yet another excuse for fining, pissing off and generally controlling the minutiae of peoples lives is a bad idea and Anne Applebaum can go stuff it where se sun shineth not.

The joy of Secs.

I just had a short Twitter Conversation with Charles Arthur of The Guardian in which he complains of having to field calls from people who want to promote their sites and apps. The fact that he gets such requests is no particular surprise as his presence as a technical editor for a well respected paper and his involvement with podcasts in the tech domain is well know. What surprises me is that someone with such a profile has an easily accessible telephone number and no-one to field his calls.

When I was director of Rogue Wave Software in the US for a while, the customer base got to be rather large and I had to have someone field calls for me because my habit of answering personally began to eat significantly into my day. I imagine that anyone who is known for presenting insightful opinions to a global audience will get a vast number of distractions even if its just a tiny percentage of the audience who pluck up courage to call. The evidence of this is clearly seen in his <grrr> posting on Twitter.

My advice to Charles is to move to another desk, change phone number and have someone grab the phone before he is even aware that it rang. The world is too small and communications too immediate to expect a moments peace. It will only get worse.

Android compatibility utter nonsense!

I am in the process of fine-tuning my game and trying to monetize the free version using providers such as AdMob and RevMob. The trouble is that even though I have tested the game on two low capability machines, The Alcatel 951 and the LG E400, the Play site refuses to admit that tha application is compatible with these telephones. Consequentially, the number of devices that my game can deploy to is severely limited.

I discovered that setting certain options such as the hardware camera autofocus feature to optional increased the compatibility matrix by more than 400 devices but the Alcatel and the LG were both still excluded, even though I have solid proof that the game runs on these devices like a charm.


To set the autofocus feature I used:
  <uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />

Finally I have added optional feature requests for network location and wifi to increase compatibility to just over 2000 devices but still not my two test phones!!


  <uses-feature android:name="android.hardware.location.network" android:required="false" />
  <uses-feature android:name="android.hardware.wifi" android:required="false" />

This story is obviously set to run and run.

LATE BREAKING NEWS:
Phew, fixed it.. here is my working app manifest for simple Augmented Reality systems:



<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto" package="my.domain.mygame" android:versionCode="10" android:versionName="1.02">
  <uses-sdk android:minSdkVersion="2" android:targetSdkVersion="14" android:required="false" />
  <application android:label="mygame" android:icon="@drawable/icon" android:name="mono.android.app.Application">
    <activity android:name="com.google.ads.AdActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" />
    <activity android:name="com.revmob.ads.fullscreen.FullscreenActivity" android:configChanges="keyboardHidden|orientation" />
    <activity android:alwaysRetainTaskState="true" android:configChanges="keyboard|keyboardHidden|orientation" android:icon="@drawable/icon" android:label="mygame" android:launchMode="singleInstance" android:theme="@style/Theme.Splash" android:name="mygame.MyGameActivity" />
    <activity android:label="@string/instructions" android:name="mygame.instructions" />
    <activity android:alwaysRetainTaskState="true" android:configChanges="keyboard|keyboardHidden|orientation" android:icon="@drawable/icon" android:label="mygame" android:launchMode="singleInstance" android:theme="@style/Theme.Splash" android:name="mygame.MainActivity">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>
    <provider android:name="mono.MonoRuntimeProvider" android:exported="false" android:initOrder="2147483647" android:authorities="my.domain.mygame.mono.MonoRuntimeProvider.__mono_init__" />
  </application>
  <supports-screens android:resizeable="true" android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" android:largestWidthLimitDp="4096" />
  <uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
  <uses-feature android:name="android.hardware.location.network" android:required="false" />
  <uses-feature android:name="android.hardware.wifi" android:required="false" />
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  <uses-permission android:name="android.permission.CAMERA" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>

Friday, November 09, 2012

Augmented reality zombies are here

Do you have an Android phone?  I've written my first ever game and its as far from ordinary as it gets! This deceptively simple game uses literally billions of dollars worth of equipment and military research to make the player fitter and healthier by stealth.
Try it out! https://play.google.com/store/apps/details?id=net.bobpowell.zombiesplat

Wednesday, November 07, 2012

GPS readings still wobble

I've been working on some Augmented Reality functionality and have come to the conclusion that there is no easy way of getting a steady fix on one's GPS receiver. I have been trying to solve the problem of my targets wobbling about when I look at them with the device. The wobble seemed to be induced by breathing or heartbeat but I suddenly realised that the GPS fix itself wobbles about a bit.

I should probably average the fix data...

Thursday, November 01, 2012

China buying up the world with YOUR shoes

The economic power of China has grown enormously in the last decade because of the west's insatiable appetite for cheap consumer goods. This comes at the cost of ethically marginal manufacturing where people are virtually imprisoned in garrison towns, paid in company script and denied the right to leave with savings in cash intact. It also comes at the cost of Chinese government run companies (Essentially all of them in a communist country) contributing to the country's coffers and permitting China to buy vast interests in strategically valuable places.

China has already bought vast swathes of African shipping, oil and agricultural businesses and are steadily moving Chinese managers into positions of power in many African countries. Chinese purchases in southern European ports where racially biased employment practices are used to ensure Chinese staff and management in what ought to be a fair employment market show again that the business aspects of the owner's tenure runs a close second to strategic concerns.

Today, the announcement that China has bought a huge stake in London's Heathrow airport predicts that the same practices will be carried out there also. It will be easy for China to move people and materials from land-side to airside or vice-versa because they will control a big chunk of the airport at London and at its other holdings Gatwick and Luton. China also recently bought a huge stake in Thames water, a previously state run company, privatised by Conservatives and given to their upper-crust old school chums to be sold privately for vast profit. Why sell your water supply to a foreign power that could use it to poison the capital city?

The dangerous fact of a totalitarian state disguised as a friendly power with tons of cash and an ever smiling demeanour is paid for by your shoes, iPhones, televisions and other plastic goods manufactured by the million ton in China. This is a scarily dangerous situation for all occidental concerns.


Camera Preview Textures on MonoDroid and MonoGame

The saga continues with the conversion of the camera preview stream into XNA Texture2D images.

It seems that the same technique of predicated texturing is used on some Android phones as is used on XBox 360 which means that the texture buffer data for any given texture may not be available immediately after drawing because the Present method outputs the textures in sections according to how much graphics memory is available to the GPU.

The result of this is the frame buffer for a texture is not available for the SetData call and data converted over from the camera preview stream will corrupt the texture nastily if the update happens at the same time.

To overcome this I used two textures A and B and while displaying B I write into A and vice-versa. All a bit complicated but graphics is like that it seems.


I set up the textures like so:

          _cameraBGa = new Texture2D(graphics.GraphicsDevice, _pvWidth, _pvHeight, false, SurfaceFormat.Bgra5551);
            _cameraBGb = new Texture2D(graphics.GraphicsDevice, _pvWidth, _pvHeight, false, SurfaceFormat.Bgra5551);

            _frameData = new short[bs.Width * bs.Height];


Then I fill them like so:

       unsafe void _listener_PreviewFrame(object sender, PreviewFrameEventArgs e)
        {
            lock (this)
            {
                fixed (short* fd = &_frameData[0])
                {
                    fixed (byte* yuv = &e.Data[0])
                    {
                        YUV2RGB.convertYUV420_NV21toRGB5551(yuv, fd,
                                                            _pvWidth, _pvHeight);
                        if (_textureSelect)
                        {
                            _cameraBGb.SetData(_frameData);
                            _bReady = true;
                        }
                        else
                        {
                            _cameraBGa.SetData(_frameData);
                            _aReady = true;
                        }
                        _textureSelect = !_textureSelect;
                    }
                }
                _bgReady = true;
            }
        }

And finally display them like so:

        protected override void Draw(GameTime gameTime)
        {
            graphics.GraphicsDevice.Clear(Color.CornflowerBlue); //Cleared by the camera

            if (_aReady && _bReady)
            {

            spriteBatch.Begin();
           
            spriteBatch.Draw(_textureSelect ? _cameraBGa : _cameraBGb, new Rectangle(0, 0, _displayWidth, _displayHeight), Color.White);


etc, etc, etc.

Ahh I love graphics problems. Why didn't I become a priest or something? 

Facebook bubble

The era of the dot com bubble isn't over it seems. Like inventions everywhere, the existence of a purely online entity has to have value at least as great as the sum of it's parts or it will not fly. Google provides a vital and ever growing service that certainly does that. Collating, searching and filtering data must only become more important as we generate more and more of it. Google's approach to data research also provides spinoffs to real technologies such as AI, translation, mobile etc. Facebook on the other hand doesn't provide anything that cannot be duplicated by a couple of students working in a dorm room for three months and the staff at Facebook know this.
Social networking is huge but providing a place for people to post even more innane pictures of their blasted cats isn't. Despite its huge user base, facebook only provides a way for people who already know eachother to share more pictures of cats. There's no money in that.

Wednesday, October 31, 2012

What does Visual Studio do to consume so much CPU?

I have noticed recently that Visual Studio is a CPU hog and sometimes it gets itself into a mode that literally eats CPU cycles like they're going out of style. I have been working on a game today and I could hear the hard-disks rattling in the PC and I looked at the CPU monitor and it was pegged at 78% while the machine was sat idle. That's 78% of a FOUR PROCESSOR 2.3 gigs per proc machine!
Looking at Task Manager I found that an instance of Visual Studio was consuming nearly all of three processors and much of a fourth and that the swap-file was getting thrashed. Closing down Visual Studio again takes the CPU consumption down to 4%. Restarting VS again does not produce the same bad behaviour until some magic trigger trips it up again.
While I realise that Visual Studio does a lot of stuff, it seems to me that it gets a bee in it's bonnet about something and goes off into the realms of outer space with no real rhyme or reason.

Global warming deniers washed away by evidence

The aftermath of Hurricaine Sandy has left New York like a war zone with flood, fire and wind having sut a swathe of destruction though the city. High winds and high storm surge tides are fueled by heat energy that the northern hemisphere in general has been releasing from industry, cars and domestic heating or cooling systems for years.
People with a vested interest in the status quo will often deny these effects as an excuse to keep doing the same old thing and money usually wins in our world. That the deniers are powerful enough to pass laws that prevent scientists from being heard is a matter for thinking people to cure.
I don't suppose that change toward a lower use of energy is truly possible and so we must learn everything there is to know about the cause and effect that we create. Only by clear scientific undestanding that is open to all will we be able to decide how much adverse effect is acceptable for the positive change in quality of life for the greatest number.

Tuesday, October 30, 2012

MONODROID Camera preview as openGL texture

I've been pulling my hair out trying to get a simple camera preview on an android phone with an OpenGL sprite on top. This seems possible if you do it in eclipse using Java but my chosen platform, Monodroid and C# seems to have problems.

Later versions of the Android SDK seem to have this feature also but let's not forget that there are still a huge proportion of 2.3 phones out there that could be supported if only this was a simple feature.

Well, I brute-forced one that runs on OpenGL on a 2.3.3 phone.

#1 I created a camera preview listener and the associated classes to provide a nice .net event when the new camera frame arrived:


    public class CameraListener : Java.Lang.Object, Camera.IPreviewCallback
    {
        public event PreviewFrameHandler PreviewFrame;
        public void OnPreviewFrame(byte[] data, Camera camera)
        {
            if (PreviewFrame != null)
            {
                PreviewFrame(this, new PreviewFrameEventArgs(data, camera));
            }
        }
    }

    public delegate void PreviewFrameHandler(object sender, PreviewFrameEventArgs e);

    public class PreviewFrameEventArgs : EventArgs
    {
        byte[] _data;
        Camera _camera;

        public byte[] Data { get { return _data; } }

        public Camera Camera { get { return _camera; } }

        public PreviewFrameEventArgs(byte[] data, Camera camera)
        {
            _data = data;
            _camera = camera;
        }
    }

#2 Using MonoGame I created a basic app

    public class Game1 : Microsoft.Xna.Framework.Game
    {
        Camera _camera;
        CameraListener _listener = new CameraListener();

        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        SpriteFont font;

        Texture2D _cameraBG;
        short[] _frameData = null;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);

            Content.RootDirectory = "Content";

            graphics.IsFullScreen = true;
            graphics.PreferredBackBufferWidth = 800;
            graphics.PreferredBackBufferHeight = 480;
            graphics.SupportedOrientations = DisplayOrientation.LandscapeLeft | DisplayOrientation.LandscapeRight;

            _listener.PreviewFrame += new PreviewFrameHandler(_listener_PreviewFrame);
        }

        unsafe void _listener_PreviewFrame(object sender, PreviewFrameEventArgs e)
        {
            lock (this)
            {
                fixed (short* fd = &_frameData[0])
                {
                    fixed (byte* yuv = &e.Data[0])
                    {
                        YUV2RGB.convertYUV420_NV21toRGB5551(yuv, fd,
                                                            _cameraBG.Width, _cameraBG.Height);
                    }
                }
                _cameraBG.SetData(_frameData);
            }
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();

           
            _camera = Camera.Open();
            Camera.Parameters parameters = _camera.GetParameters();
            IList<Camera.Size> sizes = parameters.SupportedPreviewSizes;

            _cameraBG = new Texture2D(graphics.GraphicsDevice, sizes[9].Width, sizes[9].Height, false, SurfaceFormat.Bgra5551);
            _frameData=new short[sizes[9].Width*sizes[9].Height];
            parameters.SetPreviewSize(sizes[9].Width, sizes[9].Height);
            _camera.SetParameters(parameters);
           
            _camera.SetPreviewCallback(_listener);
            _camera.StartPreview();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
            font = Content.Load<SpriteFont>("spriteFont1");
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            {
                Exit();
            }

            // TODO: Add your update logic here

            base.Update(gameTime);
        }

        int c = 0;

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            graphics.GraphicsDevice.Clear(Color.CornflowerBlue);


            spriteBatch.Begin();
            spriteBatch.Draw(_cameraBG, new Rectangle(0,0,graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height), Color.White);
            spriteBatch.DrawString(font, "Hello from MonoGame!", new Vector2(c++, 16), Color.White);
            spriteBatch.End();
            if (c > 350)
                c = 0;
            base.Draw(gameTime);
        }

#3 Using info gleaned from Wikipedia I put together a YUV to RGB translator NOTE the use of unsafe code. Sorry but that's the way it has to be. 

    public static class YUV2RGB
    {
        unsafe public static void convertYUV420_NV21toRGB4444(byte* yuvIn, short* rgbOut , int width, int height)
        {
            int size = width * height;
            int offset = size;
            int u, v, y1, y2, y3, y4;

            for (int i = 0, k = 0; i < size; i += 2, k += 2)
            {
                y1 = yuvIn[i];
                y2 = yuvIn[i + 1];
                y3 = yuvIn[width + i];
                y4 = yuvIn[width + i + 1];

                u = yuvIn[offset + k];
                v = yuvIn[offset + k + 1];
                u = u - 128;
                v = v - 128;

                convertYUVtoRGB4444(y1, u, v, rgbOut, i);
                convertYUVtoRGB4444(y2, u, v, rgbOut, (i + 1));
                convertYUVtoRGB4444(y3, u, v, rgbOut, (width + i));
                convertYUVtoRGB4444(y4, u, v, rgbOut, (width + i + 1));

                if (i != 0 && (i + 2) % width == 0)
                    i += width;
            }
        }

        unsafe private static void convertYUVtoRGB4444(int y, int u, int v, short* rgbOut, int index)
        {
            int r = y + (int)1.402f * v;
            int g = y - (int)(0.344f * u + 0.714f * v);
            int b = y + (int)1.772f * u;
            r = r > 255 ? 255 : r < 0 ? 0 : r;
            g = g > 255 ? 255 : g < 0 ? 0 : g;
            b = b > 255 ? 255 : b < 0 ? 0 : b;      

            rgbOut[index] = (short)(0xf000 | ((r&0xf0)<<8) | ((g&0x00f0)<<4) | b>>4);
        }

        unsafe public static void convertYUV420_NV21toRGB5551(byte* yuvIn, Int16* rgbOut, int width, int height)
        {
            int size = width * height;
            int offset = size;
            int u, v, y1, y2, y3, y4;

            for (int i = 0, k = 0; i < size; i += 2, k += 2)
            {
                y1 = yuvIn[i];
                y2 = yuvIn[i + 1];
                y3 = yuvIn[width + i];
                y4 = yuvIn[width + i + 1];

                u = yuvIn[offset + k];
                v = yuvIn[offset + k + 1];
                u = u - 128;
                v = v - 128;

                convertYUVtoRGB5551(y1, u, v, rgbOut, i);
                convertYUVtoRGB5551(y2, u, v, rgbOut, (i + 1));
                convertYUVtoRGB5551(y3, u, v, rgbOut, (width + i));
                convertYUVtoRGB5551(y4, u, v, rgbOut, (width + i + 1));

                if (i != 0 && (i + 2) % width == 0)
                    i += width;
            }
        }

        unsafe private static void convertYUVtoRGB5551(int y, int u, int v, Int16* rgbOut, int index)
        {
            int r = y + (int)1.402f * v;
            int g = y - (int)(0.344f * u + 0.714f * v);
            int b = y + (int)1.772f * u;
            r = r > 255 ? 255 : r < 0 ? 0 : r;
            g = g > 255 ? 255 : g < 0 ? 0 : g;
            b = b > 255 ? 255 : b < 0 ? 0 : b;      
            rgbOut[index]=(short)(((b&0xf8) << 8) |
                          ((g&0xf8) << 3) |
                          ((r >> 2) & 0x3e |
                          1)
                          );
        }
    }

------------------------------------------------------
There you go.. Check out section #2 where the preview frame event handler converts the data and copies it into the texture. This texture can then be used as a background texture on your game.

My lack of thanks goes out to the people on StackOverflow whose unhelpful responses to my pleas were the inspiration for "Do it yer frikkin self Bob"

Please feel free to enjoy the code in any way that pleases you.

Hey, if you find it useful +1 it please.