Git branch last activity

Here I am starting a new category for short posts where I will give some usefull code snippet or shell command for every day use. So I start with a git command used to show last commit date for each branch, sorted by last commit date desc:

$ for branch in `git branch -a | grep -v HEAD`;do echo -e `git show -s --format="%ci,%cr,$branch,%an" $branch`; done | sort -r |column -t -s ","

Javascript Game Engine Part 1 – Sprite drawing & animation

I always wanted to program a game engine and this easter weekend boredom gave me some time to do so. I thought this exercise could help other people so I will describe here the different steps to build such an engine. Here is the first part of this tutorial series.

Canvas definition and basic drawing

First we will need an HTML element to draw onto it. The <canvas> element is what we are looking for. You need to specify its size explicitly as it will be the available pixels we have in our canvas which can be different than the actual size on the screen defined with CSS properties. This is an important point, canvas has an intrinsic size (which define the available size for all drawing functions) and an extrinsic size (real size on the page) for which the canvas scale automatically. If you want to keep it simple, only define the intrinsic size and do not define the size of the canvas in CSS.

<canvas id="game-window" width="1024" height="640"></canvas>

From the javascript endpoint we require a specific object to actually draw on the canvas. This object (CanvasRenderingContext2D) is available from the canvas element:

var gameCanvas = document.getElementById('game-window');
var context = gameCanvas.getContext('2d');

And now come the interesting part, we will draw something onto the canvas. I am not describing every possible drawing function here, you’ll find all you need on the CanvasRenderingContext2D reference page.

// Draw a red rectangle from (100, 100) to (200, 200)
context.strokeStyle ="#f00";
context.strokeRect(100, 100, 200, 200);

// Get an image from an url
var img = new Image();
img.src = "imageurl.jpg";
// Wait for image to be loaded before rendering it
img.onload = function() {
  // Draw image at position (100,100)
  context.drawImage(img, 100, 100);
};

Game loop in javascript

If you’ve wrote a game before you know that at the core of every game you’ll allmost allways find the same paradigm. A game loop responsible for updating the environment (update scene, move sprites, handle user input) and rendering the game. This loop is infinite and only exit when the game ends. The same paradigm applies here however as the javascript is mono-threaded we need a way to ensure the browser can have some “spare” time to do its internal work. This is done by delegating the loop to the browser, we just ask to be called for each frame update. Modern browsers offer the requestAnimationFrame method to do so.

function update() {
  // Update environment
  // ...
}

function render() {
  var gameCanvas = document.getElementById('game-window');
  var context = gameCanvas.getContext('2d');
  // Render to canvas
  // ...
}

function gameloop() {
  update(); // Update environment
  render(); // Render to canvas

  // request the browser to call again gameloop function
  requestAnimationFrame(gameloop);
}

// First call to start game loop
requestAnimationFrame(gameloop);

In this example I haven’t included the timing function required to update the environment according to the elapsed time. Again this is a common pattern in game programming. If you want to know more about it you can read this article about the game loop. Here is the example with this pattern implemented:

/**
* Timestamp function
* @return {integer} a timestamp
*/

function getTimestamp() {
  return window.performance &amp;&amp; window.performance.now ? window.performance.now() : new Date().getTime();
}

/**
* Update game environment
* @param {int} dt time elapsed
*/

function update(dt) {
  //...
}

/**
* Render game scene
* @param {2DContext} context
* @param {int} dt elapsed time
*/

function render(context, dt) {
  //...
}

var step = 1/30; // This the delay between each environment update
var dt = 0;
var last = 0;
var gameCanvas = document.getElementById('game-window');
var context = gameCanvas.getContext('2d');

function gameloop() {
  var now = getTimestamp();

  // Add elapsed time since last call
  dt = dt + Math.min(1, (now - last) / 1000);

  // Here we call the update method at given interval
  // catching up time if necessary
  while(dt &gt; step) {
    dt = dt - step;
    update(step);
  }

  render(context, dt); // Render to canvas

  // request the browser to call again gameloop function
  requestAnimationFrame(gameloop);
}

