brdbootldr/ubootldr/display.cpp
author John Imhofe
Mon, 19 Oct 2009 15:55:17 +0100
changeset 0 a41df078684a
permissions -rw-r--r--
Convert Kernelhwsrv package from SFL to EPL kernel\eka\compsupp is subject to the ARM EABI LICENSE userlibandfileserver\fatfilenameconversionplugins\unicodeTables is subject to the Unicode license kernel\eka\kernel\zlib is subject to the zlib license

// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// bootldr\src\display\display.cpp
// 
//

#define FILE_ID	0x44495350
#define DEFINE_COLOURS

//
// Defining ENABLE_TRANSFER_STATS will display simplistic average and point
// transfer rates in bytes per second and provide an estimate of the length of
// time remaining.
//
#define ENABLE_TRANSFER_STATS

#include "bootldr.h"
#include <videodriver.h>
#include <hal.h>

TUint8* Screen;
TInt Screenwidth, Screenheight;		// screen dimentions in pixels
TInt XPos;
TInt YPos;
TUint Colours;
TUint PixelSize = 1;	// size of a pixel in bytes

TUint Progress[2];
TUint Pixels[2];
TUint Limit[2];
TUint32 ProgressTime[2];
TUint32 StartTime;

// Palette entries are in the platform's config.h
const TUint16 Palette[16]=	{
		KPaletteEntBlack		| KPaletteEntPBS,
		KPaletteEntMidBlue,		// 1
		KPaletteEntMidGreen,	// 2
		KPaletteEntMidCyan,		// 3
		KPaletteEntMidRed,		// 4
		KPaletteEntMidMagenta,	// 5
		KPaletteEntMidYellow,	// 6
		KPaletteEntDimWhite,	// 7
		KPaletteEntGray,		// 8
		KPaletteEntBlue,		// 9
		KPaletteEntGreen,		// 10 A
		KPaletteEntCyan,		// 11 B
		KPaletteEntRed,			// 12 C
		KPaletteEntMagenta,		// 13 D
		KPaletteEntYellow,		// 14 E
		KPaletteEntWhite 		// 15 F
		};

const TUint KRgbBlack		= 0x000000;
//const TUint KRgbDarkGray	= 0x555555;
const TUint KRgbDarkRed		= 0x800000;
const TUint KRgbDarkGreen	= 0x008000;
const TUint KRgbDarkYellow	= 0x808000;
const TUint KRgbDarkBlue	= 0x000080;
const TUint KRgbDarkMagenta	= 0x800080;
const TUint KRgbDarkCyan	= 0x008080;
const TUint KRgbRed			= 0xFF0000;
//const TUint KRgbGreen		= 0x00FF00;
const TUint KRgbYellow		= 0xFFFF00;
const TUint KRgbBlue		= 0x0000FF;
const TUint KRgbMagenta		= 0xFF00FF;
const TUint KRgbCyan		= 0x00FFFF;
const TUint KRgbGray		= 0xAAAAAA;
const TUint KRgbWhite		= 0xFFFFFF;

const TUint KRgbDimWhite    = 0xCCCCCC;

const TUint32 Palette32[16] =
{
    KRgbBlack,       // 0
    KRgbDarkBlue,    // 1
    KRgbDarkGreen,   // 2
    KRgbDarkCyan,    // 3
    KRgbDarkRed,     // 4
    KRgbDarkMagenta, // 5
    KRgbDarkYellow,  // 6
    KRgbDimWhite,    // 7 KRgbDarkGray()
    KRgbGray,        // 8
    KRgbBlue,        // 9
    KRgbDarkGreen,   // 10
    KRgbCyan,        // 11
    KRgbRed,         // 12
    KRgbMagenta,     // 13
    KRgbYellow,      // 14
    KRgbWhite        // 15
};

