Friday, August 21st 2015

MBE ECU DIM Sport Key Decryption
posted @ 4:07 pm in [ Cars -Decryption -Fixing Things -PHP -Technology ]

I’ve recently started investigating into the working of the MBE ECU (Engine Control Unit) that runs the engine and fuel mixture on my TVR Cerbera and as part of the process took my own ECU out of the car to see how it was setup, and what version of the software it was using

On inspection my own ECU seemed rather different than the test unit I had bought from eBay, as the EPROM that contains the program code was piggy-backed off of a daughter board rather than being directly connected to the ECU motherboard

As you can see from the picture below the daughterboard plugs in in-between the ECU and the code EPROM



and if we actually take the EPROM and daughterboard out of the ECU you can see that the daughterboard has an ATMEL F16V8BQL electronically programmable logic device in circuit



So the ATMEL F16V8BQL basically can be programmed like a small computer to do something with data that comes through it’s inputs, and then send this data back out of it’s outputs

Therefore the next logical question would why would you want to do that when normally the data from the EPROM is sent directly to the ECU for reading?

We’ll it turns out that basically it is a decryption device for taking encoded data stored on the EPROM, decoding it in real time, and then sending this to the ECU as unencoded data to run with

Taking the EPROM out of it’s daughterboard you can see it’s made by “DIM Sport, Electronic per motori” and is labelled as Key 1010A


On investigation DIM Sport are an Italian engine calibration specialist company who make rolling road tuning systems for cars and other vehicles and Key 1010A is sold as part of their rolling road kit

So let’s try and work out how this works by reading the EPROM on it’s own (encrypted) and with it’s daughterboard installed (unencrypted)

As you can see from the Hex dumps below, the daughterboard is doing some data decryption in between


If you compare the first 16 bytes of the encrypted versus the unencrypted you can see that there is a pattern between the two


04219402 C4C10FC4 9501C4C1 0FC49501


01249102 C1C40FC1 9504C1C4 0FC19504

Every second value is being changed between the two, but the first value is always exactly the same

Originally I thought this was a pattern based cypher, so basically something like

0, -3, 0, +3, 0, -3, 0

but if you look at it visually you can see it is actually a substitution based cypher as every time on the ASCII display you see an ‘!’ symbol on the encryption version, or the unencrypted version it is a ‘$’, the same for the letter ‘t’ being a q

So that leans to being a substitution cypher, so we basically just need to work out the mapping of which letter to which, and then we can begin to reverse engineer the encryption

Here’s my map I made as I was doing it for reference (and you can see the original pattern test sequence there too) 🙂


Now lets test our theory and translate the first 8 numbers (the numbers mapped are in brackets, every even number)

04219402 = 0(1)2(4)9(1)0(2)

Perfect! So now we have the sequence let’s write a decryption program to read the original encrypted binary EPROM dump, decode it, and then write out an UNENCODED EPROM dump for us to use in our ECU and no longer require the key

I’ve written it in PHP as that’s currently where I am spending most of my programming time at the moment, and uploaded it to my GIT HUB account here

So if you find one of these in your ECU, or you want to backup your own ECU software feel free to use the above, which because I didn’t reverse engineer any hardware, doesn’t normally break any software licensing rules 🙂

Saturday, August 8th 2015

Snap-on Tool Kit – now with wheels
posted @ 9:36 am in [ Cars -Fixing Things ]

As a recent mechanical student I had the opportunity to buy my first Snap-on tool kit, which of course I snapped up the chance of doing.

It’s a fantastic student kit with everything you need for day-to-day car maintenance tasks, however even though it comes with a carry handle it is heavy which means getting it from the house to the car is quite an effort in itself!

So I put my thinking hat on, and as with our recent arcade machine projects in the office, decided that it was time to mobilise the tool kit with it’s own set of wheels

First things first – where to mount them.

Luckily the tool box has 4 holes on the bottom which after measuring them fit nicely with 8mm / M8 allen socket bolts.


So off to our good friends on eBay, KayFast, and order M8 bolts 20mm long and matching M8 flange nuts. I went for the round headed allen socket bolts as they will sit flush either way around



Next we need some wheels, castors in this case, and as we are using our own bolts we want ones without threaded heads, just with a hole to be bolt mounted.

Again eBay is a good source for these and I ordered 4 x 50mm lockable cabinet speaker castors from the great people at Atlas Handling (make sure you order the Bolt Hole ones)


Once they’ve arrived it’s time to match them all up and check they all fit correctly as per the picture below


Now we need to remove the bottom drawer of the tool kit to access the mounting holes from the inside, but the problem here is that there is a locking latch on the drawer that matches up with a stop on the slider, meaning that you can’t just slide the drawers out.