last = getTimestamp();
// First call to start game loop
requestAnimationFrame(gameloop);

Sprite animation

So we have seen how to render an image and how to construct a game loop in javascript. We have everything needed to animate a sprite. A sprite animation is pretty straightforward as it is only a sequence of different frames of the same sprite rendered in a loop.
For example if we have the following sprite composed of different frame, all in the same image : ship-1-r
We can render each frame alternatively which will “animate” the sprite. The update() function will be responsible for determining which frame to render and render() will render the frame.

Here is an object oriented implementation of an animated sprite:

"use strict";
/**
 * Animated sprite
 * @param {string} url      Url of the image containing sprite frames
 * @param {int} frameWidth  width of individual frame
 * @param {int} frameHeight height of individual frame
 * @param {int} frameSpaceX horizontal margin between frames
 * @param {int} frameSpaceY vertical margin between frames
 * @param {int} frameCountX frame count per row
 * @param {int} frameCountY frame count per col
 */

function AnimatedSprite(url, frameWidth, frameHeight, frameSpaceX, frameSpaceY, frameCountX, frameCountY) {
  this.loaded = false;
  this.frameWidth = frameWidth;
  this.frameHeight = frameHeight;
  this.frameCountX = frameCountX;
  this.frameCountY = frameCountY;
  this.frameSpaceX = frameSpaceX;
  this.frameSpaceY = frameSpaceY;

  this.image = new Image();
  this.image.src = url;

  this.frameCount = this.frameCountX * this.frameCountY;
  this.frameIndex = 0;
  this.frameX = 0;
  this.frameY = 0;

  this.x = 0;
  this.y = 0;

  var self = this;
  this.image.onload = function() { self.loaded = true; };

}

/**
 * Reset animation
 */

AnimatedSprite.prototype.reset = function() {
  this.frameIndex = 0;
  this.frameX = 0;
  this.frameY = 0;
};

/**
 * Update animation by cycling between frames
 * @param  {int} dt elapsed time
 */

AnimatedSprite.prototype.update = function(dt) {
  this.frameIndex = (this.frameIndex + 1) % this.frameCount;  
  this.frameX = (this.frameWidth + this.frameSpaceX) * (this.frameIndex % this.frameCountX);
  this.frameY = (this.frameHeight + this.frameSpaceY) * ~~(this.frameIndex / this.frameCountX);
};

/**
 * Render sprite
 * @param {2DContext} context
 * @param {int} dt elapsed time
 */

AnimatedSprite.prototype.render = function(context, dt) {
  context.drawImage(this.image,
    this.frameX, this.frameY, this.frameWidth, this.frameHeight,
    this.x, this.y, this.frameWidth, this.frameHeight);
};


/**
 * Set position of the sprite on the canvas
 * @param {int} x
 * @param {int} y
 */

AnimatedSprite.prototype.setPosition = function(x, y) {
  this.x = x;
  this.y = y;
};


/**
 * Move the sprite by the specified direction
 * @param  {int} x
 * @param  {int} y
 */

AnimatedSprite.prototype.move = function(x, y) {
  this.x += x;
  this.y += y;
};

In our main game update and render we then only have to call this object update and render methods :

var myAnimatedSprite = new AnimatedSprite('ship-1-r.png', 100, 94, 1, 1, 1, 4);
myAnimatedSprite.setPosition(100, 100);

/**
* Update game environment
* @param {int} dt time elapsed
*/

function update(dt) {
  //...
  myAnimatedSprite.update(dt);
}

/**
* Render game scene
* @param {2DContext} context
* @param {int} dt elapsed time
*/

function render(context, dt) {
  //...
  myAnimatedSprite.render(context, dt);
}

Source Code

With the help of the tutorial you should be able to animate sprites on your screen. The enhanced source code for this tutorial is available here: JS Game Engine part 1 source code. I have also added the source of a basic scrolling background object.

Have fun !

Google analytics for Windows Phone applications

Using an analytics solution to collect some information on your application usage is a real added value to make it a great application. Of course there are informations available on the market place but these informations are quite limited. You only have access to the number of daily download and the installation base but you don’t have information on which part of your app is most used or the time spent on each page of your application. So here I’m giving the steps required to monitor your application usage with online an analytics services like Google Analytics.