// KForeground, Kbackground and [I]Pcolour entries are indexes into the palette.
// The progress bar colours are of the form "(foreground << 8) | background"
const TUint8 KForeground = 15;
const TUint8 KBackground = 9;
const TUint PColour[2]={ 0xa08, 0xc08 };		//	(10|8) and (12|8)
const TUint IPColour[2]={ 0x809, 0x809 };		//	(8|9) and (8|9)

#define NUM_FONTS	96
#define FONT_HEIGHT	10
#define FONT_WIDTH	8

#define SCREEN_SIZE			(Screenheight*Screenwidth*PixelSize)			// number of pixels (size in bytes)

#define MAX_COLUMN			(Screenwidth/FONT_WIDTH)			// chars per line e.g. 80 or 40
#define MAX_ROW				(Screenheight/FONT_HEIGHT)			// lines per screen e.g. 48 or 24
#define PROGRESSBAR0_ROW	(MAX_ROW-1)							// row in which to draw progress bar 0
#define PROGRESSBAR1_ROW	(MAX_ROW-2)							// row in which to draw progress bar 1
#define STATS_ROW			(MAX_ROW-3)							// DEBUGGING row in which to write eta/bps
//
// ascii character code - 32 == character index into bootldr table
//
extern const TUint8 Font[NUM_FONTS][FONT_HEIGHT] =
 	{
		{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
		{0x30,0x78,0x78,0x78,0x30,0x00,0x30,0x00,0x00,0x00},	//!
		{0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
		{0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00,0x00,0x00},	//#
		{0x30,0x7C,0xC0,0x78,0x0C,0xF8,0x30,0x00,0x00,0x00},	//$
		{0x00,0xC6,0xCC,0x18,0x30,0x66,0xC6,0x00,0x00,0x00},
		{0x38,0x6C,0x38,0x76,0xDC,0xCC,0x76,0x00,0x00,0x00},
		{0x60,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
		{0x18,0x30,0x60,0x60,0x60,0x30,0x18,0x00,0x00,0x00},
		{0x60,0x30,0x18,0x18,0x18,0x30,0x60,0x00,0x00,0x00},
		{0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,0x00,0x00},
		{0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00,0x00,0x00},
		{0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x60,0x00,0x00},
		{0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0x00,0x00,0x00},	//-
		{0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00},	//.
		{0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00,0x00,0x00},	///

		{0x7C,0xC6,0xCE,0xDE,0xF6,0xE6,0x7C,0x00,0x00,0x00},	//0
		{0x30,0x70,0x30,0x30,0x30,0x30,0xFC,0x00,0x00,0x00},
		{0x78,0xCC,0x0C,0x38,0x60,0xCC,0xFC,0x00,0x00,0x00},
		{0x78,0xCC,0x0C,0x38,0x0C,0xCC,0x78,0x00,0x00,0x00},
		{0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x1E,0x00,0x00,0x00},
		{0xFC,0xC0,0xF8,0x0C,0x0C,0xCC,0x78,0x00,0x00,0x00},
		{0x38,0x60,0xC0,0xF8,0xCC,0xCC,0x78,0x00,0x00,0x00},
		{0xFC,0xCC,0x0C,0x18,0x30,0x30,0x30,0x00,0x00,0x00},
		{0x78,0xCC,0xCC,0x78,0xCC,0xCC,0x78,0x00,0x00,0x00},
		{0x78,0xCC,0xCC,0x7C,0x0C,0x18,0x70,0x00,0x00,0x00},	//9
		{0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,0x00,0x00},	//:
		{0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x60,0x00,0x00},	//;
		{0x18,0x30,0x60,0xC0,0x60,0x30,0x18,0x00,0x00,0x00},	//<
		{0x00,0x00,0xFC,0x00,0x00,0xFC,0x00,0x00,0x00,0x00},	//=
		{0x60,0x30,0x18,0x0C,0x18,0x30,0x60,0x00,0x00,0x00},	//>
		{0x78,0xCC,0x0C,0x18,0x30,0x00,0x30,0x00,0x00,0x00},	//?

		{0x7C,0xC6,0xDE,0xDE,0xDE,0xC0,0x78,0x00,0x00,0x00},	//@
		{0x30,0x78,0xCC,0xCC,0xFC,0xCC,0xCC,0x00,0x00,0x00},	//A
		{0xFC,0x66,0x66,0x7C,0x66,0x66,0xFC,0x00,0x00,0x00},	//B
		{0x3C,0x66,0xC0,0xC0,0xC0,0x66,0x3C,0x00,0x00,0x00},	//C
		{0xF8,0x6C,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00},	//D
		{0x7E,0x60,0x60,0x78,0x60,0x60,0x7E,0x00,0x00,0x00},	//E
		{0x7E,0x60,0x60,0x78,0x60,0x60,0x60,0x00,0x00,0x00},	//F
		{0x3C,0x66,0xC0,0xC0,0xCE,0x66,0x3E,0x00,0x00,0x00},	//G
		{0xCC,0xCC,0xCC,0xFC,0xCC,0xCC,0xCC,0x00,0x00,0x00},	//H
		{0x78,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00},	//I
		{0x1E,0x0C,0x0C,0x0C,0xCC,0xCC,0x78,0x00,0x00,0x00},	//J
		{0xE6,0x66,0x6C,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00},	//K
		{0x60,0x60,0x60,0x60,0x60,0x60,0x7E,0x00,0x00,0x00},	//L
		{0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0x00,0x00,0x00},	//M
		{0xC6,0xE6,0xF6,0xDE,0xCE,0xC6,0xC6,0x00,0x00,0x00},	//N
		{0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00},	//O

		{0xFC,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00,0x00,0x00},	//P
		{0x78,0xCC,0xCC,0xCC,0xDC,0x78,0x1C,0x00,0x00,0x00},	//Q
		{0xFC,0x66,0x66,0x7C,0x6C,0x66,0xE6,0x00,0x00,0x00},	//R
		{0x78,0xCC,0xE0,0x70,0x1C,0xCC,0x78,0x00,0x00,0x00},	//S
		{0xFC,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x00},	//T
		{0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xFC,0x00,0x00,0x00},	//U
		{0xCC,0xCC,0xCC,0xCC,0xCC,0x78,0x30,0x00,0x00,0x00},	//V
		{0xC6,0xC6,0xC6,0xD6,0xFE,0xEE,0xC6,0x00,0x00,0x00},	//W
		{0xC6,0xC6,0x6C,0x38,0x38,0x6C,0xC6,0x00,0x00,0x00},	//X
		{0xCC,0xCC,0xCC,0x78,0x30,0x30,0x78,0x00,0x00,0x00},	//Y
		{0xFE,0x06,0x0C,0x18,0x30,0x60,0xFE,0x00,0x00,0x00},	//Z
		{0x78,0x60,0x60,0x60,0x60,0x60,0x78,0x00,0x00,0x00},
		{0xC0,0x60,0x30,0x18,0x0C,0x06,0x02,0x00,0x00,0x00},
		{0x78,0x18,0x18,0x18,0x18,0x18,0x78,0x00,0x00,0x00},
		{0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00},
		{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00},

		{0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
		{0x00,0x00,0x78,0x0C,0x7C,0xCC,0x76,0x00,0x00,0x00},
		{0xE0,0x60,0x60,0x7C,0x66,0x66,0xDC,0x00,0x00,0x00},
		{0x00,0x00,0x78,0xCC,0xC0,0xCC,0x78,0x00,0x00,0x00},
		{0x1C,0x0C,0x0C,0x7C,0xCC,0xCC,0x76,0x00,0x00,0x00},
		{0x00,0x00,0x78,0xCC,0xFC,0xC0,0x78,0x00,0x00,0x00},
		{0x38,0x6C,0x60,0xF0,0x60,0x60,0xF0,0x00,0x00,0x00},
		{0x00,0x00,0x76,0xCC,0xCC,0x7C,0x0C,0xF8,0x00,0x00},
		{0xE0,0x60,0x6C,0x76,0x66,0x66,0xE6,0x00,0x00,0x00},
		{0x30,0x00,0x70,0x30,0x30,0x30,0x78,0x00,0x00,0x00},
		{0x0C,0x00,0x0C,0x0C,0x0C,0xCC,0xCC,0x78,0x00,0x00},
		{0xE0,0x60,0x66,0x6C,0x78,0x6C,0xE6,0x00,0x00,0x00},
		{0x70,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00},
		{0x00,0x00,0xCC,0xFE,0xFE,0xD6,0xC6,0x00,0x00,0x00},
		{0x00,0x00,0xF8,0xCC,0xCC,0xCC,0xCC,0x00,0x00,0x00},
		{0x00,0x00,0x78,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00},

		{0x00,0x00,0xDC,0x66,0x66,0x7C,0x60,0xF0,0x00,0x00},
		{0x00,0x00,0x76,0xCC,0xCC,0x7C,0x0C,0x1E,0x00,0x00},
		{0x00,0x00,0xDC,0x76,0x66,0x60,0xF0,0x00,0x00,0x00},
		{0x00,0x00,0x7C,0xC0,0x78,0x0C,0xF8,0x00,0x00,0x00},
		{0x10,0x30,0x7C,0x30,0x30,0x34,0x18,0x00,0x00,0x00},
		{0x00,0x00,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00},
		{0x00,0x00,0xCC,0xCC,0xCC,0x78,0x30,0x00,0x00,0x00},
		{0x00,0x00,0xC6,0xD6,0xFE,0xFE,0x6C,0x00,0x00,0x00},
		{0x00,0x00,0xC6,0x6C,0x38,0x6C,0xC6,0x00,0x00,0x00},
		{0x00,0x00,0xCC,0xCC,0xCC,0x7C,0x0C,0xF8,0x00,0x00},
		{0x00,0x00,0xFC,0x98,0x30,0x64,0xFC,0x00,0x00,0x00},
		{0x1C,0x30,0x30,0xE0,0x30,0x30,0x1C,0x00,0x00,0x00},
		{0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x00,0x00,0x00},
		{0xE0,0x30,0x30,0x1C,0x30,0x30,0xE0,0x00,0x00,0x00},
		{0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
		{0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00},
	};

inline void ColourPixel(TInt aXPos, TInt aYPos, TUint aColour)
/**
colour a pixel on the screen
@param aXPos	pixel's X coordinate
@param aYPos	pixel's Y coordinate
@param aColour	chosen colour specified as a palette index
*/
{
	TUint8* pV = (TUint8*)Screen + (aYPos * (Screenwidth * PixelSize)) + (aXPos * PixelSize);

	switch(PixelSize)
		{
		case 4:
			*(TUint32*)pV = Palette32[aColour];
			break;
		case 2:
			*pV++ = Palette[aColour] & 0xFF ;
			*pV = Palette[aColour] >> 8 ;
			break;
		case 1:
			*pV = aColour;
			break;
		default:
			// Kern::Fault("BOOTLDR colourpixel: Unsupported bpp", PixelSize);
			BOOT_FAULT();
		}
}

#ifndef USE_ASM_DISPLAYCHAR
void DisplayChar(TInt aChar, TInt aXPos, TInt aYPos, TUint aColours)
/**
Write a character to the framebuffer
@param aChar	Character to draw
@param aXPos	Character's column
@param aYPos	Character's row
@param aColour	Palette index specified (foreground << 8| background)
*/
	{
	// Convert the ascii value into an index for the Font table
	TInt tmpChar = aChar - 32;

	// Validate this is a valid font index
	if (tmpChar < 0 || tmpChar >= NUM_FONTS)
		return;

	// Validate coordinates lie within range.
	if (aXPos > MAX_COLUMN-1 || aYPos > MAX_ROW-1)
		return;

	// for each line of the font
	for (TUint line=0 ; line < FONT_HEIGHT ; line++)
		{
		TUint8 tmpLine = Font[tmpChar][line];
		TUint8 tmpMask = 0x80;
		// for each pixel of the line
		for (TUint pixel=0 ; pixel < FONT_WIDTH ; pixel++)
			{
			ColourPixel(aXPos * FONT_WIDTH + pixel,
						aYPos * FONT_HEIGHT + line,
						(tmpLine & tmpMask) ? aColours >> 8 : aColours & 0xFF);

			// Shift the mask one bit downward to examine the next pixel
			tmpMask = tmpMask >> 1;
			}
		}

	return;
	}
#endif


GLDEF_C void ClearScreen()
/**
Set all the pixels on the screen to the background
*/
	{
	for (TInt y = 0 ; y<Screenheight ; y++)
		for (TInt x = 0 ; x<Screenwidth ; x++)
			ColourPixel(x, y, KBackground);

	XPos=0;
	YPos=0;
	Colours=(KForeground<<8)|KBackground;
	}

void ScrollScreen()
/**
Move all the pixels in the scrolling text area up one line and fill the
last line with the background colour
*/
	{
	TUint8* pV=Screen;
	wordmove(pV, pV+(Screenwidth*PixelSize*FONT_HEIGHT), (Screenwidth*PixelSize*(Screenheight-(2*FONT_HEIGHT))-(Screenwidth*PixelSize*FONT_HEIGHT)));
	pV+=(Screenwidth*PixelSize*(Screenheight-(2*FONT_HEIGHT))-(Screenwidth*PixelSize*FONT_HEIGHT));

	TInt StartLine = (Screenheight-(4*FONT_HEIGHT));
	for (TInt y = StartLine ; y<(StartLine+FONT_HEIGHT) ; y++)
		for (TInt x = 0 ; x<Screenwidth ; x++)
			ColourPixel(x, y, KBackground);
	}

void ScrollScreenDown()
/**
Move all the pixels in the scrolling text area down one line and fill the
first line with the background colour
*/
	{
	TUint8* pV=Screen;
	wordmove(pV+(Screenwidth*PixelSize*FONT_HEIGHT), pV, (Screenwidth*PixelSize*(Screenheight-(2*FONT_HEIGHT))-(Screenwidth*PixelSize*FONT_HEIGHT)));

	for (TInt y = 0 ; y<FONT_HEIGHT ; y++)
		for (TInt x = 0 ; x<Screenwidth ; x++)
			ColourPixel(x, y, KBackground);

	}

void CurDown()
/**
Move the cursor down the screen, scrolling the text area if necessary
*/
	{
	if (++YPos==(MAX_ROW-3))
		{
		YPos=(MAX_ROW-4);
		ScrollScreen();
		}
	}

void CurUp()
/**
Move the cursor up the screen, scrolling the text area if necessary
*/
	{
	if (--YPos<0)
		{
		YPos=0;
		ScrollScreenDown();
		}
	}

void CurRight()
/**
Move the cursor along the screen, scrolling the text area if necessary
*/
	{
	if (++XPos==MAX_COLUMN)
		{
		XPos=0;
		CurDown();
		}
	}

void CurLeft()
/**
Move the cursor backwards along the screen, scrolling the text area if necessary
*/
	{
	if (--XPos<0)
		{
		XPos=MAX_COLUMN-1;
		CurUp();
		}
	}

void SetPos(TInt X, TInt Y)
/**
Set the cursor to a point on the screen
@param X	Character's column
@param Y	Character's row
*/
	{
	XPos=X;
	YPos=Y;
	}

void PutChar(TUint aChar)
/**
Write a character to the screen then moves the cursor to the next position,
scrolling the screen if necessary
@param aChar	Character to write
*/
	{
	switch (aChar)
		{
		case 0x08: CurLeft(); return;		// BS '\b'
		case 0x09: CurRight(); return;		// HT '\t'
		case 0x0a: CurDown(); return;		// LF '\n'
		case 0x0b: CurUp(); return;			// VT '\v'
		case 0x0c: ClearScreen(); return;	// FF '\f'
		case 0x0d: XPos=0; return;			// CR '\r'
		default: break;
		}
	DisplayChar(aChar,XPos,YPos,Colours);
	if (++XPos==MAX_COLUMN)					// chars per line
		{
		XPos=0;
		if (++YPos==(MAX_ROW-3))	// lines per screen - 3 for progress bars & stats
			{
			YPos=(MAX_ROW-4);		// lines per screen - 4
			ScrollScreen();
			}
		}
	}

GLDEF_C void PrintToScreen(TRefByValue<const TDesC> aFmt, ...)
	{
	VA_LIST list;
	VA_START(list,aFmt);

	TBuf<0x100> aBuf;
	aBuf.AppendFormatList(aFmt,list);
	PutString(aBuf);
	//RDebug::RawPrint(aBuf);
	}

void PutString(const TDesC& aBuf)
/**
For each character in the given string write it to the screen
@param aString	String of characters to write
*/
	{
	const TText* pS=aBuf.Ptr();
	const TText* pE=pS+aBuf.Length();
	if (pS!=pE)
		{
		while (pS<pE)
			PutChar(*pS++);
		}
	}

GLDEF_C void InitProgressBar(TInt aId, TUint aLimit, const TDesC& aBuf)
/**
Initialise a progress bar, writes a label and sets the pixels to the
background colour
@param aId		configure Bar0 or Bar1
@param aLimit	Sets the upper bound of the value given to Update
@param aTitle	Label to place before the progress bar (7 characters wide)
*/
	{
	const TText* aTitle=aBuf.Ptr();
	TInt line=aId ? PROGRESSBAR0_ROW : PROGRESSBAR1_ROW;
	Progress[aId]=0;
	if (aId==0)
			StartTime=0;

	Pixels[aId]=0;
	Limit[aId]=aLimit;
	char c;
	TInt x=0;
	while ((c=*aTitle++)!=0 && x<7)
		{
		DisplayChar(c,x,line,Colours);
		++x;
		}
	if (x<7)
		x=7;
	for (; x<(MAX_COLUMN-1); ++x)
		DisplayChar(0x7f,x,line,IPColour[aId]);
	}

GLDEF_C void UpdateProgressBar(TInt aId, TUint aProgress)
/**
Update a progress bar filling in the bar to a new position
If ENABLE_TRANSFER_STATS has been defined at build time the function will
generate some simple statistics.
@param aId			update Bar0 or Bar1
@param aProgress	The point value between 0 and the given aLimit
*/
	{
	TInt line=aId ? PROGRESSBAR0_ROW : PROGRESSBAR1_ROW;
	TUint old_pixels=Pixels[aId];

#ifdef ENABLE_TRANSFER_STATS
	// turn this on and get a few statistics as it loads
	if (aId==0) {
			if (StartTime == 0) {
					StartTime = User::NTickCount();
					ProgressTime[aId] = StartTime;
			}
			TUint avg_bps=0, bps=0, eta=0;
			TUint32 timenow = User::NTickCount();
			TUint32 delta_time = timenow - ProgressTime[aId];
			ProgressTime[aId] = timenow;
			if (delta_time) {
					bps = ((aProgress - Progress[aId]) * 1000) / delta_time;		// delta bytes / delta milliseconds

					delta_time = (timenow - StartTime);					// milliseconds since started
					if (delta_time) {
							avg_bps = ((TUint64)aProgress  * 1000) / delta_time;
							eta = (Limit[aId] - aProgress) / avg_bps;
					}
			}

			TInt savedXPos=XPos, savedYPos=YPos;
			XPos=0;
			YPos=STATS_ROW;
//			Printf("C/s avg: %7d point: %7d ETA: %d    ", avg_bps, bps, eta);
			PrintToScreen(_L("point: %7d ETA: %d    "), bps, eta);
			XPos=savedXPos;
			YPos=savedYPos;
	}
#endif

	Progress[aId]=aProgress;
	Int64 prog64=aProgress;
	prog64*=(Screenwidth - (8*FONT_WIDTH));		// screenwidth in pixels - 8 characters
	prog64/=Limit[aId];
	TUint pixels=(TUint)prog64;
	if (pixels>old_pixels)
		{
		Pixels[aId]=pixels;

		while (old_pixels<pixels)
			{
			for (TInt i=0; i<6; ++i)
				ColourPixel( old_pixels + (7*FONT_WIDTH), (line * FONT_HEIGHT) + 2 + i  , (PColour[aId]>>8));

			++old_pixels;
			}
		}
	}

void InitDisplay()
/**
Reads the properties of the screen from the HAL and configures the settings so
this driver can colour in pixels.
*/
    {
	TInt iDisplayMode;
	TInt iScreenAddress;
	TInt iBitsPerPixel;
	TInt iIsPalettized;
	TInt offset;

	HAL::Get(HAL::EDisplayMode, iDisplayMode);
	iBitsPerPixel = iDisplayMode; //getbpp needs the current mode as its param
	HAL::Get(HAL::EDisplayBitsPerPixel, iBitsPerPixel);	

	iIsPalettized = iDisplayMode; //ispalettized needs the current mode as its param
	HAL::Get(HAL::EDisplayIsPalettized, iIsPalettized);	

	HAL::Get(HAL::EDisplayMemoryAddress, iScreenAddress);
	
	offset = iDisplayMode;
	HAL::Get(HAL::EDisplayOffsetToFirstPixel, offset);
	iScreenAddress += offset;

	// get the dimentions of the screen
	HAL::Get(HAL::EDisplayXPixels, Screenwidth);
	HAL::Get(HAL::EDisplayYPixels, Screenheight);
	
	Screen = (TUint8 *)iScreenAddress;

#if 0
	RDebug::Printf("EDisplayMode %d", iDisplayMode);
	RDebug::Printf("EDisplayBitsPerPixel %d", iBitsPerPixel);
	RDebug::Printf("EDisplayIsPalettized %d", iIsPalettized);
	RDebug::Printf("EDisplayMemoryAddress 0x%x (after offset)", iScreenAddress);
	RDebug::Printf("EDisplayOffsetToFirstPixel  %d",offset);
	RDebug::Printf("EDisplayXPixels  %d",Screenwidth);
	RDebug::Printf("EDisplayYPixels  %d", Screenheight);
#endif
	
	// get the bits per pixel to work out the size
	if (iBitsPerPixel == 32)
		{
		PixelSize = 4;
		}
	else if (iBitsPerPixel == 16)
		{
		PixelSize = 2;
		}
	else if (iBitsPerPixel == 8)
		{
#if 0
		// derive where the palette is located - assumes when no offset to first
		// pixel the palette is at end of framebuffer.
		TUint8* pV;
		if(vidBuf().iOffsetToFirstPixel)
			pV=(TUint8*)(vidBuf().iVideoAddress);
		else
			pV=(TUint8*)(vidBuf().iVideoAddress)+SCREEN_SIZE;

		// Kern::Printf("Screenbuffer 0x%x palette 0x%x (%dx%d)",Screen,pV,Screenwidth,Screenheight);
		PixelSize = 1;
		memcpy(pV,Palette,32);
#endif
		}
	else
		{
		RDebug::Printf("BOOTLDR display: Unsupported bpp %d",iBitsPerPixel);
		BOOT_FAULT();
		}

	ClearScreen();
	}