I had a read around and this guy had suggested using a flat hacksaw blade, but for me the easiest way was to get behind the point where they lock and apply gentle pressure using the small Snap-on screwdriver included with the toolkit on the drawer latch point to allow it slide underneath the slider locking point as per this photo


This allows the drawer to slide all the way out as per this photo and then we can start to mount our wheels to the bottom of the cabinet

IMG_1322 (2)

Tighten everything up using an allen key (I put the bolts with the heads on the bottom so that I can tighten them up at a later date if needed) and voila all ready to go!

IMG_1326 (1)

Friday, November 29th 2013

Magento: The order of translations
posted @ 7:45 am in [ Magento -Magento Certified Developer ]

Magento supports localised translations of text used within the site, using a number of translation methods which are perfect for localising the text used within your e-commerce website.

However it is often confusing what order they are prioritised in and where to look to find out which files should be translating your text, so here’s the orders and a little explanation for reference:

The order of checking translation files by Magento is:

1. Extension translation files
2. Theme translation files
3. Database translation table

        foreach ($this->getModulesConfig() as $moduleName=>$info) {
            $info = $info->asArray();
            $this->_loadModuleTranslation($moduleName, $info['files'], $forceReload);


1. Extension translation files

Extension translation files are defined in your (or other 3rd party) extensions using the extension’s etc/config.xml file.

Here is an example for our made-up extension, Skywire_Translation



Extension translation files are stored in:


so in our case as we are using en_GB as our locale and our above config.xml, this would be:


and the contents has the usual Magento format of “Thing to translate”,”What you want it to be instead”, for example

"Add to Cart","Add to Bag"

2. Theme translation files

Theme translation files are applied after Extension translation files so will not get used if text is already re-defined in the extension translation files.

These files reside in:


so in our case would be


and are the same format as all other Magento translate files, namely:

"Add to Cart","Add to Bag"

3. Database translation table

The Database translation table, core_translate, can also be used to store translations, but seems to be largely not used by core or other extensions.

The table structure is:

mysql> desc core_translate;
| Field     | Type                 | Null | Key | Default          | Extra          |
| key_id    | int(10) unsigned     | NO   | PRI | NULL             | auto_increment |
| string    | varchar(255)         | NO   |     | Translate String |                |
| store_id  | smallint(5) unsigned | NO   | MUL | 0                |                |
| translate | varchar(255)         | YES  |     | NULL             |                |
| locale    | varchar(20)          | NO   |     | en_US            |                |

so we would use the ‘string’ field for our source text, and the ‘translate’ string for our desired text.

Interestingly this is used by the Magento inline translation system – which is something I didn’t even know existed (did you?!)

There’s a video of it here and it appears to allow you to translate all the text on your website, using your browser from the frontend.

4. Debugging

If you want to see what extension is claiming what text on your page, a quick check is to echo out the $code for each translate object as the page is rendered.

A quick way to do this (only for testing mind you) is to edit


and around line 405 in function translate, echo out the $code value after it is set.

For example:

     * Translate
     * @param   array $args
     * @return  string
    public function translate($args)
        if ($text instanceof Mage_Core_Model_Translate_Expr) {
            $code = $text->getCode(self::SCOPE_SEPARATOR);
            $module = $text->getModule();
            $text = $text->getText();
            $translated = $this->_getTranslatedString($text, $code);
        else {
            if (!empty($_REQUEST['theme'])) {
                $module = 'frontend/default/'.$_REQUEST['theme'];
            } else {
                $module = 'frontend/default/default';
            $code = $module.self::SCOPE_SEPARATOR.$text;
            $translated = $this->_getTranslatedString($text, $code);
        // debug line below
        echo $code;
        return $result;

5. One Final Tip…

Magento Translation Files are cached which means after you have changed them or added new files, you have to clear the Translations cache in order to see the effects

System -> Cache Management -> Cache Storage Management -> Translations [select] -> Actions [Referesh] -> Submit

You’ll be happy you read this line 🙂


What is the difference between translate.csv translations and the database method via the table core_translate?

How to add your own translations to Extensions?

Usefull tools:

Exports the DB translations in Magento to CSV files

Magento in-line translations

Friday, July 19th 2013

This arrived today
posted @ 5:23 am in [ Games ]

From the US some great new (old) parts for our arcade machines

– A new Tron “Encom” marquee for our Tron arcade machine, the same as the one used in the new Tron movie

– A Galaxian back glass from an original Bally Galaxian machine

– A Tron “cabaret” back glass to use on our cabaret machine to make it into a Tron cabaret

Happy days!

Tron "Encom", Galaxian and Tron "cabaret" back glasses

Tron “Encom”, Galaxian and Tron “cabaret” back glasses

Tron "cabaret" back glass in place on our cabaret conversion machine

Tron “cabaret” back glass in place on our cabaret conversion machine

Thursday, July 4th 2013

Magento: calculating Total Paid 1 penny out £0.01
posted @ 6:45 am in [ Fixing Things -Magento ]

We have a strange issue with a Magento / eBay install for a client where occasionally the orders are being stored with the Total Paid for the order showing in Magento as being £0.01 less than the real total paid by the customer.


Looking at the order in the Magento database it appears to be an incosistency in the way that the tax for shipping is calculated.

Amount of shipping charged = £3.95

Magento Values:

Base Shipping Amount = £3.29

Base Shipping Tax Amount = £0.65

Total of these = £3.94

What these values should be:

Base Shipping Amount = (£3.95 – 20% tax) = (£3.95 / 1.2) = £3.29166666

Base Shipping Tax Amount = (20% tax of £3.95) = (£3.95 / (1.2 * 5)) = £0.65833333

Total of these = £3.95 (notice the extra £0.01 difference)

So Magento seems to occasionally NOT correctly round-up the Base Shipping Tax Amount as the value should be £0.66 if the full value is £0.658333333

Now to find out why, where and fix it!

Here’s the tables for reference of two sequential orders – the first that is calculated incorrectly then the second that is calculated correctly!:

mysql> select base_shipping_amount, base_shipping_tax_amount, base_shipping_incl_tax from sales_flat_order where entity_id like '%298';
| base_shipping_amount | base_shipping_tax_amount | base_shipping_incl_tax |
| 3.2900 | 0.6500 | 3.9500 |
1 row in set (0.00 sec)

mysql> select base_shipping_amount, base_shipping_tax_amount, base_shipping_incl_tax from sales_flat_order where entity_id like '%299';

| base_shipping_amount | base_shipping_tax_amount | base_shipping_incl_tax |
| 3.2900 | 0.6600 | 3.9500 |
1 row in set (0.00 sec)

Wednesday, December 5th 2012

Magento: Show out of stock configurable product options and notifications
posted @ 11:13 am in [ Magento -Technology -Web Design ]

Configurable products in Magento are difficult to handle, as they consist of multiple “Simple” products that have their own stock levels, prices etc.

These notes talk through how to add “Out of Stock” options to each of these on the Magento product page, and some extensions to provide Out of Stock Notifications when they are:

Programming: Show out of stock configurable options

Programming: How to show out of stock configurable options with Magento

Extension: Aheadworks – Product Updates Notifications ($89)

Extension: Amasty – Out of Stock Notifications ($79)

Extension: Apptha – Out of Stock Notification ($79)

Wednesday, October 24th 2012

Decoding $_F=__FILE__;$_X= Encoded PHP Files
posted @ 7:27 am in [ Decryption -Fixing Things -Magento -PHP -Technology -Web Design ]

Some PHP files we get from Extension developers for Magento have Bytecode encoding on them, which means if we want to change the functionality or layout of certain parts of the code, even if we’ve paid for it, we can’t.

Obviously this is rather frustrating, however it is possible to reverse engineer the files as follows to make the changes you need.

1. The three component parts

Each file has 3 main parts to it:




These parts are as follows:

$_F - a holder to do the ereg_replace of the obfuscater code with the unencryption keys

$_X - the encrypted PHP code

eval(base64_decode() - the decryption code for $_X

2. Getting the decryption code

To get the decryption code, we need to change the eval(base64_decode()); code to be an echo instead.

In our case above this would be:


and this gives us the decryption code for the main $_X values;


If we break this apart into it’s core lines we have:

//decode our main string with base64_decode

//replace obfuscater characters in the result with the correct ones

//replace the contents of $_R with our unencrypted file/PHP code

//run the contents of the unencrypted file/PHP code

//clear the contents of $_R so you can't access it

//clear the contents of $_X so you can't access it

3. Decrypting the encoded code

So now we just need to run the decryption code as far as it replacing the contents of $_R with the un-encrypted result, and echo that out to the screen.

Here’s the code:

//decode our main string with base64_decode

//replace obfuscater characters in the result with the correct ones

//replace the contents of $_R with our unencrypted file/PHP code

//print the contents of the unencrypted file/PHP code

4. Final code

So we end up with:

And we can now make the changes we need

Monday, July 16th 2012

Magento: Extend/Rewrite Block
posted @ 7:11 am in [ Magento -Technology -Web Design ]

To extend/rewrite an existing Block, you need to create your new extension, and your extended block and then rewrite the current block using your config.xml file.

1. Create your new extension

1.1 Folder for your blocks


1.2 Folder for your configuration file


2. Extend the block you want to extend/rewrite

2.1 Extended block


* Detailed Product Reviews
* @category Zuneta
* @package Zuneta_Review
* @author Alex Judd
class Zuneta_Review_Block_Product_View_List extends Mage_Review_Block_Product_View_List
public function getReviewUrlSection($id, $section)
return Mage::getUrl($section . '/*/view', array('id' => $id));


Here we have extended the core block, namely /app/code/core/Mage/Review/Block/Product/View/List.php with our own local version to add a new function allowing us to specify which section we would like to refer to when you view a review.

3. Extend/Rewrite the current block using our XML config.xml file

3.1 /app/code/local/Zuneta/Rewrite/etc/config.xml




The trick here is to specify within the ‘global’ section that we want to talk to the ‘blocks’ section.

Then when in the ‘blocks’ section we want the ‘review’ block to be the one begin rewritten, and as our code is 3 levels deep, we want to rewrite the ‘product_view_list’ block as that relates to /app/code/core/Mage/Review/Block/Product/View/List.php

Then we simply specify the whole structure of our block in the rewrite contents

4. Enabling our block

4.1 /app/etc/modules/Zuneta_Review.xml

We need a /app/etc/modules/Zuneta_Review.xml file in order to enable our module


5. Done!

We should now be good to go and our new function can be called, for example in my case I am modifying the product template


to specify that I want to use the ‘review’ rewrite for all my detailed review links

htmlEscape($_review->getTitle()) ?> __('Review by %s', $this->htmlEscape($_review->getNickname())) ?>

Wednesday, May 2nd 2012

Extending core events in concrete5
posted @ 7:09 am in [ concrete5 -PHP -Technology -Web Design ]

We’re building all of our content based sites on concrete5 as it fits in with our LAMP architecture and Zend Framework architecture which we implement a lot with our Magento eCommerce websites.

The platform is ready to go out of the box, but it’s a bit hard to find how to do what you want sometimes so here’s how to extend the core events (add user, login etc.) with your own code

1. Extending the core events

Events are extended using the /config/site_events.php file and contain the event you want to extend, along with the class and method you want to call when this happens, and finally the model that contains that information

Here’s my example extending the user add event, and calling my own class ‘ApplicationUser’ and the method (function) ‘setupUserJoinInfo’

Obviously you only need the PHP tags the first time you create the file and you can overwrite many events in the same file.

2. Create your class

New file outside of the core, so we’re going to create /models/application_user.php and add in our basic class definition

3. Create our method

So in my case I'm going to hook into my method 'setupUserJoinInfo' pass it the new user object (as we know this is being triggered by the 'on_user_add' event)

class ApplicationUser extends Object {

* @param User $uI
public static function setupUserJoinInfo($ui) {
/* Your own code goes here */

4. Make it do something

In my case I wanted to email the user a one time hash password when their account was registered so I used the User object and the Mail object with a template in the '/mail/' folder called 'account_creation.php' (you can borrow the hash generation code from the core user.php file/class)

It's not that scary once you get your files installed and the Helpers for Mail and Users make it pretty flexible. Good luck!



1. System events

2. Helpers -> Mail

3. Permissions -> Users

Monday, November 7th 2011

NGinx not compressing CSS and Javascript
posted @ 8:11 am in [ Fixing Things -Javascript -Magento -PHP -Web Design ]

Another challenge to catch-out the unwary, is that the latest CentOS/RedHat YUM repository version of NGinx, the fantastically fast web server we use for Magento, has some case scenarios where even though it should be compressing CSS and Javascript, it simply doesn’t!

The reason why seems to be that most definitions for what types of files NGinx should compress posted across the forums of the web, include the “text/html” type, such as:

gzip_types text/plain text/html text/css application/json application/x-javascript text/xml application/javascript text/x-js;

Now the problem with this seems to be that NGinx throws a simple warning that it has already got “text/html” defined as it does this by default, however what it then doesn’t tell you is that it IGNORES all the other definitions that come after it in the same line.

So what that means is that if you have the line above in your config file, even though you are defining for example “text/css” as being a file type to compress, NGinx will ignore this as it stops reading the line as soon as it hits the “text/html” double definition.

To fix, remove “text/html” from your line (*and while you are there you might as well just define the types we are using) and it will all work again.

Here’s my line for reference:

gzip_types text/css application/x-javascript;