Prerequisities

Microsoft was kind enough to create a library to make this task easy. So the first step is to download and install this library. You can get the latest version of the Microsoft Silverlight Analytics Framework here : http://msaf.codeplex.com/
You also need an analytics service provider. Here I am using Google analytics, it’s free and quite powerfull for a free product. If you want to use Google Analytics, you will need to create an account and add a website : http://www.google.com/analytics/

Code

Add references to the following assemblies by manually browsing to C:\Program Files\Microsoft SDKs\Microsoft Silverlight Analytics Framework.4\WP7:

  • Microsoft.SilverlightMediaFramework.Helpers.Phone (Microsoft.SilverlightMediaFramework.Compatibility.Phone.dll)
  • Microsoft.WebAnalytics (Microsoft.WebAnalytics.dll)
  • Microsoft.WebAnalytics.Behaviors (Microsoft.WebAnalytics.Behaviors.dll)
  • Google.WebAnalytics (Google.WebAnalytics.dll)

Add reference to the following assemblies using the .Net tab in the “Add reference” dialog box:

  • System.Device
  • System.Windows.Interactivity

The documentation tells you to but DO NOT ADD a reference to ComponentModel (System.ComponentModel.Composition.dll) !!! Otherwise you will get an error about the type AssemblyCatalog beeing defined in two different assemblies.

Create service class derived from IApplicationService

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.ComponentModel.Composition.Hosting;

namespace AnalyticsSample
{
    public class AnalyticsAppService : IApplicationService
    {
        /// <summary>
        /// Initialize the assembly catalogs for the Silverlight Analytics Framework
        /// </summary>
        /// <param name="context">the application service context</param>
        public void StartService(ApplicationServiceContext context)
        {

            CompositionHost.Initialize(new AssemblyCatalog(
                Application.Current.GetType().Assembly),
                new AssemblyCatalog(typeof(Microsoft.WebAnalytics.AnalyticsEvent).Assembly),
                new AssemblyCatalog(typeof(Microsoft.WebAnalytics.Behaviors.TrackAction).Assembly),
                new AssemblyCatalog(typeof(Google.WebAnalytics.GoogleAnalytics).Assembly));
        }

        /// <summary>
        /// Stop the service
        /// </summary>
        public void StopService()
        {
        }
    }
}

Then you will need to modify your App.xaml file:

<Application
   x:Class="AnalyticsSample.App"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
   xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
   xmlns:local="clr-namespace:AnalyticsSample"
   xmlns:mwa="clr-namespace:Microsoft.WebAnalytics;assembly=Microsoft.WebAnalytics"
   xmlns:ga="clr-namespace:Google.WebAnalytics;assembly=Google.WebAnalytics">

    <!--Ressources d'applications-->
    <Application.Resources>
    </Application.Resources>

    <Application.ApplicationLifetimeObjects>
        <!-- Must be first service -->
        <shell:PhoneApplicationService
           Launching="Application_Launching" Closing="Application_Closing"
           Activated="Application_Activated" Deactivated="Application_Deactivated"/>
       
        <!-- Then the Analytics service we created -->
        <local:AnalyticsAppService/>
       
        <!-- And the Web analytics service provider -->
        <mwa:WebAnalyticsService>
            <mwa:WebAnalyticsService.Services>
                <ga:GoogleAnalytics WebPropertyId="UA-12345-1"/>
            </mwa:WebAnalyticsService.Services>
        </mwa:WebAnalyticsService>
    </Application.ApplicationLifetimeObjects>

</Application>

Here are the modification:

  • Add the namespace for “local” (AnalyticsSample: our application namespace), “mwa” (Microsoft.WebAnalytics) and “ga” (Google.WebAnalytics).
  • Add the AnalyticsAppService you defined earlier to the Application.ApplicationLifetimeObjects node. The line must be typed after shell:PhoneApplicationService, the order is important !
  • Add a web analytics service after local:AnalyticsAppService (again the order is important), replace the “UA-12345-1″ with the site id from your Google analytics account.
  • Done ! It takes some time to see the result in Google Analytics.

    Tracking Pivot & Panorama control usage

    The previous steps will correctly report information about your application usage per page, however if your application main interface is based on a Pivot or Panorama control you will not have detailled information about it’s usage. Fortunately, the Microsoft Analytics framework allows you to track your Pivot control usage. Here is how:
    Add a reference to the Microsoft.WebAnaltyics.Controls.WP7 by manually browsing to “C:\Program Files\Microsoft SDKs\Microsoft Silverlight Analytics Framework” with the “Add reference” dialog box.

    Edit your application page and make the following modification:
    * Add the namespace for “i” (System.Windows.Interactivity) and “mwab” (Microsoft.WebAnalytics.Behaviors)
    * Bind the SelectionChanged event to the TrackAction behavior from the analytics framework.

        <i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectionChanged">
                <mwab:TrackAction/>
            </i:EventTrigger>
        </i:Interaction.Triggers>

    You can also make these modifications using Microsoft Expression Blend.

    Edit your AnalyticsAppService and add an AssemblyCatalog line to the StartService method previously defined:

    CompositionHost.Initialize(new AssemblyCatalog(
        Application.Current.GetType().Assembly),
        new AssemblyCatalog(typeof(Microsoft.WebAnalytics.AnalyticsEvent).Assembly),
        new AssemblyCatalog(typeof(Microsoft.WebAnalytics.Behaviors.TrackAction).Assembly),
        new AssemblyCatalog(typeof(Microsoft.WebAnalytics.Controls.HandlePanorama).Assembly),
        new AssemblyCatalog(typeof(Google.WebAnalytics.GoogleAnalytics).Assembly));

    The PanoramaItem/PivotItem Name or Header (if there is no Name) is then tracked in the event’s ActionValue.

    Download example

    A demo application is like a photo, it’s worth a million words so here it is:  AnalyticsSample

Binding to a class property in XAML

Binding something in your XAML file to a property in your underlying partial class is pretty easy once you know the trick. You only have to name your XAML base object. For example, here is a PhoneApplicationPage declaration:

<phone:PhoneApplicationPage
    x:Class="MyApp.MySamplePage"
    x:Name="Self"
    >
    ...
</phone:PhoneApplicationPage>

I always give “Self” as my object name as I find using “Self” in the binding declaration makes the binding obvious but you can use the name you want. My example is for a Windows Phone application however the same mechanism works for any XAML desktop application.

Then you define a property in your class, for example

namespace MyApp
{
    public partial class MySamplePage : PhoneApplicationPage
    {
        public String MyStringProperty { get { return "Binded string"; } }
        ...
    }
}

Now, you can use some binding magic in your XAML file to map a node property to a class property :

<TextBlock Text="{Binding MyStringProperty, ElementName=Self}" />

And Voilà !

Using Silverlight charting control in Windows Phone

I’m currently working on a small app for Windows Phone. I wanted to add some simples charts to the application and found silverlight contained a charting control. As a reminder for me and as an helpfull example for you, here are the necessary steps to display a simple chart in your Windows Phone Application. The example below was tested against the Windows Phone SDK version 7.1.

Prerequisities

First, you need to install the silverlight libraries from http://silverlight.codeplex.com/

  • Silverlight Phone toolkit
  • Silverlight 3 (not 4 ! not 5 !): It’s an old version but unfortunately, newer silverlight versions are not supported. In fact, Windows Phone SDK is build around Silverlight 3 with some addition from silverlight 4.

Next, you need to add manually the references to the silverlight toolkit by browsing to the Silverlight install folder:

  • System.Windows.Controls.DataVisualization.Toolkit.dll (should be in C:\Program Files\Microsoft SDKs\Silverlight\v3.0\Toolkit\Nov09\Bin)
  • System.Windows.Controls.dll (should be in C:\Program Files\Microsoft SDKs\Silverlight\v3.0\Libraries\Client\)

Code

We need to add the namespace for the charting toolkit, here named “chartingToolkit”:

<phone:PhoneApplicationPage
   x:Class="ChartDemo.MainPage"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
   xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
   xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   xmlns:chartingToolkit="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit"
   mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
   FontFamily="{StaticResource PhoneFontFamilyNormal}"
   FontSize="{StaticResource PhoneFontSizeNormal}"
   Foreground="{StaticResource PhoneForegroundBrush}"
   SupportedOrientations="Portrait" Orientation="Portrait"
   shell:SystemTray.IsVisible="True">
...
</phone:PhoneApplicationPage>

Then we add the control to our application page :

            <chartingToolkit:Chart x:Name="ChartControl" Title="My chart">
                <chartingToolkit:Chart.Axes>
                    <chartingToolkit:LinearAxis Orientation="Y" ShowGridLines="True" />
                </chartingToolkit:Chart.Axes>
                <chartingToolkit:ColumnSeries IndependentValueBinding="{Binding Name}" DependentValueBinding="{Binding Value}" />
            </chartingToolkit:Chart>

Note the binding parameters, they are linked to the data object we defined to hold chart data :

    public class ChartData
    {
        public string Name { get; set; }
        public double Value { get; set; }
    }

We also need some data so we generate some :

            List<ChartData> data = new List<ChartData>();
            for (int i = 0; i < 10; i++)
            {
                data.Add(new ChartData(){
                    Name = String.Format("data {0}", i + 1),
                    Value = i
                });
            }

The final step is to set the data source of the data serie:

            ColumnSeries series = ChartControl.Series[0] as ColumnSeries;
            if (series != null)
                series.ItemsSource = data;

Troubleshooting

If you link your project with the wrong silverlight version you might get the following errors :

  • “A first chance exception of type ‘System.InvalidOperationException‘ occurred in Microsoft.Phone.dl”: You probably forgot to add the reference to System.windows.control
  • “A reference to a higher version or incompatible assembly cannot be added to the project”: You probably linked against Silverlight version 5 dll

Source code

In case it may help, here is the source code of the demo application: ChartDemo application source

Flash.bin build tool for LG KS 20

This is a command line tool to extract content from a flash.bin file and rebuild a new one using other file parts. Click on the link below to download the tool.

Latest version : LGFlashMuncher Version 0.2

Usage :

LGFlashMuncher.exe [options] path [output]
  EXTRACT Options ---(at least one option required)-----------------------------
        -r      : extract Raw data
        -h      : extract header
        -m      : extract MBR
        -p      : extract partitions
        -t      : trim extracted partitions
        -l      : output layout informations to file 'flash.xml'
        -o      : output OS.nb compatible file
        output  : path to output directory (must exists)

  CREATE Options  ---(all options required)-------------------------------------
        -c file : create new flash.bin outputed to 'file'
                  (MBR and fat partition are taken from original flash.bin)
        -e file : use 'file' for header
        -0 file : use 'file' for partition 0 (boot)
        -1 file : use 'file' for partition 1 (rawfs)
        -2 file : use 'file' for partition 2 (imgfs)

  COMMON Option  ---------------------------------------------------------------
        path       : path to flash.bin file

Next, how to extract data from a flash.bin to a directory named output :

LGFlashMuncher.exe -htmlp FLASH.bin output

How to rebuild a new flash.bin :

LGFlashMuncher.exe -c newflash.bin -e header.bin -0 part_0_BOOT.bin -1 part_1_RAWFS.bin -2 part_2_IMGFS.bin FLASH.bin

WCF : WS-Security Hell

dotnetLastly, I had to build a client to consume a web service. This task seems a bit trivial at first, but the service required an authentication mechanism based on WS-Security. Nothing really complex, the only requirement was to send a username and a password in plain text.

As usual when I build this kind of application, I used Visual Studio wizard to create the proxy to the web service, and after some tweaking in the app.config file, my application was ready to consume this web service !

Unfortunately, there is a security behavior in WCF that prevent from using plain text message based authentication over unsecure transport : i.e. you cannot send a clear password if you are using HTTP as the transport layer instead of HTTPS. That would have been nice of Microsoft to give us a way to override this mechanism easily, but they didn”t (and they didn”t bother to add an explicit error message in the thrown exception…)

So, if you want to send a plain-text username and password using WCF, the only way I found was to stuff the corresponding soap header when sending the request.

Here is my code, use it at your own risks…

public class SecurityBehavior : MessageHeader, IClientMessageInspector, IEndpointBehavior
{
     private string m_sUserName;
     private string m_sPassword;
     public override string Name        
     {            
        get { return "wsse:Security"; }
     }
 
     public override string Namespace        
     {            
        get { return ""; }
     }          
 
     public string UserName        
     {            
        get { return m_sUserName; }
        set { m_sUserName = value; }        
     }          
 
     public string Password        
     {            
        get { return m_sPassword; }            
        set { m_sPassword = value; }        
     }          
 
     public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)        
     {                      
 
     }          
 
     public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)        
     {              
        request.Headers.Add(this);
        return null;
     }          
 
     public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)        
     {                      
 
     }          
 
     public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)        
     {            
        clientRuntime.MessageInspectors.Add((IClientMessageInspector)this);
     }          
 
     public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)        
     {          
 
     }          
 
     public void Validate(ServiceEndpoint endpoint)        
     {          
 
     }          
 
     protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)        
     {            
        writer.WriteAttributeString("xmlns", "wsse", null, "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
        writer.WriteStartElement("wsse:UsernameToken");
        writer.WriteElementString("wsse:Username", m_sUserName);
        writer.WriteStartElement("wsse:Password");
        writer.WriteAttributeString("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
        writer.WriteValue(m_sPassword);                          
        writer.WriteEndElement(); //wsse:Password            
        writer.WriteEndElement(); //wsse:UsernameToken        
     }              
}

DZExtract LG DZ file format and extract tool lg ks20

Everything is in the title, just click on the link below to download the file.

Latest version : DZ Extract Version 0.2

Some details about the various format found in the DZ file.

DZ File format
Offset length (byte) Description
0x0 0x8 Magic code “MSTXMETX”
0x8 0x2 Unknown, same value in all files (value 0x01)
0xA 0x2 Separator ? (value 0x0)
0xC 0x2 Unknown, same value in all files (value 0x0B)
0xE 0x2 Separator ? (value 0x0)
0x10 0x6 Unknow, value differs from file to file
0x16 0x2 Unknown, same value in all files (value0x01C8)
0x18 0x8 String, phone model ? (value “KS20″)
0x20 0x50 String, file title ?
0x70 0x1C Two null terminated string concatened (“[chipmodel]\\0[osname]\\0″)
0x8C 0x80 String, DZ filename
0x10C 0x20 Separator (filled with 0xFF)
0x12C 0x10 Header MD5 hash
0x13C Variable Concatened subfiles (see Subfile format)
0x78 Offset Table, unknown useage
Optionnal data, present in some DZ file (unknown)

 

Subfile format
Offset length (byte) Description
0x0 0x4 Magic code “SSTX”
0x4 0x2 Unknown, same value for all subheaders (value 0x01)
0x6 0x2 Separator ? (value 0x0)
0x8 0x2 File Type ?
0xA 0x6 Separator ? (filled with 0x0)
0x10 0x4 Data length
0x14 0x80 Filename, null terminated string
0x94 0x10 Separator (filled with 0xFF)
0xA4 0x10 Uncompressed data MD5 hash
0xB4 0x10 Subheader MD5 Hash
0xC4 Data length Gzip compressed data

 

File type
Type Filename Description
0x3 amss.mbn AMSS modem
0x8 partition.mbn Partition table
0xA qcsblhd_cfgdata.mbn QCSBL header
0xB qcsbl.mbn QCSBL
0xC oemsblhd.mbn OEM boot header
0xD oemsbl.mbn OEM boot
0xE amsshd.mbn AMSS modem header
0x13 appsboothd.mbn APPS boot loader header
0x14 appsboot.mbn APPS boot loader
0x15 FLASH.bin Windows CE flash.bin
0x16 apps.mbn APPS