[Scummvm-cvs-logs] CVS: scummvm/backends/ps2 DmaPipe.cpp,NONE,1.1 DmaPipe.h,NONE,1.1 Gs2dScreen.cpp,NONE,1.1 Gs2dScreen.h,NONE,1.1 GsDefs.h,NONE,1.1 asyncfio.cpp,NONE,1.1 asyncfio.h,NONE,1.1 cd.c,NONE,1.1 cd.h,NONE,1.1 fileio.cpp,NONE,1.1 fileio.h,NONE,1.1 icon.cpp,NONE,1.1 libkbd.cpp,NONE,1.1 ps2input.cpp,NONE,1.1 ps2input.h,NONE,1.1 ps2pad.cpp,NONE,1.1 ps2pad.h,NONE,1.1 savefile.cpp,NONE,1.1 savefile.h,NONE,1.1 sdlkeys.h,NONE,1.1 sjpcm.h,NONE,1.1 sysdefs.h,NONE,1.1 systemps2.cpp,NONE,1.1 systemps2.h,NONE,1.1

Robert Göffringmann lavosspawn at users.sourceforge.net
Wed Mar 30 21:35:58 CEST 2005


Update of /cvsroot/scummvm/scummvm/backends/ps2
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv21872/backends/ps2

Added Files:
	DmaPipe.cpp DmaPipe.h Gs2dScreen.cpp Gs2dScreen.h GsDefs.h 
	asyncfio.cpp asyncfio.h cd.c cd.h fileio.cpp fileio.h icon.cpp 
	libkbd.cpp ps2input.cpp ps2input.h ps2pad.cpp ps2pad.h 
	savefile.cpp savefile.h sdlkeys.h sjpcm.h sysdefs.h 
	systemps2.cpp systemps2.h 
Log Message:
Playstation2 Port: initial import

--- NEW FILE: DmaPipe.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2001-2004 The ScummVM project
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/backends/ps2/DmaPipe.cpp,v 1.1 2005/03/31 05:35:04 lavosspawn Exp $
 *
 */

// minimalistic gfx pipe implementation based on Vzzrzzn's GfxPipe.

#include <kernel.h>
#include <malloc.h>
#include "DmaPipe.h"
#include "GsDefs.h"

class SinglePipe {
public:
	SinglePipe(uint64 *buf, uint32 size);
	uint32 spaceLeft(void);
	void flush(void);
	void setGifRegListTag(uint8 numRegs, uint64 list);
	void setGifLoopTag(uint16 nLoop);
	void setReg(uint64 reg, uint64 value);
	void setListReg(uint64 value1, uint64 value2);
	void appendChain(uint64 dmaTag);
	void init(void);
	uint64 *_chainHead;
private:
	uint64 *_bufPos;
	uint16 *_chainSize;
	uint64 *_buf;
	uint32 _size;
};

DmaPipe::DmaPipe(uint32 size) {
	size &= ~0x1F;
	_buf = (uint64*)memalign(64, size);
	_curPipe = 0;
    _pipes[0] = new SinglePipe(_buf, size >> 4);
	_pipes[1] = new SinglePipe(_buf + (size >> 4), size >> 4);

	// reset DMAC Channel 2
	D2_CHCR = 0;
	D2_TADR = 0;
	D2_MADR = 0;
	D2_ASR1 = 0;
	D2_ASR0 = 0;
	D_STAT  = 0xFF1F;
	D_CTRL  = 0;
	D_PCR   = 0;
	D_SQWC  = 0;
	D_RBOR  = 0;
	D_RBSR  = 0;
	D_CTRL  = 1;
	if (!(D_STAT & CIM2)) // channel 2 interrupts enabled?
		D_STAT = CIM2;	  // enable them
	if (D_STAT & CIS2)	  // is there an old interrupt we have to acknowledge?
		D_STAT = CIS2;	  // do so...
	SifSetDChain();
}

void DmaPipe::uploadTex(uint32 dest, uint16 bufWidth, uint16 destOfsX, uint16 destOfsY, uint8 pixelFmt, const void *src, uint16 width, uint16 height) {

	checkSpace(5);
	*(_pipes[_curPipe]->_chainHead) &= 0xffffffff8fffffff; // change last chain tag id, from 'end' to 'cnt'
	*(_pipes[_curPipe]->_chainHead) |= (1 << 28);
	_pipes[_curPipe]->setGifLoopTag(4);
	_pipes[_curPipe]->setReg(GPR_BITBLTBUF, GS_SET_DEST_BLTBUF((dest/256) & 0x3fff, (bufWidth/64) & 0x3f, pixelFmt & 0x3f));
	_pipes[_curPipe]->setReg(	GPR_TRXPOS, GS_SET_DEST_TRXPOS(destOfsX, destOfsY));
	_pipes[_curPipe]->setReg(   GPR_TRXREG, GS_SET_TRXREG(width, height));
	_pipes[_curPipe]->setReg(   GPR_TRXDIR, 0);
	
	checkSpace(15);
	uint32 numq = width * height;
	switch (pixelFmt) {
		case GS_PSMCT32:
			numq = (numq + 3) >> 2; break;
		case GS_PSMCT24:
			numq = (numq + 2) / 3; break;
		case GS_PSMCT16:
		case GS_PSMCT16S:
			numq = (numq + 7) >> 3; break;
		case GS_PSMT8:
		case GS_PSMT8H:
			numq = (numq + 15) >> 4; break;
		case GS_PSMT4HL:
		case GS_PSMT4HH:
		case GS_PSMT4:
			numq = (numq + 31) >> 5; break;
		default:
			numq = 0;
	}
	uint64 texSrc = (uint32)src & 0x7fffffff;
	while (numq) {
		uint64 sendQuads = (numq <= 0x7FF0) ? numq : 0x7FF0;
		_pipes[_curPipe]->appendChain((1 << 28) | 1);
		_pipes[_curPipe]->appendChain(0x0800000000000000 + sendQuads); // IMAGE mode giftag. Flg = 10b, nloop = currq
		_pipes[_curPipe]->appendChain((texSrc << 32) | 0x0000000030000000 | sendQuads); // set up dma tag for image transfer. next = tex addr, id = 11b, qwc = numq
		numq -= sendQuads;
		texSrc += sendQuads * 16;
	}
	_pipes[_curPipe]->appendChain(0x0000000070000000); // next dma tag
	_pipes[_curPipe]->setGifLoopTag(1);
	_pipes[_curPipe]->setReg(GPR_TEXFLUSH, 1);
}

void DmaPipe::setTex(uint32 tex, uint32 texBufWidth, uint8 texPowW, uint8 texPowH, uint8 texPixFmt, uint32 clut, uint8 csm, uint32 clutBufWidth, uint32 clutPixFmt) {
	checkSpace(7);
	_pipes[_curPipe]->setGifLoopTag(6);
	_pipes[_curPipe]->setReg( GPR_TEXCLUT, 256 / 64);
	_pipes[_curPipe]->setReg(GPR_TEXFLUSH, 0);
	_pipes[_curPipe]->setReg(    GPR_TEXA, GS_SET_TEXA(128, 1, 0));
	_pipes[_curPipe]->setReg(  GPR_TEX1_1, GS_SET_TEX1(0, 0, FILTER_LINEAR, FILTER_LINEAR, 0, 0, 0));
	_pipes[_curPipe]->setReg(  GPR_TEX0_1, GS_SET_TEX0(tex / 256, texBufWidth / 64, texPixFmt, texPowW, texPowH, 1, 0, clut / 256, clutBufWidth / 64, csm, 0, 1));
	_pipes[_curPipe]->setReg( GPR_CLAMP_1, 0);
}

void DmaPipe::textureRect(uint16 x1, uint16 y1, uint16 u1, uint16 v1, uint16 x2, uint16 y2, uint16 u2, uint16 v2, uint16 z, uint32 colour) {
	checkSpace(4);
	_pipes[_curPipe]->setGifRegListTag( 6, 0xffffffffff535310);
	_pipes[_curPipe]->setListReg( GS_SET_PRIM(PR_SPRITE, 0, 1, 0, 1, 0, 1, 0, 0),
								  GS_SET_COLQ(colour));
	_pipes[_curPipe]->setListReg( GS_SET_UV(u1, v1),
								  GS_SET_XYZ(x1, y1, z));
	_pipes[_curPipe]->setListReg( GS_SET_UV(u2, v2),
								  GS_SET_XYZ(x2, y2, z));
}

void DmaPipe::textureRect(const GsVertex *p1, const GsVertex *p2, const GsVertex *p3, const GsVertex *p4, const TexVertex *t1, const TexVertex *t2, const TexVertex *t3, const TexVertex *t4, uint32 rgba) {
	checkSpace(6);
	_pipes[_curPipe]->setGifRegListTag(10, 0xffffff5353535310);

	_pipes[_curPipe]->setListReg( GS_SET_PRIM(PR_TRIANGLESTRIP, 0, 1, 0, 1, 0, 1, 0, 0),
								  GS_SET_COLQ(rgba));
	_pipes[_curPipe]->setListReg( GS_SET_UV(t1->u, t1->v),
								  GS_SET_XYZ(p1->x, p1->y, p1->z));
	_pipes[_curPipe]->setListReg( GS_SET_UV(t2->u, t2->v),
								  GS_SET_XYZ(p2->x, p2->y, p2->z));
	_pipes[_curPipe]->setListReg( GS_SET_UV(t3->u, t3->v),
								  GS_SET_XYZ(p3->x, p3->y, p3->z));
	_pipes[_curPipe]->setListReg( GS_SET_UV(t4->u, t4->v),
								  GS_SET_XYZ(p4->x, p4->y, p4->z));
}

/*void DmaPipe::flatRect(uint16 x1, uint16 y1, uint16 x2, uint16 y2, uint16 x3, uint16 y3, uint16 x4, uint16 y4, uint16 z, uint32 rgba) {
	checkSpace(4);
	_pipes[_curPipe]->setGifRegListTag( 6, 0xffffffffff555510);
	//_pipes[_curPipe]->setListReg( GS_SET_PRIM(PR_TRIANGLESTRIP, 0, 0, 0, 1, 0, 0, 0, 0),
	_pipes[_curPipe]->setListReg( GS_SET_PRIM(PR_TRIANGLESTRIP, 0, 0, 0, 0, 0, 0, 0, 0),
								  GS_SET_COLQ(rgba));
	_pipes[_curPipe]->setListReg( GS_SET_XYZ(x2, y2, z),
								  GS_SET_XYZ(x1, y1, z));
	_pipes[_curPipe]->setListReg( GS_SET_XYZ(x3, y3, z),
								  GS_SET_XYZ(x4, y4, z));
}*/

void DmaPipe::flatRect(const GsVertex *p1, const GsVertex *p2, const GsVertex *p3, const GsVertex *p4, uint32 rgba) {
	checkSpace(4);
	_pipes[_curPipe]->setGifRegListTag( 6, 0xffffffffff555510);
	_pipes[_curPipe]->setListReg( GS_SET_PRIM(PR_TRIANGLESTRIP, 0, 0, 0, 0, 0, 0, 0, 0),
								  GS_SET_COLQ(rgba));
	_pipes[_curPipe]->setListReg( GS_SET_XYZ(p1->x, p1->y, p1->z),
								  GS_SET_XYZ(p2->x, p2->y, p2->z));
	_pipes[_curPipe]->setListReg( GS_SET_XYZ(p3->x, p3->y, p3->z),
								  GS_SET_XYZ(p4->x, p4->y, p4->z));
}

void DmaPipe::flatRect(const GsVertex *p1, const GsVertex *p2, uint32 rgba) {
	checkSpace(3);
	_pipes[_curPipe]->setGifRegListTag( 4, 0xffffffffffff5510);
	_pipes[_curPipe]->setListReg( GS_SET_PRIM(PR_SPRITE, 0, 0, 0, 0, 0, 0, 0, 0),
								  GS_SET_COLQ(rgba));
	_pipes[_curPipe]->setListReg( GS_SET_XYZ(p1->x, p1->y, p1->z),
								  GS_SET_XYZ(p2->x, p2->y, p2->z));
}

void DmaPipe::setOrigin(uint16 x, uint16 y) {
	checkSpace(2);
	_pipes[_curPipe]->setGifLoopTag(1);
	_pipes[_curPipe]->setReg( GPR_XYOFFSET_1, GS_SET_XYOFFSET(x, y));
}

void DmaPipe::setAlphaBlend(AlphaBlendColor a, AlphaBlendColor b, AlphaBlendAlpha c, AlphaBlendColor d, uint8 fix) {
	checkSpace(2);
	_pipes[_curPipe]->setGifLoopTag(1);
	_pipes[_curPipe]->setReg(GPR_ALPHA_1, GS_SET_ALPHA(a, b, c, d, fix));
}

void DmaPipe::setConfig(uint8 prModeCont, uint8 dither, uint8 colClamp) {
	checkSpace(9);
	_pipes[_curPipe]->setGifLoopTag(8);

	// set some defaults
	// alpha blending formula: (A-B) * C + D
		// set: A = source pixel, b = 0, C = source alpha, D = destination pixel, fix = don't care
	//_pipes[_curPipe]->setReg(GPR_ALPHA_1, GS_SET_ALPHA(SOURCE_COLOR, ZERO_COLOR, SOURCE_ALPHA, DEST_COLOR, 0));
	// set: A = source pixel, b = dest pixel, C = source alpha, D = destination pixel, fix = don't care
	//_pipes[_curPipe]->setReg( GPR_ALPHA_1, GS_SET_ALPHA(SOURCE_COLOR, DEST_COLOR, SOURCE_ALPHA, DEST_COLOR, 0x7F));

	_pipes[_curPipe]->setReg(GPR_ALPHA_1, GS_SET_ALPHA(DEST_COLOR, ZERO_COLOR, SOURCE_ALPHA, SOURCE_COLOR, 0));
	_pipes[_curPipe]->setReg(   GPR_PRIM, 0);
	_pipes[_curPipe]->setReg(   GPR_PABE, 0); // alpha blending off
	_pipes[_curPipe]->setReg( GPR_TEST_1, GS_SET_TEST(0, 0, 0, 0, 0, 0, 1, 1)); // ztest off
	_pipes[_curPipe]->setReg( GPR_ZBUF_1, (uint64)1 << 32); // zbuffer off

	_pipes[_curPipe]->setReg( GPR_PRMODECONT, prModeCont & 1);
	_pipes[_curPipe]->setReg( GPR_DTHE, dither & 1);
	_pipes[_curPipe]->setReg( GPR_COLCLAMP, colClamp & 1);
}

void DmaPipe::setScissorRect(uint64 x1, uint64 y1, uint64 x2, uint64 y2) {
	checkSpace(2);
	_pipes[_curPipe]->setGifLoopTag(1);
	_pipes[_curPipe]->setReg( GPR_SCISSOR_1, GS_SET_SCISSOR(x1, x2, y1, y2));
}

void DmaPipe::setDrawBuffer(uint64 base, uint64 width, uint8 pixelFmt, uint64 mask) {
	checkSpace(2);
	_pipes[_curPipe]->setGifLoopTag(1);
	_pipes[_curPipe]->setReg( GPR_FRAME_1, GS_SET_FRAME(base / 8192, width / 64, pixelFmt, mask));
}

void DmaPipe::checkSpace(uint32 needed) {
	if (_pipes[_curPipe]->spaceLeft() < (needed << 1))
		flush();
}

void DmaPipe::waitForDma(void) {
	while (D2_CHCR & 0x100) {}
}

void DmaPipe::flush(void) {
	waitForDma();
	FlushCache(0);
	_pipes[_curPipe]->flush();
	_curPipe ^= 1;
	_pipes[_curPipe]->init();
}

SinglePipe::SinglePipe(uint64 *buf, uint32 size) {
	_buf = buf;
	_size = size;
	init();
}

void SinglePipe::flush(void) {
	D2_TADR = (uint32)_buf;
	D2_QWC  = 0;
	D2_CHCR |= 0x185;
}

void SinglePipe::init(void) {
	_buf[0] = 0x0000000070000000;
	_buf[1] = 0;
	_chainHead = _buf;
	_chainSize = (uint16*)_chainHead;
	_bufPos = _buf + 2;
}

uint32 SinglePipe::spaceLeft(void) {
	return (_size - (_bufPos - _buf));
}

void SinglePipe::appendChain(uint64 dmaTag) {
	_chainHead = _bufPos;
	_chainHead[0] = dmaTag;
	_chainHead[1] = 0;
	_chainSize = (uint16*)_chainHead;
	_bufPos += 2;
}

void SinglePipe::setReg(uint64 reg, uint64 value) {
	*_bufPos++ = value;
	*_bufPos++ = reg;
    (*_chainSize)++;
}

void SinglePipe::setListReg(uint64 value1, uint64 value2) {
	*_bufPos++ = value1;
	*_bufPos++ = value2;
	(*_chainSize)++;
}

void SinglePipe::setGifRegListTag(uint8 numRegs, uint64 list) {
	*_bufPos++ = GIF_SET_TAG(1, 1, 0, 0, 1, 0) | ((uint64)numRegs << 60);
	*_bufPos++ = list;
	(*_chainSize)++;
}

void SinglePipe::setGifLoopTag(uint16 nLoop) {
	*_bufPos++ = GIF_SET_TAG(0, 1, 0, 0, 0, 1) | nLoop;
	*_bufPos++ = 0xfffffffffffffffe;
	(*_chainSize)++;
}

--- NEW FILE: DmaPipe.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2001-2004 The ScummVM project
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/backends/ps2/DmaPipe.h,v 1.1 2005/03/31 05:35:04 lavosspawn Exp $
 *
 */

// minimalistic gfx pipe implementation based on Vzzrzzn's GfxPipe.

#ifndef __DMAPIPE_H__
#define __DMAPIPE_H__

#include "sysdefs.h"
#include "backends/ps2/GsDefs.h"

class SinglePipe;

struct GsVertex {
	uint16 x, y, z;
};

struct TexVertex {
	uint16 u, v;
};

class DmaPipe {
public:
	DmaPipe(uint32 size);
	void uploadTex(uint32 dest, uint16 bufWidth, uint16 destOfsX, uint16 destOfsY, uint8 pixelFmt, const void *src, uint16 width, uint16 height);
	void setTex(uint32 tex, uint32 texBufWidth, uint8 texPowW, uint8 texPowH, uint8 texPixFmt, uint32 clut, uint8 csm, uint32 clutBufWidth, uint32 clutPixFmt);
	void setDrawBuffer(uint64 base, uint64 width, uint8 pixelFmt, uint64 mask);
	void textureRect(uint16 x1, uint16 y1, uint16 u1, uint16 v1, uint16 x2, uint16 y2, uint16 u2, uint16 v2, uint16 z, uint32 colour);
	void textureRect(const GsVertex *p1, const GsVertex *p2, const GsVertex *p3, const GsVertex *p4, const TexVertex *t1, const TexVertex *t2, const TexVertex *t3, const TexVertex *t4, uint32 rgba);
	void flatRect(const GsVertex *p1, const GsVertex *p2, const GsVertex *p3, const GsVertex *p4, uint32 rgba);
	void flatRect(const GsVertex *p1, const GsVertex *p2, uint32 rgba);

	void setOrigin(uint16 x, uint16 y);
	void setConfig(uint8 prModeCont, uint8 dither, uint8 colClamp);
	void setScissorRect(uint64 x1, uint64 y1, uint64 x2, uint64 y2);
	void setAlphaBlend(AlphaBlendColor a, AlphaBlendColor b, AlphaBlendAlpha c, AlphaBlendColor d, uint8 fix);
	void flush(void);
	void waitForDma(void);
private:
	void checkSpace(uint32 needed);
	uint64 *_buf;
	uint8 _curPipe;
	SinglePipe *_pipes[2];
};

#endif //__DMAPIPE_H__


--- NEW FILE: Gs2dScreen.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2001-2004 The ScummVM project
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/backends/ps2/Gs2dScreen.cpp,v 1.1 2005/03/31 05:35:04 lavosspawn Exp $
 *
 */

#include "Gs2dScreen.h"
#include <kernel.h>
#include <malloc.h>
#include <string.h>
#include <assert.h>
#include <fileio.h>
#include <math.h> // for sqrt()
#include "DmaPipe.h"
#include "GsDefs.h"
#include <sio.h>

enum Buffers {
	SCREEN = 0,
	MOUSE,
	TEXT
};

#define DEFAULT_PAL_X		175
#define DEFAULT_PAL_Y		40
#define DEFAULT_NTSC_X		165
#define DEFAULT_NTSC_Y		45
#define ORG_X 256
#define ORG_Y 256
#define ORIGIN_X (ORG_X << 4)
#define ORIGIN_Y (ORG_Y << 4)
#define TEX_POW 10

#define SCALE(x) ((x) << 4)
#define COORD_XY(x, y) SCALE((x) + ORG_X), SCALE((y) + ORG_Y)
#define COORD_UV(u, v) SCALE(u), SCALE(v)

/*#define COORD_X1(x)		SCALE((x) + ORG_X + GS_RECT_OFFSET)
#define COORD_Y1(y)		SCALE((y) + ORG_Y + GS_RECT_OFFSET)
#define COORD_X2(x)		SCALE((x) + ORG_X - GS_RECT_OFFSET)
#define COORD_Y2(y)		SCALE((y) + ORG_Y - GS_RECT_OFFSET)
#define COORD_XY1(x, y) COORD_X1(x), COORD_Y1(y)
#define COORD_XY2(x, y) COORD_X2(x), COORD_Y2(y)*/

#define M_SIZE 128
#define M_POW 7

#define PI 3.1415926535897932384626433832795

static volatile uint32 g_VblankCmd, g_DmacCmd;

int32 vblankHandler(int32 cause) {
	// start of VBlank period
	if (g_VblankCmd) {			  // is there a new image waiting?
		GS_DISPFB1 = g_VblankCmd; // show it.
		g_VblankCmd = 0;
	}
	return 0;
}

int32 dmacHandler(int32 channel) {
	if (g_DmacCmd && (channel == 2)) { // GS DMA transfer finished,
		g_VblankCmd = g_DmacCmd;	   // we want to show the image
		g_DmacCmd = 0;				   // when the next vblank occurs
	}
	return 0;
}

void createAnimThread(Gs2dScreen *screen);

Gs2dScreen::Gs2dScreen(uint16 width, uint16 height, TVMode tvMode) {

	g_DmacCmd = g_VblankCmd = 0;
	AddIntcHandler(INT_VBLANK_START, vblankHandler, 0);
	AddDmacHandler(2, dmacHandler, 0);	 // 2 = 2nd dma channel = EE <-> GS

	_dmaPipe = new DmaPipe(0x2000);

	EnableIntc(INT_VBLANK_START);
    EnableDmac(2);

	_width = width;
	_height = height;
	_pitch = (width + 127) & ~127;

	_screenBuf = (uint8*)memalign(64, _width * _height);
	_overlayBuf = (uint16*)memalign(64, _width * _height * 2);
	_clut = (uint32*)memalign(64, 256 * 4);

	memset(_screenBuf, 0, _width * _height);
	for (uint32 cnt = 0; cnt < 256; cnt++)
		_clut[cnt] = GS_RGBA(0, 0, 0, 0x80);
	clearOverlay();

	if (tvMode == TV_DONT_CARE) {
		if (PAL_NTSC_FLAG == 'E')
			_videoMode = TV_NTSC;
		else
			_videoMode = TV_PAL;
	} else
		_videoMode = tvMode;

	printf("Setting up %s mode\n", (_videoMode == TV_PAL) ? "PAL" : "NTSC");

    // set screen size, 640x576 for pal, 640x448 for ntsc
	_tvWidth = 640;
	_tvHeight = ((_videoMode == TV_PAL) ? 576 : 448);
	
	uint32 tvFrameSize = _tvWidth * _tvHeight * 4;  // 32 bits per pixel

	// setup frame buffer pointers
	_frameBufPtr[0] = 0;
	_frameBufPtr[1] = tvFrameSize;
	_clutPtrs[SCREEN] = tvFrameSize * 2;
	_clutPtrs[MOUSE]  = _clutPtrs[SCREEN] + 0x1000; // the cluts in PSMCT32 take up half a memory page each
	_clutPtrs[TEXT]   = _clutPtrs[SCREEN] + 0x2000;
	_texPtrs[SCREEN]  = _clutPtrs[SCREEN] + 0x3000;
	_texPtrs[TEXT]    = 0;
	_texPtrs[MOUSE]	  = 128 * 128 * 4;			  // mouse cursor is loaded into the gaps of the frame buffer

	_showOverlay = true;
	_showMouse = false;
	_mouseScaleX = (_tvWidth << 8) / _width;
	_mouseScaleY = (_tvHeight << 8) / _height;
	setMouseXy(_width / 2, _height / 2);
	_mTraCol = 255;
	_shakePos = 0;

	// setup hardware now.
	GS_CSR = GS_SET_CSR(0, 0, 0, 0, 0, 1, 0);
	asm ("sync.p");
	GS_CSR = 0;
	GsPutIMR(0xFF00);

	uint16 dispPosX, dispPosY;

	if (_videoMode == TV_PAL) {
		SetGsCrt(GS_INTERLACED, 3, 0);
		dispPosX = DEFAULT_PAL_X;
		dispPosY = DEFAULT_PAL_Y;
	} else {
		SetGsCrt(GS_INTERLACED, 2, 0);
		dispPosX = DEFAULT_NTSC_X;
		dispPosY = DEFAULT_NTSC_Y;
	}

	asm("di");
	GS_PMODE = GS_SET_PMODE(1, 0, 1, 1, 0, 255);
	GS_BGCOLOUR = GS_RGBA(0, 0, 0, 0);
	GS_DISPLAY1 = GS_SET_DISPLAY(_tvWidth, _tvHeight, dispPosX, dispPosY);
	asm("ei");

	_curDrawBuf = 0;

	_dmaPipe->setOrigin(ORIGIN_X, ORIGIN_Y);
	_dmaPipe->setConfig(1, 0, 1);
	_dmaPipe->setScissorRect(0, 0, _tvWidth - 1, _tvHeight - 1);
	_dmaPipe->setDrawBuffer(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24, 0);

	_clutChanged = _screenChanged = _overlayChanged = true;
	updateScreen();
	
	createAnimTextures();

	ee_sema_t newSema;
	newSema.init_count = 1;
	newSema.max_count = 1;
	_screenSema = CreateSema(&newSema);
	
	newSema.init_count = 0;
	_timerSema = CreateSema(&newSema);

	if ((_screenSema < 0) || (_timerSema < 0)) {
		printf("Can't create semaphores.\n");
		SleepThread();
	}	

	createAnimThread(this);
}

void Gs2dScreen::createAnimTextures(void) {
	uint8 *buf = (uint8*)memalign(64, 14 * 64);
	uint32 vramDest = _texPtrs[TEXT];
	for (int i = 0; i < 16; i++) {
		uint32 *destPos = (uint32*)buf;
		for (int ch = 15; ch >= 0; ch--) {
			uint32 *src = (uint32*)(_binaryData + ((_binaryPattern[i] >> ch) & 1) * 4 * 14);
			for (int line = 0; line < 14; line++)
				destPos[line << 4] = src[line];
			destPos++;
		}
		if (!(i & 1))
			_dmaPipe->uploadTex( vramDest, 128, 0, 0,  GS_PSMT4HH, buf, 128, 14);
		else {
			_dmaPipe->uploadTex( vramDest, 128, 0, 0,  GS_PSMT4HL, buf, 128, 14);
			vramDest += 128 * 16 * 4;
		}
		_dmaPipe->flush();
		_dmaPipe->waitForDma();
	}
	_dmaPipe->uploadTex(_clutPtrs[TEXT], 64, 0, 0, GS_PSMCT32, _binaryClut, 8, 2);
	free(buf);
}

void Gs2dScreen::newScreenSize(uint16 width, uint16 height) {
	if ((width == _width) && (height == _height))
		return;

	printf("New screen size %d/%d\n", width, height);
	_dmaPipe->flush();
	_screenChanged = _overlayChanged = false;
	_width = width;
	_height = height;
	_pitch = (width + 127) & ~127;
	waitForImage(); // if there's a frame waiting to be shown, wait for vblank handler
	
	// now malloc new buffers
	free(_screenBuf);
	free(_overlayBuf);
	_screenBuf = (uint8*)memalign(64, _width * _height);
	memset(_screenBuf, 0, _width * height);
	_overlayBuf = (uint16*)memalign(64, _width * _height * 2);
	memset(_overlayBuf, 0, _width * height * 2);
	_screenChanged = _overlayChanged = true;

	_mouseScaleX = (_tvWidth << 8) / _width;
	_mouseScaleY = (_tvHeight << 8) / _height;
	setMouseXy(_width / 2, _height / 2);
	printf("done\n");
}

void Gs2dScreen::copyScreenRect(const uint8 *buf, uint16 pitch, uint16 x, uint16 y, uint16 w, uint16 h) {
	waitForDma();

	assert((x + w <= _width) && (y + h <= _height));
	uint8 *dest = _screenBuf + y * _width + x;
	for (uint16 cnt = 0; cnt < h; cnt++) {
		memcpy(dest, buf, w);
		buf += pitch;
		dest += _width;
	}
	_screenChanged = true;
}

void Gs2dScreen::setPalette(const uint32 *pal, uint8 start, uint16 num) {
	waitForDma();

	assert(start + num <= 256);
	for (uint16 cnt = 0; cnt < num; cnt++) {
		uint16 dest = start + cnt;
		dest = (dest & 0x7) | ((dest & 0x8) << 1) | ((dest & 0x10) >> 1) | (dest & 0xE0); // rearrange like the GS expects it
		_clut[dest] = pal[cnt] & 0xFFFFFF;
	}
	_clutChanged = true;
}

void Gs2dScreen::updateScreen(void) {
	/* we can't draw more than 50 images on PAL and 60 on NTSC, wait until the other buffer is shown.
	   especcially necessary for BS2 which does hundreds of updateScreen()s per second */
	waitForImage();
	
	WaitSema(_screenSema);

	if (_clutChanged) {
		_clutChanged = false;
		uint32 tmp = _clut[_mTraCol];
		_clut[_mTraCol] = GS_RGBA(0, 0, 0, 0x80); // this mouse color is transparent
		_dmaPipe->uploadTex(_clutPtrs[MOUSE], 64, 0, 0, GS_PSMCT32, _clut, 16, 16);
		_dmaPipe->flush();
		_dmaPipe->waitForDma();
		_clut[_mTraCol] = tmp;

		_dmaPipe->uploadTex(_clutPtrs[SCREEN], 64, 0, 0, GS_PSMCT32, _clut, 16, 16);
	}

	drawScreen();

	g_DmacCmd = GS_SET_DISPFB(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24); // put it here for dmac/vblank handler
	_dmaPipe->flush();
	_curDrawBuf ^= 1;
	_dmaPipe->setDrawBuffer(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24, 0);
	SignalSema(_screenSema);
}

void Gs2dScreen::drawScreen(void) {
	static GsVertex fullScreen[2] = {
		{ COORD_XY(0, 0), SCALE(0) },
		{ COORD_XY(_tvWidth, _tvHeight), SCALE(0) }
	};

	_dmaPipe->flatRect(fullScreen + 0, fullScreen + 1, GS_RGBA(0, 0, 0, 0)); // clear screen

	if (_showOverlay) {
		if (_overlayChanged) {
			_dmaPipe->uploadTex(_texPtrs[SCREEN], _width, 0, 0, GS_PSMCT16, _overlayBuf, _width, _height);
			_overlayChanged = false;
		}
		_dmaPipe->setTex(_texPtrs[SCREEN], _width, TEX_POW, TEX_POW, GS_PSMCT16, 0, 0, 0, 0);
		_dmaPipe->textureRect(COORD_XY(0, 0), COORD_UV(1, 1), 
			COORD_XY(_tvWidth, _tvHeight), COORD_UV(_width, _height), 0, GS_RGBA(0x80, 0x80, 0x80, 0x80));
	} else {
		if (_screenChanged) {
			_dmaPipe->uploadTex(_texPtrs[SCREEN], _pitch, 0, 0, GS_PSMT8, _screenBuf, _width, _height);
			_screenChanged = false;
		}
		_dmaPipe->setTex(_texPtrs[SCREEN], _pitch, TEX_POW, TEX_POW, GS_PSMT8, _clutPtrs[SCREEN], 0, 64, GS_PSMCT32);
		_dmaPipe->textureRect(COORD_XY(0, -_shakePos), COORD_UV(1, 1), 
			COORD_XY(_tvWidth, _tvHeight - _shakePos), COORD_UV(_width, _height), 0, GS_RGBA(0x80, 0x80, 0x80, 0x80));
	}

	if (_showMouse) {
		_dmaPipe->setTex(_texPtrs[MOUSE], M_SIZE, M_POW, M_POW, GS_PSMT8H, _clutPtrs[MOUSE], 0, 64, GS_PSMCT32);
		uint16 mpX1 = (((_mouseX - _hotSpotX) * _mouseScaleX + 128) >> 4) + ORIGIN_X;
		uint16 mpY1 = (((_mouseY - _hotSpotY) * _mouseScaleY + 128) >> 4) + ORIGIN_Y;
		uint16 mpX2 = mpX1 + ((M_SIZE * _mouseScaleX + 128) >> 4);
		uint16 mpY2 = mpY1 + ((M_SIZE * _mouseScaleY + 128) >> 4);
		_dmaPipe->textureRect(mpX1, mpY1, COORD_UV(0, 0), 
			mpX2, mpY2, COORD_UV(M_SIZE - 1, M_SIZE - 1), 0, GS_RGBA(0x80, 0x80, 0x80, 0x80));
	}
}

void Gs2dScreen::showOverlay(void) {
	_showOverlay = true;
	clearOverlay();
}

void Gs2dScreen::hideOverlay(void) {
	_screenChanged = true;
	_showOverlay = false;
}

void Gs2dScreen::setShakePos(int shake) {
	_shakePos = (shake * _mouseScaleY) >> 8;
}

void Gs2dScreen::copyOverlayRect(const uint16 *buf, uint16 pitch, uint16 x, uint16 y, uint16 w, uint16 h) {
	waitForDma();

	_overlayChanged = true;
	uint16 *dest = _overlayBuf + y * _width + x;
	for (uint32 cnt = 0; cnt < h; cnt++) {
		memcpy(dest, buf, w * 2);
		dest += _width;
		buf += pitch;
	}
}

void Gs2dScreen::clearOverlay(void) {
	waitForDma();
	
	_overlayChanged = true;
	// first convert our clut to 16 bit RGBA for the overlay...
	uint16 palette[256];
	for (uint32 cnt = 0; cnt < 256; cnt++) {
		uint32 rgba = _clut[(cnt & 0x7) | ((cnt & 0x8) << 1) | ((cnt & 0x10) >> 1) | (cnt & 0xE0)];
		palette[cnt] = ((rgba >> 3) & 0x1F) | (((rgba >> 11) & 0x1F) << 5) | (((rgba >> 19) & 0x1F) << 10);
	}
	// now copy the current screen over
	for (uint32 cnt = 0; cnt < _width * _height; cnt++)
		_overlayBuf[cnt] = palette[_screenBuf[cnt]];
}

void Gs2dScreen::grabOverlay(uint16 *buf, uint16 pitch) {
	uint16 *src = _overlayBuf;
	for (uint32 cnt = 0; cnt < _height; cnt++) {
		memcpy(buf, src, _width * 2);
		buf += pitch;
        src += _width;
	}	
}

void Gs2dScreen::setMouseOverlay(const uint8 *buf, uint16 width, uint16 height, uint16 hotSpotX, uint16 hotSpotY, uint8 transpCol) {
	assert((width <= M_SIZE) && (height <= M_SIZE));

	_hotSpotX = hotSpotX;
	_hotSpotY = hotSpotY;
	if (_mTraCol != transpCol) {
		_mTraCol = transpCol;
		_clutChanged = true;
	}
	uint8 *bufCopy = (uint8*)memalign(64, M_SIZE * M_SIZE); // make a copy to align to 64 bytes
	memset(bufCopy, _mTraCol, M_SIZE * M_SIZE);
	for (int cnt = 0; cnt < height; cnt++)
		memcpy(bufCopy + cnt * M_SIZE, buf + cnt * width, width);

	_dmaPipe->uploadTex( _texPtrs[MOUSE], M_SIZE, 0, 0,  GS_PSMT8H, bufCopy, M_SIZE, M_SIZE);
	_dmaPipe->flush();
	_dmaPipe->waitForDma(); // make sure all data has been transferred when we free bufCopy
	free(bufCopy);
}

void Gs2dScreen::waitForDma(void) {
	// wait until dma transfer finished
	while (g_DmacCmd)
		;
}

void Gs2dScreen::waitForImage(void) {
	/* if there's an image waiting to be shown on next vblank, wait for it.
	   however, first we must wait for the dma transfer (if running) as it will
	   result in a new image */
	waitForDma();
	while (g_VblankCmd)
		;
	/* both waitForImage and waitForDma should only get called by the main thread,
	   so they may be implemented as busy waits, as both the timer- and sound-thread have
	   a higher priority than this one. There's no thread we could switch to anyways... */
}

void Gs2dScreen::showMouse(bool show) {
	_showMouse = show;
}

void Gs2dScreen::setMouseXy(int16 x, int16 y) {
	_mouseX = x;
	_mouseY = y;
}

uint8 Gs2dScreen::tvMode(void) {
	return _videoMode;
}

#define LINE_SPACE 20
#define SCRL_TIME 8
#define V 1000
#define Z_TRANSL 65

void Gs2dScreen::wantAnim(bool runIt) {
	_runAnim = runIt;
}

void Gs2dScreen::animThread(void) {
	// animate zeros and ones while game accesses memory card, etc.
	_runAnim = false;
	float yPos   = 0.0;
	uint8 texSta = 0;
	float scrlSpeed = (_videoMode == TV_PAL) ? (_tvHeight / (SCRL_TIME * 50.0)) : (_tvHeight / (SCRL_TIME * 60.0));
	uint8 texMax = (_tvHeight / LINE_SPACE) + (ORG_Y / LINE_SPACE);
	TexVertex texNodes[4] = {
		{ COORD_UV(  0,  0) }, { COORD_UV(  0, 14) },
		{ COORD_UV(128,  0) }, { COORD_UV(128, 14) }
	};
	float angleStep = ((2 * PI) / _tvHeight);

	while (1) {
		WaitSema(_timerSema);
		if (_runAnim && !g_DmacCmd && !g_VblankCmd) {
			if (PollSema(_screenSema) > 0) {
				drawScreen(); // draw the last screen the engine did again

				_dmaPipe->setAlphaBlend(SOURCE_COLOR, ZERO_COLOR, SOURCE_ALPHA, DEST_COLOR, 0);
				yPos -= scrlSpeed;
				if (yPos <= -LINE_SPACE) {
					yPos += LINE_SPACE;
					texSta++;
				}

				float drawY = yPos;

				for (int i = 0; i < texMax; i++) {
					uint8 texIdx = (texSta + i) & 0xF;

					float x[4] = { -64.0, -64.0, 64.0, 64.0 };
					float y[4];
					y[0] = y[2] = drawY - _tvHeight / 2 - LINE_SPACE / 2;
					y[1] = y[3] = y[0] + LINE_SPACE;
					float z[4] = { 0.0, 0.0, 0.0, 0.0 };
					GsVertex nodes[4];

					float angle = PI / 2 + angleStep * drawY;
					float rotSin = sinf(angle);
					float rotCos = cosf(angle);
					for (int coord = 0; coord < 4; coord++) {
						z[coord] = rotCos * x[coord];
						x[coord] = rotSin * x[coord];
					
						nodes[coord].z = 0;
						nodes[coord].x = (uint16)(((V * x[coord]) / (z[coord] + V + Z_TRANSL)) * 16);
						nodes[coord].y = (uint16)(((V * y[coord]) / (z[coord] + V + Z_TRANSL)) * 16);
						nodes[coord].x += SCALE(_tvWidth - 80 + ORG_X);
						nodes[coord].y += SCALE(_tvHeight / 2 + ORG_Y);
					}

					uint32 texPtr = _texPtrs[TEXT] + 128 * 16 * 4 * (texIdx >> 1);
					if (texIdx & 1)
						_dmaPipe->setTex(_texPtrs[TEXT], 128, 7, 4, GS_PSMT4HL, _clutPtrs[TEXT], 0, 64, GS_PSMCT32);
					else
						_dmaPipe->setTex(_texPtrs[TEXT], 128, 7, 4, GS_PSMT4HH, _clutPtrs[TEXT], 0, 64, GS_PSMCT32);
					
					_dmaPipe->textureRect(nodes + 0, nodes + 1, nodes + 2, nodes + 3,
						texNodes + 0, texNodes + 1, texNodes + 2, texNodes + 3, GS_RGBA(0x80, 0x80, 0x80, 0x80));

					drawY += LINE_SPACE;
				}
				g_DmacCmd = GS_SET_DISPFB(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24); // put it here for dmac/vblank handler
				_dmaPipe->flush();
				_curDrawBuf ^= 1;
				_dmaPipe->setDrawBuffer(_frameBufPtr[_curDrawBuf], _tvWidth, GS_PSMCT24, 0);
				_dmaPipe->setAlphaBlend(DEST_COLOR, ZERO_COLOR, SOURCE_ALPHA, SOURCE_COLOR, 0);
				SignalSema(_screenSema);
			}
		}
	}
}

void Gs2dScreen::timerTick(void) {
	if (_runAnim)
		SignalSema(_timerSema);
}

void runAnimThread(Gs2dScreen *param) {
	param->animThread();
}

#define ANIM_STACK_SIZE (1024 * 32)

void createAnimThread(Gs2dScreen *screen) {
	ee_thread_t animThread, thisThread;
	ReferThreadStatus(GetThreadId(), &thisThread);

	animThread.initial_priority = thisThread.current_priority - 1;
	animThread.stack = malloc(ANIM_STACK_SIZE);
	animThread.stack_size = ANIM_STACK_SIZE;
	animThread.func = (void *)runAnimThread;
	//animThread.gp_reg = _gp;		for some reason _gp is always NULL
	asm("move %0, $gp\n": "=r"(animThread.gp_reg));

	int tid = CreateThread(&animThread);
	if (tid >= 0) {
		StartThread(tid, screen);
	} else
		free(animThread.stack);
}

// data for the animated zeros and ones...
const uint8 Gs2dScreen::_binaryData[4 * 14 * 2] = {
	// figure zero
	0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x22, 0x22, 0x00, 0x31, 0x13,
	0x31, 0x13, 0x20, 0x02, 0x22, 0x02, 0x31, 0x13, 0x33, 0x13, 0x20, 0x02, 0x20, 0x02,
	0x31, 0x33, 0x31, 0x13, 0x20, 0x22, 0x20, 0x02, 0x31, 0x13, 0x31, 0x13, 0x00, 0x22,
	0x22, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11,
	// figure one
	0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x20, 0x02, 0x00, 0x11, 0x33,
	0x13, 0x11, 0x22, 0x22, 0x02, 0x00, 0x11, 0x31, 0x13, 0x11, 0x00, 0x20, 0x02, 0x00,
	0x11, 0x31, 0x13, 0x11, 0x00, 0x20, 0x02, 0x00, 0x11, 0x31, 0x13, 0x11, 0x00, 0x20,
	0x02, 0x00, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x11, 0x11
};

const uint16 Gs2dScreen::_binaryPattern[16] = {
	0xD992, 0x344B, 0xA592, 0x110D,
	0x9234, 0x2326, 0x5199, 0xC8A6,
	0x4D29, 0x18B0, 0xA5AA, 0x2949,
	0x6DB3, 0xB2AA, 0x64A4, 0x3329 
};

const uint32 Gs2dScreen::_binaryClut[16] __attribute__((aligned(64))) = {
	GS_RGBA(   0,    0,    0, 0x40),
	GS_RGBA(  50,   50,   50, 0x40),
	GS_RGBA( 204,  204, 0xFF, 0x40),
	GS_RGBA( 140,  140, 0xFF, 0x40),

	GS_RGBA(0xFF, 0xFF, 0xFF, 0x80), GS_RGBA(0xFF, 0xFF, 0xFF, 0x80),
	GS_RGBA(0xFF, 0xFF, 0xFF, 0x80), GS_RGBA(0xFF, 0xFF, 0xFF, 0x80),
	GS_RGBA(0xFF, 0xFF, 0xFF, 0x80), GS_RGBA(0xFF, 0xFF, 0xFF, 0x80),
	GS_RGBA(0xFF, 0xFF, 0xFF, 0x80), GS_RGBA(0xFF, 0xFF, 0xFF, 0x80),
	GS_RGBA(0xFF, 0xFF, 0xFF, 0x80), GS_RGBA(0xFF, 0xFF, 0xFF, 0x80),
	GS_RGBA(0xFF, 0xFF, 0xFF, 0x80), GS_RGBA(0xFF, 0xFF, 0xFF, 0x80)
};



--- NEW FILE: Gs2dScreen.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2001-2004 The ScummVM project
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/backends/ps2/Gs2dScreen.h,v 1.1 2005/03/31 05:35:04 lavosspawn Exp $
 *
 */

#ifndef __GS2DSCREEN_H__
#define __GS2DSCREEN_H__

#include "sysdefs.h"

#define SUPPORT_STUPID_OVERLAYS

enum TVMode {
	TV_DONT_CARE = 0,
	TV_PAL,
	TV_NTSC
};

enum GsInterlace {
	GS_NON_INTERLACED = 0,
	GS_INTERLACED
};

class DmaPipe;

class Gs2dScreen {
public:
	Gs2dScreen(uint16 width, uint16 height, TVMode tvMode);
	~Gs2dScreen(void);
	void newScreenSize(uint16 width, uint16 height);
	uint8 tvMode(void);

	void copyScreenRect(const uint8 *buf, uint16 pitch, uint16 x, uint16 y, uint16 w, uint16 h);
	void setPalette(const uint32 *pal, uint8 start, uint16 num);
	void updateScreen(void);
	//- overlay routines
	void copyOverlayRect(const uint16 *buf, uint16 pitch, uint16 x, uint16 y, uint16 w, uint16 h);
	void grabOverlay(uint16 *buf, uint16 pitch);
	void clearOverlay(void);
	void showOverlay(void);
	void hideOverlay(void);
	//- mouse routines
	void setMouseOverlay(const uint8 *buf, uint16 width, uint16 height, uint16 hotSpotX, uint16 hotSpotY, uint8 transpCol);
	void showMouse(bool show);
	void setMouseXy(int16 x, int16 y);
	void setShakePos(int shake);

	void animThread(void);
	void timerTick(void);
	void wantAnim(bool runIt);
private:
	void createAnimTextures(void);
	void drawScreen(void);
	static inline void waitForDma(void);
	static inline void waitForImage(void);
	
	DmaPipe *_dmaPipe;
	uint8 _videoMode;
	uint16 _tvWidth, _tvHeight;
	
	uint8  _curDrawBuf;
	uint32 _frameBufPtr[2]; //
	uint32 _clutPtrs[3];    //   vram pointers
	uint32 _texPtrs[3];     //

	uint16 _width, _height, _pitch;
	int16  _mouseX, _mouseY, _hotSpotX, _hotSpotY;
	uint32 _mouseScaleX, _mouseScaleY;
	uint8  _mTraCol;

	int _shakePos;

	bool _showMouse, _showOverlay, _screenChanged, _overlayChanged, _clutChanged;
	uint16 *_overlayBuf;
	uint8 *_screenBuf;
	uint32 *_clut;

	bool _runAnim;
	int _timerSema, _screenSema;
	static const uint32 _binaryClut[16];
	static const uint8  _binaryData[4 * 14 * 2];
	static const uint16 _binaryPattern[16];
};

#endif // __GS2DSCREEN_H__

--- NEW FILE: GsDefs.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2001-2004 The ScummVM project
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/backends/ps2/GsDefs.h,v 1.1 2005/03/31 05:35:04 lavosspawn Exp $
 *
 */

#ifndef __GSDEFS_H__
#define __GSDEFS_H__

#include "sysdefs.h"

// Gs2dScreen defines:

#define PAL_NTSC_FLAG		(*((uint8*)0x1FC80000))

#define GS_PMODE			*((volatile uint64*)0x12000000)
#define GS_CSR				*((volatile uint64*)0x12001000)
#define GS_DISPFB1			*((volatile uint64*)0x12000070)
#define GS_DISPLAY1			*((volatile uint64*)0x12000080)
#define GS_BGCOLOUR			*((volatile uint64*)0x120000E0)

#define GS_SET_CSR(signal, finish, hsint, vsint, flush, reset, field) \
	((signal) | ((finish) << 1) | ((hsint) << 2) | ((vsint) << 3) | \
	((flush) << 8) | ((reset) << 9) | ((field) << 13))

#define GS_SET_PMODE(readC1, readC2, alphaSel, alphaOut, alphaBlend, alphaFixed) \
	((readC1) | ((readC2) << 1) | ((alphaSel) << 5) | ((alphaOut) << 6) | ((alphaBlend) << 7) | ((alphaFixed) << 8))

#define GS_SET_DISPLAY(width, height, xpos, ypos) \
	(((uint64)(height - 1) << 44) | ((uint64)0x9FF << 32) | \
	((((2560 + (width - 1)) / width) - 1)<<23) | \
	(ypos << 12) | (xpos * (2560 / width)))

#define GS_SET_DISPFB(frameBufPtr, frameBufWidth, psm) \
	(((frameBufPtr) / 8192) | (((frameBufWidth) / 64) << 9) | ((psm) << 15))

#define GS_RGBA(r, g, b, a) \
	((r) | ((g) << 8) | ((b) << 16) | ((a) << 24))

//DmaPipe defines:

enum GsRegs {
	GPR_PRIM = 0x00,	// Select and configure current drawing primitive
	GPR_RGBAQ,			// Setup current vertex color
	GPR_ST,				// ...
	GPR_UV,				// Specify Vertex Texture Coordinates
	GPR_XYZF2,			// Set vertex coordinate
	GPR_XYZ2,			// Set vertex coordinate and 'kick' drawing
	GPR_TEX0_1,			// Texture Buffer Setup (Context 1)
	GPR_TEX0_2,			// Texture Buffer Setup (Context 2)
	GPR_CLAMP_1,		// ...
	GPR_CLAMP_2,		// ...
	GPR_FOG,			// ...
	
	GPR_XYZF3 = 0x0C,	// ...
	GPR_XYZ3,			// ...
	
	GPR_TEX1_1 = 0x14,	// ...
	GPR_TEX1_2,			// ...
	GPR_TEX2_1,			// ...
	GPR_TEX2_2,			// ...
	GPR_XYOFFSET_1,		// Mapping from Primitive to Window coordinate system (Context 1)
	GPR_XYOFFSET_2,		// Mapping from Primitive to Window coordinate system (Context 2)
	GPR_PRMODECONT,		// ...
	GPR_PRMODE,			// ...
	GPR_TEXCLUT,		// ...
	
	GPR_SCANMSK	= 0x22,	// ...
	
	GPR_MIPTBP1_1 = 0x34,	// ...
	GPR_MIPTBP1_2,		// ...
	GPR_MIPTBP2_1,		// ...
	GPR_MIPTBP2_2,		// ...
	
	GPR_TEXA = 0x3b,	// ...
	
	GPR_FOGCOL = 0x3d,	// ...

	GPR_TEXFLUSH = 0x3f,// Write to this register before using newly loaded texture
	GPR_SCISSOR_1,		// Setup clipping rectangle (Context 1)
	GPR_SCISSOR_2,		// Setup clipping rectangle (Context 2)
	GPR_ALPHA_1,		// Setup Alpha Blending Parameters (Context 1)
	GPR_ALPHA_2,		// Setup Alpha Blending Parameters (Context 2)
	GPR_DIMX,			// ...
	GPR_DTHE,			// ...
	GPR_COLCLAMP,		// ...
	GPR_TEST_1,			// ...
	GPR_TEST_2,			// ...
	GPR_PABE,			// ...
	GPR_FBA_1,			// ...
	GPR_FBA_2,			// ...
	GPR_FRAME_1,		// Frame buffer settings (Context 1)
	GPR_FRAME_2,		// Frame buffer settings (Context 2)
	GPR_ZBUF_1,			// ...
	GPR_ZBUF_2,			// ...
	GPR_BITBLTBUF,		// Setup Image Transfer Between EE and GS
	GPR_TRXPOS,			// Setup Image Transfer Coordinates
	GPR_TRXREG,			// Setup Image Transfer Size
	GPR_TRXDIR,			// Set Image Transfer Directon + Start Transfer
	GPR_HWREG,
	
	GPR_SIGNAL = 0x60,
	GPR_FINISH,
	GPR_LABEL
};

enum PrimTypes {
	PR_POINT = 0,
	PR_LINE,
	PR_LINESTRIP,
	PR_TRIANGLE,
	PR_TRIANGLESTRIP,
	PR_TRIANGLEFAN,
	PR_SPRITE
};

#define GS_PSMCT32		0x00
#define GS_PSMCT24		0x01
#define GS_PSMCT16		0x02
#define GS_PSMCT16S		0x0A
#define GS_PSMT8		0x13
#define GS_PSMT4		0x14
#define GS_PSMT4HL		0x24
#define GS_PSMT4HH		0x2C
#define GS_PSMT8H		0x1B

/*#define GS_SET_BITBLTBUF(sbp, sbw, spsm, dbp, dbw, dpsm) \
	((uint64)(sbp)         | ((uint64)(sbw) << 16) | \
	((uint64)(spsm) << 24) | ((uint64)(dbp) << 32) | \
	((uint64)(dbw) << 48)  | ((uint64)(dpsm) << 56))*/

#define GS_SET_SRC_BLTBUF(sbp, sbw, spsm) \
	((sbp) | ((uint64)sbw << 16) | ((uint64)spsm << 24))

#define GS_SET_DEST_BLTBUF(dbp, dbw, dpsm) \
	(((uint64)(dbp) << 32) | ((uint64)(dbw) << 48)  | ((uint64)(dpsm) << 56))

#define GS_SET_SRC_TRXPOS(ssax, ssay) \
	((ssax) | ((uint64)ssay << 16))

#define GS_SET_DEST_TRXPOS(dsax, dsay) \
	(((uint64)(dsax) << 32) | ((uint64)(dsay) << 48))

#define GS_SET_TRXREG(rrw, rrh) \
	((uint64)(rrw) | ((uint64)(rrh) << 32))

#define GS_SET_TEXA(ta0, aem, ta1) \
	((uint64)(ta0) | ((uint64)(aem) << 15) | ((uint64)(ta1) << 32))

#define GS_SET_TEX0(tbp, tbw, psm, tw, th, tcc, tfx, cbp, cpsm, csm, csa, cld) \
	((uint64)(tbp)         | ((uint64)(tbw) << 14) | ((uint64)(psm) << 20)  | ((uint64)(tw) << 26) | \
	((uint64)(th) << 30)   | ((uint64)(tcc) << 34) | ((uint64)(tfx) << 35)  | ((uint64)(cbp) << 37) | \
	((uint64)(cpsm) << 51) | ((uint64)(csm) << 55) | ((uint64)(csa) << 56)  | ((uint64)(cld) << 61))

#define GIF_SET_TAG(nloop, eop, pre, prim, flg, nreg) \
	( (uint64)(nloop) | ((uint64)(eop)<<15) | ((uint64)(pre) << 46) | \
	((uint64)(prim)<<47) | ((uint64)(flg)<<58) | ((uint64)(nreg)<<60) )

#define GS_SET_UV(u, v) ((uint64)(u) | ((uint64)(v) << 16))

#define GS_SET_XYZ(x, y, z) \
	((uint64)(x) | ((uint64)(y) << 16) | ((uint64)(z) << 32))

#define GS_SET_XYOFFSET(ofx, ofy) ((uint64)(ofx) | ((uint64)(ofy) << 32))

#define GS_SET_SCISSOR(scax0, scax1, scay0, scay1) \
	( (uint64)(scax0) | ((uint64)(scax1) << 16) | ((uint64)(scay0) << 32) | ((uint64)(scay1) << 48) )

#define GS_SET_FRAME(fbp, fbw, psm, fbmask) \
	( (uint64)(fbp) | (uint64)((uint64)(fbw) << 16) | (uint64)((uint64)(psm) << 24) | (uint64)((uint64)(fbmask) << 32) )

#define GS_SET_TEST(ate, atst, aref, afail, date, datm, zte, ztst) \
	( (uint64)(ate)         | ((uint64)(atst) << 1) | ((uint64)(aref) << 4)  | ((uint64)(afail) << 12) | \
	((uint64)(date) << 14) | ((uint64)(datm) << 15) | ((uint64)(zte) << 16)  | ((uint64)(ztst) << 17) )

#define FILTER_NEAREST 0
#define FILTER_LINEAR 1

#define GS_SET_TEX1(lcm, mxl, mmag, mmin, mtba, l, k) \
	((uint64)(lcm) | ((uint64)(mxl) << 2)  | ((uint64)(mmag) << 5) | ((uint64)(mmin) << 6) | \
	((uint64)(mtba) << 9) | ((uint64)(l) << 19) | ((uint64)(k) << 32))

enum AlphaBlendColor {
	SOURCE_COLOR = 0,
	DEST_COLOR,
	ZERO_COLOR
};

enum AlphaBlendAlpha {
	SOURCE_ALPHA = 0,
	DEST_ALPHA,
    FIXED_ALPHA
};

#define GS_SET_ALPHA(a, b, c, d, fix) \
	((uint64)(a) | ((uint64)(b)<<2) | ((uint64)(c)<<4) | ((uint64)(d)<<6) | ((uint64)(fix)<<32))

#define GS_SET_PRIM(prim, iip, tme, fge, abe, aa1, fst, ctxt, fix) \
	((uint64)(prim)      | ((uint64)(iip) << 3)  | ((uint64)(tme) << 4) | \
	((uint64)(fge) << 5) | ((uint64)(abe) << 6)  | ((uint64)(aa1) << 7) | \
	((uint64)(fst) << 8) | ((uint64)(ctxt) << 9) | ((uint64)(fix) << 10))

#define GS_SET_COLQ(c) (0x3f80000000000000 | c)

#endif // __GSDEFS_H__

--- NEW FILE: asyncfio.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004-2005 The ScummVM project
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/backends/ps2/asyncfio.cpp,v 1.1 2005/03/31 05:35:04 lavosspawn Exp $
 *
 */

#include "asyncfio.h"
#include <tamtypes.h>
#include <kernel.h>
#include <fileio.h>
#include <assert.h>
#include <string.h>

extern void sioprintf(const char *zFormat, ...);

AsyncFio::AsyncFio(void) {
	_runningOp = NULL;
	memset(_ioSlots, 0, MAX_HANDLES * sizeof(int));
	ee_sema_t newSema;
	newSema.init_count = 1;
	newSema.max_count = 1;
	_ioSema = CreateSema(&newSema);
}

AsyncFio::~AsyncFio(void) {
	DeleteSema(_ioSema);
}

int AsyncFio::open(const char *name, int ioMode) {
	WaitSema(_ioSema);
	checkSync();
	int res;
	fioOpen(name, ioMode);
	int fioRes = fioSync(FIO_WAIT, &res);
	if (fioRes != FIO_COMPLETE) {
		sioprintf("ERROR: fioOpen(%s, %X):\n", name, ioMode);
		sioprintf("  fioSync returned %d, open res = %d\n", fioRes, res);
        SleepThread();		
	}
	SignalSema(_ioSema);
	return res;
}

void AsyncFio::close(int handle) {
	WaitSema(_ioSema);
	checkSync();
	fioClose(handle);
	SignalSema(_ioSema);
}

void AsyncFio::checkSync(void) {
	if (_runningOp) {
		assert(fioSync(FIO_WAIT, _runningOp) == FIO_COMPLETE);
		_runningOp = NULL;
	}
}

void AsyncFio::read(int fd, void *dest, unsigned int len) {
	WaitSema(_ioSema);
	checkSync();
	assert(fd < MAX_HANDLES);
	_runningOp = _ioSlots + fd;
    fioRead(fd, dest, len);
	SignalSema(_ioSema);
}

void AsyncFio::write(int fd, const void *src, unsigned int len) {
	WaitSema(_ioSema);
	checkSync();
	assert(fd < MAX_HANDLES);
	_runningOp = _ioSlots + fd;
	fioWrite(fd, (unsigned char*)src, len);
	SignalSema(_ioSema);
}

int AsyncFio::seek(int fd, int offset, int whence) {
	WaitSema(_ioSema);
	checkSync();
	int res = fioLseek(fd, offset, whence);
	SignalSema(_ioSema);
	return res;
}

int AsyncFio::sync(int fd) {
	WaitSema(_ioSema);
	if (_runningOp == _ioSlots + fd)
		checkSync();
	SignalSema(_ioSema);
	return _ioSlots[fd];
}

bool AsyncFio::poll(int fd) {
	bool retVal = false;
	if (PollSema(_ioSema) > 0) {
		if (_runningOp == _ioSlots + fd) {
			if (fioSync(FIO_NOWAIT, _runningOp) == FIO_COMPLETE) {
				_runningOp = NULL;
				retVal = true;
			} else
				retVal = false;
		} else
			retVal = true;
		SignalSema(_ioSema);
	}
	return retVal;
}

bool AsyncFio::fioAvail(void) {
	bool retVal = false;
	if (PollSema(_ioSema) > 0) {
		if (_runningOp) {
			if (fioSync(FIO_NOWAIT, _runningOp) == FIO_COMPLETE) {
				_runningOp = NULL;
				retVal = true;
			} else
				retVal = false;
		} else
			retVal = true;
		SignalSema(_ioSema);
	}
	return retVal;
}


--- NEW FILE: asyncfio.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004-2005 The ScummVM project
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/backends/ps2/asyncfio.h,v 1.1 2005/03/31 05:35:04 lavosspawn Exp $
 *
 */

#define MAX_HANDLES 32

class AsyncFio {
public:
	AsyncFio(void);
	~AsyncFio(void);
	int open(const char *name, int ioMode);
	void close(int handle);
	void read(int fd, void *dest, unsigned int len);
	void write(int fd, const void *src, unsigned int len);
	int seek(int fd, int offset, int whence);
	int sync(int fd);
	bool poll(int fd);
	bool fioAvail(void);
private:
	void checkSync(void);
	int _ioSema;
	int *_runningOp;
	int _ioSlots[MAX_HANDLES];
};


--- NEW FILE: cd.c ---
/*********************************************************************
 * Copyright (C) 2003 Tord Lindstrom (pukko at home.se)
 * This file is subject to the terms and conditions of the PS2Link License.
 * See the file LICENSE in the main directory of this distribution for more
 * details.
 */

#include <tamtypes.h>
#include <kernel.h>
#include <sifrpc.h>

#define CDVD_INIT_BIND_RPC 0x80000592

static SifRpcClientData_t cdvdCd __attribute__((aligned(64)));
static char sendBuffer[256] __attribute__((aligned(16)));

int cdvdInitialised = 0;


void cdvdExit(void)
{
    cdvdInitialised = 0;
}


int cdvdInit(int mode)
{
	int i=0,len=0,ret=0;
    u8  *pkt;

    cdvdCd.server = NULL;
    
    do {
        if ((ret = SifBindRpc(&cdvdCd, CDVD_INIT_BIND_RPC, 0)) < 0) {
            return -1;
        }
        if (!cdvdCd.server) {
            nopdelay();
        }
    }
	while(!cdvdCd.server);

    pkt = sendBuffer; 
    PUSHDATA( int, pkt, mode, i);
    pkt += i; len += i;

	if ((ret = SifCallRpc(&cdvdCd, 0, 0, sendBuffer, len, NULL, 0, 0, 0)) < 0)
        return -1;
  
    cdvdInitialised = 1;
    
    return 0;
}

--- NEW FILE: cd.h ---
/*********************************************************************
 * Copyright (C) 2003 Tord Lindstrom (pukko at home.se)
 * This file is subject to the terms and conditions of the PS2Link License.
 * See the file LICENSE in the main directory of this distribution for more
 * details.
 */

#ifndef _CD_H_
#define _CD_H_

#define CDVD_INIT_WAIT   0
#define CDVD_INIT_NOWAIT 1
#define CDVD_EXIT        5

#ifdef __cplusplus
extern "C" {
#endif

int cdvdInit(int mode);
void cdvdExit(void);

#ifdef __cplusplus
}
#endif

#endif

--- NEW FILE: fileio.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004-2005 The ScummVM project
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/backends/ps2/fileio.cpp,v 1.1 2005/03/31 05:35:04 lavosspawn Exp $
 *
 */

#include "backends/ps2/fileio.h"

#include <tamtypes.h>
#include <kernel.h>
#include <fileio.h>
#include <assert.h>
#include <string.h>
//#include <fileXio_rpc.h>
#include <cdvd_rpc.h>
#include "backends/ps2/asyncfio.h"
#include "base/engine.h"
#include "common/file.h"

#define CACHE_BUF_SIZE (2048 * 16)
#define MAX_CACHED_FILES 8

//#define DEFAULT_MODE (FIO_S_IRUSR | FIO_S_IWUSR | FIO_S_IRGRP | FIO_S_IWGRP | FIO_S_IROTH | FIO_S_IWOTH)

extern void sioprintf(const char *zFormat, ...);

AsyncFio fio;

AccessFio::AccessFio(void) {
	_handle = -1;
}

AccessFio::~AccessFio(void) {
	if (_handle >= 0)
		fio.close(_handle);
}

int32 AccessFio::sync(void) {
	return fio.sync(_handle);
}

bool AccessFio::poll(void) {
	return fio.poll(_handle);
}

bool AccessFio::fioAvail(void) {
	return fio.fioAvail();
}

bool AccessFio::open(const char *name, int mode) {
	_handle = fio.open(name, mode);
	return (_handle >= 0);
}

void AccessFio::read(void *dest, uint32 size) {
	fio.read(_handle, dest, size);
}

void AccessFio::write(const void *src, uint32 size) {
	fio.write(_handle, src, size);
}

int AccessFio::seek(int32 offset, int whence) {
	return fio.seek(_handle, offset, whence);
}

/*class AccessFioX : public AccessFio{
public:
	AccessFioX(void);
	virtual ~AccessFioX(void);
	virtual bool open(const char *name, int mode);
	virtual int read(void *dest, uint32 size);
	virtual int write(const void *src, uint32 size);
	virtual int seek(int32 offset, int whence);
	virtual void sync(int32 *res);
};

AccessFioX::AccessFioX(void) {
	_handle = -1;
}

AccessFioX::~AccessFioX(void) {
	if (_handle >= 0)
		fileXioClose(_handle);
}

void AccessFioX::sync(int32 *res) {
	assert(false);
}

bool AccessFioX::open(const char *name, int mode) {
	_handle = fileXioOpen(name, mode, DEFAULT_MODE);
	return (_handle >= 0);
}

int AccessFioX::read(void *dest, uint32 size) {
	return fileXioRead(_handle, (unsigned char*)dest, size);
}

int AccessFioX::write(const void *src, uint32 size) {
	return fileXioWrite(_handle, (unsigned char*)src, size);
}

int AccessFioX::seek(int32 offset, int whence) {
	return fileXioLseek(_handle, offset, whence);
}*/

struct TocNode {
	char name[64];
	TocNode *next, *sub;
	bool isDir;
	uint8 nameLen;
};

class TocManager {
public:
	TocManager(void);
	~TocManager(void);
	void readEntries(const char *root);
    int64 fileExists(const char *name);
	bool haveEntries(void);
private:
	void readDir(const char *path, TocNode **node, int level);
	TocNode *_rootNode;
	char _root[256];
	uint8 _rootLen;
};

class Ps2File {
public:
	Ps2File(int64 cacheId);
	~Ps2File(void);
	bool open(const char *name, int ioMode);
	bool isOpen(void);
	uint32 read(void *dest, uint32 size);
	uint32 write(const void *src, uint32 size);
	uint32 tell(void);
	uint32 size(void);
	int seek(int32 offset, int origin);
	bool eof(void);
	AccessFio *giveHandle(void);
	int64 _cacheId;
	void setSeekReset(void);
private:
	void checkCache(void);
	void syncCache(void);
	bool _cacheOp;
	bool _seekReset;

	bool _forWriting;
	AccessFio *_handle;
	uint8 *_cacheBuf, *_cachePos;
	uint32 _filePos;
	uint32 _cacheBytesLeft;
	uint32 _fSize;
	uint32 _readBytesBlock;
};

Ps2File::Ps2File(int64 cacheId) {
	_handle = NULL;
	_cachePos = _cacheBuf = (uint8*)malloc(CACHE_BUF_SIZE);
	_fSize = _filePos = _cacheBytesLeft = 0;
	_forWriting = false;
	_readBytesBlock = 0;
	_cacheOp = false;
	_cacheId = cacheId;
	_seekReset = false;
}

Ps2File::~Ps2File(void) {
	if (_handle != NULL) {
		syncCache();
		if (_forWriting && (_cachePos != _cacheBuf)) {
			_handle->write(_cacheBuf, _cachePos - _cacheBuf);
			int res = _handle->sync();
			if (res != (_cachePos - _cacheBuf)) {
				// Fixme: writing operation failed and we noticed
				// too late to return an error to the engine. 
				printf("ERROR: flushing the cache on fclose() failed!\n");
			}
		}
		delete _handle;
	}
	free(_cacheBuf);
}

bool Ps2File::open(const char *name, int ioMode) {
	//if (strncmp(name, "pfs0", 4) == 0)
	//	_handle = new AccessFioX();
	//else
	_handle = new AccessFio();

	if (_handle->open(name, ioMode)) {
		if (ioMode == O_RDONLY) {
			_fSize = _handle->seek(0, SEEK_END);
			_handle->seek(0, SEEK_SET);
		} else {
			_cacheBytesLeft = CACHE_BUF_SIZE;
			_forWriting = true;
		}
		return true;
	} else {
		delete _handle;
		_handle = NULL;
		return false;
	}
}

void Ps2File::setSeekReset(void) {
	_seekReset = true;
}

bool Ps2File::isOpen(void) {
	return (_handle != NULL);
}

int Ps2File::seek(int32 offset, int origin) {
	assert(!_forWriting);
	syncCache();
	uint32 seekDest;
	switch (origin) {
		case SEEK_SET:
			seekDest = offset;
			break;
		case SEEK_CUR:
			if (_seekReset)
				seekDest = offset;
			else
				seekDest = _filePos + offset;
			break;
		case SEEK_END:
			seekDest = _fSize + offset;
			break;
		default:
			return -1;
	}
	_seekReset = false;
	if (seekDest <= _fSize) {
		if ((seekDest >= _filePos) && (seekDest < _filePos + _cacheBytesLeft)) {
			uint32 cacheOffset = (seekDest - _filePos);
			_cacheBytesLeft -= cacheOffset;
            _cachePos += cacheOffset;
		} else {
			_handle->seek(seekDest, SEEK_SET);
			_cacheBytesLeft = 0;
		}
		_filePos = seekDest;
		_readBytesBlock = 0;
		return 0;
	} else
		return -1;
}

bool Ps2File::eof(void) {
	if ((!_forWriting) && (_filePos == _fSize))
		return true;
	else
		return false;
}

void Ps2File::checkCache(void) {
	if (!_forWriting) {
		if (_readBytesBlock > 32768) {
			if (_cacheBytesLeft <= (CACHE_BUF_SIZE / 4)) {
				if (_cacheBytesLeft && (_cachePos != _cacheBuf)) {
					memmove(_cacheBuf, _cachePos, _cacheBytesLeft);
				}
				_cachePos = _cacheBuf;
				_handle->read(_cacheBuf + _cacheBytesLeft, CACHE_BUF_SIZE - _cacheBytesLeft);
				_cacheOp = true;
			}
		}
	}
}

void Ps2File::syncCache(void) {
	if ((!_forWriting) && _cacheOp) {
		int cacheRes = _handle->sync();
		assert(cacheRes >= 0);
		_cacheBytesLeft += cacheRes;
		_cacheOp = false;
	}
}

uint32 Ps2File::read(void *dest, uint32 size) {
	assert(!_forWriting);
	syncCache();
	if (_seekReset)
        seek(0, SEEK_SET);	
	_readBytesBlock += size;

	uint8 *destBuf = (uint8*)dest;
	while (size) {
		if (_cacheBytesLeft != 0) {
			uint32 doCopy = (size >= _cacheBytesLeft) ? _cacheBytesLeft : size;
			memcpy(destBuf, _cachePos, doCopy);
			size -= doCopy;
			_cacheBytesLeft -= doCopy;
			_cachePos += doCopy;
			destBuf += doCopy;
			_filePos += doCopy;
		}
		if (size > 0) {
			assert(_cacheBytesLeft == 0);
			if (size >= CACHE_BUF_SIZE) {
				int readRes;
				do {
					_handle->read(destBuf, size);
					readRes = _handle->sync();
					_filePos += readRes;
					destBuf += readRes;
					size -= readRes;
				} while (size && readRes);
				if (size)
					printf("read operation failed, %d bytes left to read\n", size);
				return destBuf - (uint8*)dest;
			} else {
				uint32 doRead = size;
				if ((doRead < 2048) && (_cacheId >= 0))
					doRead = 2048;
				memset(_cacheBuf, 'A', 0x20);
				_handle->read(_cacheBuf, doRead);
				_cacheBytesLeft = _handle->sync();
				_cachePos = _cacheBuf;
				if (_cacheBytesLeft == 0) {
					return destBuf - (uint8*)dest;
				}
			}
		}
	}
	checkCache();
	return destBuf - (uint8*)dest;
}

uint32 Ps2File::write(const void *src, uint32 size) {
	assert(_forWriting && (!_seekReset));
	const uint8 *srcBuf = (const uint8*)src;

	while (size) {
		uint32 doWrite = (size > _cacheBytesLeft) ? _cacheBytesLeft : size;
		memcpy(_cachePos, srcBuf, doWrite);
		_cachePos += doWrite;
		_cacheBytesLeft -= doWrite;
		size -= doWrite;
		srcBuf += doWrite;
		_filePos += doWrite;

		if (_cacheBytesLeft == 0) {
			_handle->write(_cacheBuf, CACHE_BUF_SIZE);
			int res = _handle->sync();
			if (res == CACHE_BUF_SIZE) {
				_cachePos = _cacheBuf;
				_cacheBytesLeft = CACHE_BUF_SIZE;
			} else {
				printf("cache write operation failed, only %d bytes written\n", res);
				return 0;
			}

			if (size >= CACHE_BUF_SIZE) {
				int writeRes;
				do {
					_handle->write(srcBuf, size);
					writeRes = _handle->sync();
					_filePos += writeRes;
					srcBuf += writeRes;
					size -= writeRes;
				} while (size && writeRes);
				if (size)
					printf("write operation failed, %d bytes left to write\n", size);
                return srcBuf - (uint8*)src;
			}
		}
	}
	return srcBuf - (uint8*)src;
}

uint32 Ps2File::tell(void) {
	if (_seekReset)
		seek(0, SEEK_SET);
	return _filePos;
}

uint32 Ps2File::size(void) {
	assert(!_forWriting);
	return _fSize;
}

AccessFio *Ps2File::giveHandle(void) {
	assert(_handle);
	return _handle;
}

TocManager tocManager;

struct FioHandleCache {
	Ps2File *file;
	FioHandleCache *next, *prev;
};

static FioHandleCache *cacheListStart = NULL;
static FioHandleCache *cacheListEnd = NULL;
static int cacheListLen = 0;
static int cacheListSema = -1;
static bool wantHandleCaching = true;

extern void ps2_disableHandleCaching(void) {
	wantHandleCaching = false;
}

Ps2File *findInCache(int64 id);

FILE *ps2_fopen(const char *fname, const char *mode) {
	if (cacheListSema == -1) {
		ee_sema_t newSema;
		newSema.init_count = 1;
		newSema.max_count = 1;
		cacheListSema = CreateSema(&newSema);
		assert(cacheListSema >= 0);
	}
	if (!tocManager.haveEntries() && g_engine) // read the TOC the first time the engine opens a file
		tocManager.readEntries(g_engine->getGameDataPath());

	int fioMode = 0;
	switch(*mode) {
		case 'r':
			fioMode = O_RDONLY;
			break;
		case 'w':
			fioMode = O_WRONLY | O_CREAT | O_TRUNC;
			break;
		default:
			printf("unsupported mode \"%s\" for file \"%s\"\n", mode, fname);
			return NULL;
	}
	int64 cacheId = -1;
	if ((fioMode == O_RDONLY) && tocManager.haveEntries())
		cacheId = tocManager.fileExists(fname);

	if (cacheId != 0) {
		Ps2File *file = findInCache(cacheId);
		if (file)
			return (FILE*)file;

		if ((mode[1] != 'b') && (mode[1] != '\0')) {
			printf("unsupported mode \"%s\" for file \"%s\"\n", mode, fname);
			return NULL;
		}
		file = new Ps2File(cacheId);
		if (file->open(fname, fioMode))
			return (FILE*)file;
		else
			delete file;
	}
	return NULL;
}

void checkCacheListLen(void) {
	while (cacheListLen > MAX_CACHED_FILES) {
		assert(cacheListEnd && cacheListStart);
		delete cacheListEnd->file;
		cacheListEnd->prev->next = NULL;
		FioHandleCache *temp = cacheListEnd;
		cacheListEnd = cacheListEnd->prev;
		delete temp;
		cacheListLen--;
	}
}

int ps2_fclose(FILE *stream) {
	Ps2File *file = (Ps2File*)stream;
	if ((file->_cacheId > 0) && wantHandleCaching) { // this is a file on the CD, could be smart to cache it
		FioHandleCache *newHandle = new FioHandleCache;
		newHandle->file = file;
		file->setSeekReset();

		WaitSema(cacheListSema);
		if (!cacheListEnd) {
			newHandle->prev = newHandle->next = NULL;
			cacheListEnd = cacheListStart = newHandle;
		} else {
			newHandle->prev = NULL;
			newHandle->next = cacheListStart;
			cacheListStart->prev = newHandle;
			cacheListStart = newHandle;
		}
		cacheListLen++;
		checkCacheListLen();
		SignalSema(cacheListSema);
	} else
		delete file;
    return 0;
}

Ps2File *findInCache(int64 id) {
	if ((id <= 0) || !wantHandleCaching)
		return NULL;
	WaitSema(cacheListSema);
	FioHandleCache *node = cacheListStart;
	while (node) {
		if (node->file->_cacheId == id) {
			if (node == cacheListStart)
				cacheListStart = node->next;
			if (node == cacheListEnd)
				cacheListEnd = node->prev;
			if (node->prev)
				node->prev->next = node->next;
			if (node->next)
				node->next->prev = node->prev;
			Ps2File *ret = node->file;
			delete node;
			cacheListLen--;
			SignalSema(cacheListSema);
			return ret;
		} else
			node = node->next;
	}
	SignalSema(cacheListSema);
	return NULL;
}

int ps2_fseek(FILE *stream, long offset, int origin) {
	return ((Ps2File*)stream)->seek(offset, origin);
}

long ps2_ftell(FILE *stream) {
	return ((Ps2File*)stream)->tell();
}

long ps2_fsize(FILE *stream) {
	return ((Ps2File*)stream)->size();
}

int ps2_feof(FILE *stream) {
	return ((Ps2File*)stream)->eof();
}

size_t ps2_fread(void *buf, size_t r, size_t n, FILE *stream) {
	assert(r != 0);
	return ((Ps2File*)stream)->read(buf, r * n) / r;
}

int ps2_fgetc(FILE *stream) {
	uint8 temp;
	if (((Ps2File*)stream)->read(&temp, 1))
		return temp;
	else
		return EOF;
}

char *ps2_fgets(char *buf, int n, FILE *stream) {
	char *retVal = buf;
	while (n--) {
		if (n == 0)
			*buf = '\0';
		else {
			char c = ps2_fgetc(stream);
			if (c == EOF)
				return NULL;
			if ((c == '\r') || (c == '\n')) {
				*buf++ = '\0';
                return retVal;
			}
			*buf++ = c;
		}
	}
	return retVal;
}

int ps2_fprintf(FILE *pOut, const char *zFormat, ...) {
	va_list ap;
	char resStr[2048];

	va_start(ap,zFormat);
	int res = vsnprintf(resStr, 2048, zFormat, ap);
	va_end(ap);
	if ((pOut == stderr) || (pOut == stdout)) {
		printf("%s", resStr);
		sioprintf("%s", resStr);
	} else
		res = ps2_fwrite(resStr, 1, res, pOut);
	return res;
}

size_t ps2_fwrite(const void *buf, size_t r, size_t n, FILE *stream) {
	assert(r != 0);
	return ((Ps2File*)stream)->write(buf, r * n) / r;
}

int ps2_fputc(int c, FILE *stream) {
	if (((Ps2File*)stream)->write(&c, 1) == 1)
		return c;
	else
		return -1;
}

int ps2_fputs(const char *s, FILE *stream) {
	int len = strlen(s);
	if (ps2_fwrite(s, 1, len, stream) == len)
		return len;
	else
		return EOF;
}

int ps2_fflush(FILE *stream) {
	printf("fflush not implemented\n");
	return 0;
}

TocManager::TocManager(void) {
	_rootNode = NULL;
}

TocManager::~TocManager(void) {
	// todo: write this...
}

bool TocManager::haveEntries(void) {
	return _rootNode != NULL;
}

void TocManager::readEntries(const char *root) {
    _rootLen = strlen(root);
	strcpy(_root, root);
	if (_root[_rootLen - 1] == '/') {
		_rootLen--;
		_root[_rootLen] = '\0';
	}
	readDir(_root, &_rootNode, 0);
}

#define MAX_DIR_ENTRIES 512

void TocManager::readDir(const char *path, TocNode **node, int level) {
	if (level <= 2) { // we don't scan deeper than that
		struct TocEntry tocEntries[MAX_DIR_ENTRIES];
		int files = CDVD_GetDir(path + 5, NULL, CDVD_GET_FILES_AND_DIRS, tocEntries, MAX_DIR_ENTRIES, NULL);

		for (int cnt = 0; cnt < files; cnt++) {
			if (tocEntries[cnt].filename[0] != '.') { // skip '.' and '..'
				*node = new TocNode;
				(*node)->sub = (*node)->next = NULL;

				(*node)->nameLen = strlen(tocEntries[cnt].filename);
				memcpy((*node)->name, tocEntries[cnt].filename, (*node)->nameLen + 1);

				if (tocEntries[cnt].fileProperties & 2) { // directory
					(*node)->isDir = true;
					char nextPath[256];
					sprintf(nextPath, "%s/%s", path, tocEntries[cnt].filename);
					readDir(nextPath, &((*node)->sub), level + 1);
				} else
					(*node)->isDir = false;
				node = &((*node)->next);
			}
		}
	}
}

int64 TocManager::fileExists(const char *name) {
	const char *tmpName = name;

	if (((name[_rootLen] != '/') && (name[_rootLen] != '\0')) || (strnicmp(name, _root, _rootLen) != 0)) {
		for (int i = 0; i < 8; i++)
			if (name[i] == ':')	// we don't know the content of other drives,
				return -1;		// assume file exists
			else if ((name[i] == '/') || (name[i] == '\\'))
				return 0;		// does not exists (this is probably ScummVM trying the 'current directory'.)
		return 0;
	}

	uint8 nameLen = strlen(name);

	name += _rootLen + 1;
	nameLen -= _rootLen + 1;

	TocNode *node = _rootNode;
	int64 retId = 1;
	while (node) {
		if (((name[node->nameLen] == '/') || (name[node->nameLen] == '\0')) && (strnicmp(name, node->name, node->nameLen) == 0)) {
			name += node->nameLen;
			nameLen -= node->nameLen;
			if (node->isDir) {
				if (nameLen) {
					name++;	// skip '/'
					nameLen--;
					node = node->sub;
					retId <<= 10;
				} else
					return 0; // can't open a directory with fopen()
			} else {
				if (nameLen == 0)
					return retId; // ok, found
				else
					return 0; // here's a file, but there's something left in the path
			}
		} else {
			node = node->next;
			retId++;
		}
	}
	return 0; // does not exist
}


--- NEW FILE: fileio.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2004-2005 The ScummVM project
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/backends/ps2/fileio.h,v 1.1 2005/03/31 05:35:04 lavosspawn Exp $
 *
 */

#ifndef __PS2FILE_IO__
#define __PS2FILE_IO__

#include "scummsys.h"

class AccessFio {
public:
	AccessFio(void);
	virtual ~AccessFio(void);
	virtual bool open(const char *name, int mode);
	virtual void read(void *dest, uint32 size);
	virtual void write(const void *src, uint32 size);
	virtual int seek(int32 offset, int whence);
	virtual int32 sync(void);
	virtual bool poll(void);
	virtual bool fioAvail(void);
protected:
	int _handle;
};

class File;

FILE *ps2_fopen(const char *fname, const char *mode);
int ps2_fclose(FILE *stream);
int ps2_fflush(FILE *stream);
int ps2_fseek(FILE *stream, long offset, int origin);
long ps2_ftell(FILE *stream);
int ps2_feof(FILE *stream); 
long ps2_fsize(FILE *stream);

size_t ps2_fread(void *buf, size_t r, size_t n, FILE *stream);
int ps2_fgetc(FILE *stream);
char *ps2_fgets(char *buf, int n, FILE *stream);

size_t ps2_fwrite(const void *buf, size_t r, size_t n, FILE *stream);
int ps2_fputc(int c, FILE *stream);
int ps2_fputs(const char *s, FILE *stream);
int ps2_fprintf(FILE *pOut, const char *zFormat, ...);

AccessFio *fetchHandle(File *file);

#endif // __PS2FILE_IO__

--- NEW FILE: icon.cpp ---
#include "backends/ps2/savefile.h"
#include "backends/ps2/Gs2dScreen.h"
#include "backends/ps2/GsDefs.h"

const iconIVECTOR Ps2SaveFileManager::_bgcolor[4] = {
	{  68,  23, 116,  0 }, // top left
	{ 255, 255, 255,  0 }, // top right
	{ 255, 255, 255,  0 }, // bottom left
	{  68,  23, 116,  0 }, // bottom right
};

const iconFVECTOR Ps2SaveFileManager::_lightdir[3] = {
	{ 0.5, 0.5, 0.5, 0.0 },
	{ 0.0,-0.4,-0.1, 0.0 },
	{-0.5,-0.5, 0.5, 0.0 },
};

const iconFVECTOR Ps2SaveFileManager::_lightcol[3] = {
	{ 0.3, 0.3, 0.3, 0.00 },
	{ 0.4, 0.4, 0.4, 0.00 },
	{ 0.5, 0.5, 0.5, 0.00 },
};

const iconFVECTOR Ps2SaveFileManager::_ambient = { 0.50, 0.50, 0.50, 0.00 };

//  Source File: stdico2.rle
// Orig. Offset: 0 / 0x00000000
//       Length: 14018 / 0x000036C2 (bytes)

const uint8 Ps2SaveFileManager::_rleIcoData[14018] = {
    0xCC, 0x41, 0x00, 0x00, 0xCC, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x24, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x00, 0xF7, 0x00, 0xFE, 
    0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0E, 0x7F, 0x7F, 
    0x7F, 0x80, 0x00, 0x24, 0x00, 0xC1, 0x00, 0xFE, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 
    0x00, 0x04, 0x00, 0x10, 0x00, 0x02, 0x7F, 0x7F, 0x7F, 0x80, 0x00, 0xDC, 0x00, 0xC1, 0x00, 0xFE, 
    0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x7F, 0x7F, 
    0x7F, 0x80, 0x00, 0x24, 0x00, 0xC1, 0x00, 0xFE, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 
    0x00, 0x04, 0x00, 0x10, 0x00, 0x02, 0x7F, 0x7F, 0x7F, 0x80, 0x00, 0xDC, 0x00, 0xF7, 0x00, 0xFE, 
    0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0E, 0x7F, 0x7F, 
    0x7F, 0x80, 0x00, 0x24, 0x00, 0xF7, 0x00, 0xFE, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 
    0x00, 0x04, 0x00, 0x10, 0x00, 0x0E, 0x7F, 0x7F, 0x7F, 0x80, 0x00, 0x24, 0x00, 0xF7, 0x00, 0x02, 
    0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0E, 0x7F, 0x7F, 
    0x7F, 0x80, 0x00, 0xDC, 0x00, 0xC1, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 
    0x00, 0x04, 0x00, 0x10, 0x00, 0x02, 0x7F, 0x7F, 0x7F, 0x80, 0x00, 0x24, 0x00, 0xC1, 0x00, 0x02, 
    0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x7F, 0x7F, 
    0x7F, 0x80, 0x00, 0xDC, 0x00, 0xC1, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 
    0x00, 0x04, 0x00, 0x10, 0x00, 0x02, 0x7F, 0x7F, 0x7F, 0x80, 0x00, 0x24, 0x00, 0xF7, 0x00, 0x02, 
    0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0E, 0x7F, 0x7F, 
    0x7F, 0x80, 0x00, 0xDC, 0x00, 0xF7, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 
    0x00, 0x04, 0x00, 0x10, 0x00, 0x0E, 0x7F, 0x7F, 0x7F, 0x80, 0x00, 0xDC, 0x00, 0xC1, 0x00, 0xFE, 
    0x00, 0x04, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x7F, 0x7F, 
    0x7F, 0x80, 0x00, 0x24, 0x00, 0xC1, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 
    0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x7F, 0x7F, 0x7F, 0x80, 0x00, 0xDC, 0x00, 0xC1, 0x00, 0x02, 
    0x00, 0x04, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x7F, 0x7F, 
    0x7F, 0x80, 0x00, 0x24, 0x00, 0xC1, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 
    0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x7F, 0x7F, 0x7F, 0x80, 0x00, 0xDC, 0x00, 0xC1, 0x00, 0xFE, 
    0x00, 0x04, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x7F, 0x7F, 
    0x7F, 0x80, 0x00, 0x24, 0x00, 0xC1, 0x00, 0xFE, 0x00, 0x04, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 
    0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x7F, 0x7F, 0x7F, 0x80, 0x00, 0xDC, 0x00, 0xF7, 0x00, 0x02, 
    0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x7F, 0x7F, 
    0x7F, 0x80, 0x00, 0x24, 0x00, 0xF7, 0x00, 0xFE, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 
    0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x7F, 0x7F, 0x7F, 0x80, 0x00, 0xDC, 0x00, 0xF7, 0x00, 0xFE, 
    0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x7F, 0x7F, 
    0x7F, 0x80, 0x00, 0x24, 0x00, 0xF7, 0x00, 0xFE, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 
    0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x7F, 0x7F, 0x7F, 0x80, 0x00, 0xDC, 0x00, 0xF7, 0x00, 0x02, 
    0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x7F, 0x7F, 
    0x7F, 0x80, 0x00, 0x24, 0x00, 0xF7, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 
    0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x7F, 0x7F, 0x7F, 0x80, 0x00, 0xDC, 0x00, 0xF7, 0x00, 0x02, 
    0x00, 0x04, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x10, 0x00, 0x0E, 0x7F, 0x7F, 
    0x7F, 0x80, 0x00, 0xDC, 0x00, 0xC1, 0x00, 0xFE, 0x00, 0x04, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x04, 0x00, 0x10, 0x00, 0x02, 0x7F, 0x7F, 0x7F, 0x80, 0x00, 0xDC, 0x00, 0xC1, 0x00, 0x02, 
    0x00, 0x04, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x10, 0x00, 0x02, 0x7F, 0x7F, 
    0x7F, 0x80, 0x00, 0xDC, 0x00, 0xC1, 0x00, 0xFE, 0x00, 0x04, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x04, 0x00, 0x10, 0x00, 0x02, 0x7F, 0x7F, 0x7F, 0x80, 0x00, 0xDC, 0x00, 0xF7, 0x00, 0x02, 
    0x00, 0x04, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x10, 0x00, 0x0E, 0x7F, 0x7F, 
    0x7F, 0x80, 0x00, 0xDC, 0x00, 0xF7, 0x00, 0xFE, 0x00, 0x04, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x04, 0x00, 0x10, 0x00, 0x0E, 0x7F, 0x7F, 0x7F, 0x80, 0x00, 0x24, 0x00, 0xF7, 0x00, 0xFE, 
    0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0E, 0x7F, 0x7F, 
    0x7F, 0x80, 0x00, 0x24, 0x00, 0xC1, 0x00, 0x02, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x7F, 0x7F, 0x7F, 0x80, 0x00, 0x24, 0x00, 0xC1, 0x00, 0xFE, 
    0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x7F, 0x7F, 
    0x7F, 0x80, 0x00, 0x24, 0x00, 0xC1, 0x00, 0x02, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x7F, 0x7F, 0x7F, 0x80, 0x00, 0x24, 0x00, 0xF7, 0x00, 0xFE, 
    0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0E, 0x7F, 0x7F, 
    0x7F, 0x80, 0x00, 0x24, 0x00, 0xF7, 0x00, 0x02, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x04, 0x00, 0x00, 0x00, 0x0E, 0x7F, 0x7F, 0x7F, 0x80, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x4E, 0x07, 
    0x0C, 0x00, 0xFD, 0x73, 0xF5, 0x47, 0xED, 0x1B, 0xE7, 0x03, 0xE6, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE7, 0x03, 0xE6, 0x03, 0xE9, 0x03, 0xF0, 0x2B, 0xF8, 0x57, 0x74, 0x00, 0x0C, 0x00, 0xFD, 0x73, 
    0xF5, 0x47, 0xED, 0x1B, 0xE7, 0x03, 0xE6, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE7, 0x03, 0xE6, 0x03, 
    0xE9, 0x03, 0xF0, 0x2B, 0xF8, 0x57, 0x62, 0x00, 0x21, 0x00, 0xFE, 0x77, 0xFB, 0x67, 0xF9, 0x5F, 
    0xF8, 0x5F, 0xF9, 0x5F, 0xF9, 0x5F, 0xF9, 0x5F, 0xF9, 0x5F, 0xF9, 0x5F, 0xF9, 0x5F, 0xF9, 0x5F, 
    0xF9, 0x5F, 0xF9, 0x5F, 0xF9, 0x5F, 0xF9, 0x5F, 0xF9, 0x5F, 0xF9, 0x5F, 0xF9, 0x5F, 0xF7, 0x53, 
    0xF1, 0x33, 0xEB, 0x13, 0xE7, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE7, 0x03, 0xE7, 0x03, 
    0xE9, 0x03, 0xED, 0x1F, 0xF3, 0x3F, 0xF9, 0x5B, 0xFB, 0x67, 0xFE, 0x77, 0x5F, 0x00, 0x21, 0x00, 
    0xFB, 0x6B, 0xF5, 0x4B, 0xF0, 0x2F, 0xEE, 0x2F, 0xF0, 0x2F, 0xF1, 0x2F, 0xF1, 0x2F, 0xF1, 0x2F, 
    0xF1, 0x2F, 0xF1, 0x2F, 0xF1, 0x2F, 0xF1, 0x2F, 0xF1, 0x2F, 0xF1, 0x2F, 0xF1, 0x2F, 0xF1, 0x2F, 
    0xF1, 0x2F, 0xF0, 0x2F, 0xEF, 0x2B, 0xEC, 0x1B, 0xE9, 0x0B, 0xE7, 0x03, 0xE7, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xEA, 0x0F, 0xEC, 0x1F, 0xF1, 0x2F, 0xF6, 0x4B, 
    0xFC, 0x6B, 0x5F, 0x00, 0x21, 0x00, 0xF8, 0x57, 0xEF, 0x2B, 0xE8, 0x07, 0xE6, 0x07, 0xE8, 0x07, 
    0xEA, 0x07, 0xEA, 0x07, 0xEA, 0x07, 0xEA, 0x07, 0xEA, 0x07, 0xEA, 0x07, 0xEA, 0x07, 0xEA, 0x07, 
    0xEA, 0x07, 0xEA, 0x07, 0xE9, 0x07, 0xE9, 0x07, 0xE9, 0x07, 0xE8, 0x07, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE7, 0x03, 
    0xE7, 0x07, 0xE9, 0x07, 0xF0, 0x2B, 0xF8, 0x57, 0x56, 0x00, 0x30, 0x00, 0xFD, 0x73, 0xFB, 0x67, 
    0xFA, 0x63, 0xF9, 0x63, 0xFA, 0x63, 0xFA, 0x63, 0xFA, 0x63, 0xFA, 0x63, 0xF9, 0x5F, 0xF2, 0x3B, 
    0xEB, 0x13, 0xE5, 0x03, 0xE3, 0x03, 0xE4, 0x03, 0xE6, 0x03, 0xE6, 0x03, 0xE6, 0x03, 0xE6, 0x03, 
    0xE6, 0x03, 0xE6, 0x03, 0xE6, 0x03, 0xE6, 0x03, 0xE6, 0x03, 0xE6, 0x03, 0xE6, 0x03, 0xE6, 0x03, 
    0xE5, 0x03, 0xE5, 0x03, 0xE6, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 
    0xE9, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xE6, 0x03, 0xE5, 0x03, 0xE6, 0x03, 0xEC, 0x13, 0xF3, 0x3B, 
    0xF9, 0x5F, 0xFA, 0x63, 0xF9, 0x63, 0xFA, 0x63, 0xFB, 0x6B, 0xFE, 0x77, 0x50, 0x00, 0x30, 0x00, 
    0xFA, 0x63, 0xF5, 0x43, 0xF1, 0x37, 0xF0, 0x37, 0xF2, 0x37, 0xF2, 0x37, 0xF2, 0x37, 0xF2, 0x37, 
    0xF1, 0x33, 0xEE, 0x1F, 0xE9, 0x07, 0xE6, 0x03, 0xE5, 0x03, 0xE6, 0x03, 0xE7, 0x03, 0xE7, 0x03, 
    0xE7, 0x03, 0xE7, 0x03, 0xE7, 0x03, 0xE7, 0x03, 0xE7, 0x03, 0xE7, 0x03, 0xE7, 0x03, 0xE7, 0x03, 
    0xE7, 0x03, 0xE7, 0x03, 0xE6, 0x03, 0xE7, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 
    0xE9, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE7, 0x03, 0xE6, 0x03, 0xE7, 0x03, 
    0xEA, 0x07, 0xEE, 0x1F, 0xF1, 0x33, 0xF1, 0x37, 0xF0, 0x37, 0xF1, 0x37, 0xF5, 0x47, 0xFB, 0x67, 
    0x4F, 0x00, 0x32, 0x00, 0xFD, 0x77, 0xF6, 0x4B, 0xEE, 0x1F, 0xE9, 0x0B, 0xE8, 0x0B, 0xEA, 0x0B, 
    0xEA, 0x0B, 0xEA, 0x0B, 0xEA, 0x0B, 0xEA, 0x0B, 0xEA, 0x07, 0xE9, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE9, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xEA, 0x07, 0xEA, 0x0B, 0xEA, 0x0B, 0xE8, 0x0B, 
    0xE9, 0x0B, 0xEF, 0x23, 0xF7, 0x4F, 0xFE, 0x7B, 0x49, 0x00, 0x39, 0x00, 0xFD, 0x73, 0xFB, 0x6B, 
    0xFA, 0x67, 0xFB, 0x67, 0xFB, 0x67, 0xF8, 0x57, 0xF0, 0x2F, 0xE9, 0x07, 0xE4, 0x03, 0xE4, 0x03, 
    0xE5, 0x03, 0xE6, 0x03, 0xE6, 0x03, 0xE6, 0x03, 0xE6, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE9, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xC8, 0x03, 0xC8, 0x03, 0xA8, 0x03, 
    0xA8, 0x03, 0xA8, 0x03, 0xA8, 0x03, 0xA8, 0x03, 0xA8, 0x03, 0xC8, 0x03, 0xC8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xE7, 0x03, 0xE6, 0x03, 0xE5, 0x03, 
    0xE4, 0x03, 0xE5, 0x03, 0xEA, 0x0B, 0xF1, 0x33, 0xF8, 0x5B, 0xFC, 0x6B, 0xFE, 0x77, 0x46, 0x00, 
    0x3A, 0x00, 0xFF, 0x7B, 0xF9, 0x5F, 0xF4, 0x43, 0xF1, 0x3B, 0xF2, 0x3B, 0xF3, 0x3B, 0xF1, 0x2F, 
    0xEC, 0x17, 0xE8, 0x03, 0xE5, 0x03, 0xE5, 0x03, 0xE5, 0x03, 0xE6, 0x03, 0xE6, 0x03, 0xE6, 0x03, 
    0xE7, 0x03, 0xE7, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE9, 0x03, 
    0xE9, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xC8, 0x03, 0xC8, 0x03, 0xC8, 0x03, 0xC8, 0x03, 0xC8, 0x03, 
    0xC8, 0x03, 0xA8, 0x03, 0x87, 0x03, 0x47, 0x03, 0x47, 0x03, 0x27, 0x03, 0x27, 0x03, 0x47, 0x03, 
    0x68, 0x03, 0x88, 0x03, 0xA8, 0x03, 0xC8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xE9, 0x03, 
    0xE8, 0x03, 0xE7, 0x03, 0xE7, 0x03, 0xE6, 0x03, 0xE5, 0x03, 0xE6, 0x03, 0xE8, 0x03, 0xEC, 0x1B, 
    0xF0, 0x33, 0xF5, 0x47, 0xFB, 0x63, 0x46, 0x00, 0x3B, 0x00, 0xFC, 0x6F, 0xF4, 0x43, 0xED, 0x1B, 
    0xE9, 0x0F, 0xE9, 0x0F, 0xEB, 0x0F, 0xEB, 0x0F, 0xE9, 0x07, 0xE8, 0x03, 0xE7, 0x03, 0xE7, 0x03, 
    0xE7, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xC8, 0x03, 0xC8, 0x03, 0xA8, 0x03, 0xA7, 0x03, 
    0x87, 0x03, 0x87, 0x03, 0x87, 0x03, 0x88, 0x03, 0x67, 0x03, 0x27, 0x03, 0x06, 0x03, 0xC5, 0x02, 
    0xA6, 0x02, 0xA6, 0x02, 0xA6, 0x02, 0xC6, 0x02, 0xE7, 0x02, 0x27, 0x07, 0x67, 0x03, 0x87, 0x03, 
    0xC7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x07, 0xE9, 0x0F, 0xEF, 0x23, 0xF6, 0x4F, 0xFE, 0x77, 
    0x43, 0x00, 0x40, 0x00, 0xFD, 0x77, 0xFC, 0x6F, 0xF6, 0x4F, 0xEF, 0x27, 0xE8, 0x03, 0xE4, 0x03, 
    0xE5, 0x03, 0xE6, 0x03, 0xE7, 0x03, 0xE7, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE7, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE7, 0x03, 0xC7, 0x03, 
    0xC7, 0x03, 0xA7, 0x03, 0x67, 0x03, 0x47, 0x03, 0x27, 0x03, 0x06, 0x03, 0x06, 0x03, 0xE6, 0x02, 
    0xE6, 0x02, 0xE6, 0x02, 0xE6, 0x02, 0xC6, 0x02, 0x85, 0x02, 0x65, 0x02, 0x24, 0x02, 0x04, 0x02, 
    0x04, 0x02, 0x05, 0x02, 0x25, 0x02, 0x45, 0x06, 0x85, 0x06, 0xC6, 0x02, 0x06, 0x03, 0x46, 0x03, 
    0x87, 0x03, 0xA7, 0x03, 0xC8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xE9, 0x03, 
    0xE9, 0x03, 0xE7, 0x03, 0xE5, 0x03, 0xE5, 0x03, 0xEA, 0x07, 0xF1, 0x33, 0xF8, 0x5B, 0xFC, 0x6F, 
    0xFD, 0x77, 0xFF, 0x7B, 0x3F, 0x00, 0x41, 0x00, 0xFE, 0x77, 0xF9, 0x5B, 0xF5, 0x43, 0xEF, 0x2F, 
    0xEB, 0x13, 0xE7, 0x03, 0xE5, 0x03, 0xE5, 0x03, 0xE6, 0x03, 0xE7, 0x03, 0xE7, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE7, 0x03, 0xA7, 0x03, 0x87, 0x03, 0x26, 0x03, 0xE6, 0x02, 0xA6, 0x02, 0x65, 0x02, 
    0x45, 0x02, 0x45, 0x02, 0x45, 0x02, 0x24, 0x02, 0x24, 0x02, 0x24, 0x02, 0x04, 0x02, 0xE4, 0x01, 
    0xC4, 0x01, 0xA3, 0x05, 0x83, 0x05, 0x63, 0x01, 0x83, 0x01, 0x83, 0x05, 0xA3, 0x01, 0xE4, 0x01, 
    0x24, 0x02, 0x65, 0x02, 0xC6, 0x02, 0x26, 0x03, 0x67, 0x03, 0xA7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xE6, 0x03, 0xE6, 0x03, 0xE8, 0x03, 
    0xEC, 0x1B, 0xF1, 0x37, 0xF5, 0x47, 0xF9, 0x5F, 0xFD, 0x73, 0x3F, 0x00, 0x41, 0x00, 0xFC, 0x6B, 
    0xF4, 0x43, 0xED, 0x1B, 0xE9, 0x0F, 0xE8, 0x07, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xE9, 0x03, 
    0xE9, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xC7, 0x03, 0x86, 0x03, 0x26, 0x03, 0xA5, 0x02, 
    0x24, 0x02, 0xE4, 0x01, 0xC4, 0x01, 0x84, 0x01, 0x84, 0x01, 0x84, 0x01, 0x83, 0x01, 0x63, 0x01, 
    0x63, 0x01, 0x63, 0x01, 0x43, 0x01, 0x43, 0x05, 0x23, 0x05, 0x23, 0x05, 0x02, 0x05, 0x02, 0x05, 
    0x02, 0x05, 0x22, 0x01, 0x43, 0x01, 0x83, 0x01, 0xC4, 0x01, 0x25, 0x02, 0xA6, 0x02, 0x06, 0x03, 
    0x67, 0x03, 0xA7, 0x03, 0xC8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x0B, 0xEA, 0x13, 0xEE, 0x23, 0xF5, 0x47, 0xFC, 0x6B, 
    0x39, 0x00, 0x47, 0x00, 0xFF, 0x7B, 0xFE, 0x77, 0xFD, 0x73, 0xFC, 0x73, 0xFD, 0x73, 0xFD, 0x73, 
    0xF7, 0x4F, 0xEF, 0x23, 0xE8, 0x03, 0xE5, 0x03, 0xE6, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xE9, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xC8, 0x03, 0xC8, 0x03, 0xA8, 0x03, 0xA7, 0x03, 0xA7, 0x03, 0x66, 0x03, 0xE5, 0x02, 0x85, 0x02, 
    0x04, 0x02, 0x83, 0x01, 0x43, 0x01, 0x23, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 
    0xE2, 0x00, 0xE2, 0x00, 0xE2, 0x00, 0xE2, 0x04, 0xE3, 0x04, 0xE3, 0x08, 0xE2, 0x08, 0xC2, 0x08, 
    0xC2, 0x04, 0xC1, 0x04, 0xC1, 0x04, 0xE2, 0x00, 0x03, 0x01, 0x23, 0x01, 0xA4, 0x01, 0x05, 0x02, 
    0x65, 0x02, 0xE6, 0x02, 0x46, 0x03, 0x87, 0x03, 0xC8, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xE5, 0x03, 0xE5, 0x03, 0xEA, 0x07, 0xF2, 0x37, 
    0xFB, 0x67, 0x39, 0x00, 0x47, 0x00, 0xFD, 0x73, 0xF8, 0x5B, 0xF5, 0x47, 0xF4, 0x47, 0xF4, 0x47, 
    0xF5, 0x47, 0xF1, 0x2F, 0xEC, 0x13, 0xE7, 0x03, 0xE5, 0x03, 0xE6, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xC8, 0x03, 0xC8, 0x03, 
    0xA7, 0x03, 0x87, 0x03, 0x87, 0x03, 0x47, 0x03, 0x46, 0x03, 0x26, 0x03, 0xC5, 0x02, 0x64, 0x02, 
    0xE4, 0x01, 0x83, 0x01, 0x23, 0x05, 0x03, 0x05, 0xE3, 0x04, 0xC3, 0x04, 0xE3, 0x04, 0xE3, 0x00, 
    0xE2, 0x00, 0xC2, 0x04, 0xC2, 0x04, 0xC2, 0x04, 0xE2, 0x04, 0xE3, 0x08, 0xE3, 0x08, 0xE3, 0x08, 
    0xE2, 0x08, 0xC2, 0x04, 0xC2, 0x04, 0xA2, 0x04, 0xC2, 0x04, 0xC2, 0x04, 0x03, 0x01, 0x43, 0x01, 
    0xA4, 0x01, 0xE4, 0x01, 0x65, 0x02, 0xE6, 0x02, 0x47, 0x03, 0xA8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xE5, 0x03, 0xE4, 0x03, 0xE9, 0x03, 
    0xF2, 0x33, 0xFA, 0x67, 0x39, 0x00, 0x47, 0x00, 0xFA, 0x63, 0xF3, 0x3B, 0xED, 0x1B, 0xEB, 0x1B, 
    0xEC, 0x1B, 0xED, 0x1B, 0xEB, 0x13, 0xEA, 0x07, 0xE8, 0x03, 0xE7, 0x03, 0xE7, 0x03, 0xE7, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xC7, 0x03, 0xA7, 0x03, 
    0x87, 0x03, 0x46, 0x03, 0x26, 0x03, 0x06, 0x03, 0xE5, 0x02, 0xA5, 0x02, 0x85, 0x02, 0x44, 0x02, 
    0xC4, 0x01, 0x63, 0x01, 0x03, 0x05, 0xE3, 0x04, 0xE3, 0x04, 0xE3, 0x04, 0xE3, 0x04, 0xE3, 0x04, 
    0x03, 0x05, 0xE2, 0x04, 0xE2, 0x04, 0xE2, 0x04, 0xE2, 0x08, 0x03, 0x09, 0x23, 0x09, 0x23, 0x09, 
    0x23, 0x09, 0x03, 0x05, 0x03, 0x05, 0xE3, 0x08, 0xC3, 0x08, 0xC3, 0x08, 0xE3, 0x04, 0xE3, 0x04, 
    0x23, 0x01, 0x43, 0x01, 0x83, 0x05, 0xE4, 0x05, 0x66, 0x02, 0x07, 0x03, 0x88, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE6, 0x03, 0xE6, 0x03, 
    0xEB, 0x0F, 0xF3, 0x3B, 0xFB, 0x67, 0x36, 0x00, 0x4A, 0x00, 0xFF, 0x7B, 0xFE, 0x77, 0xFC, 0x6F, 
    0xF5, 0x47, 0xED, 0x1B, 0xE7, 0x03, 0xE5, 0x03, 0xE6, 0x03, 0xE7, 0x03, 0xE7, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xC8, 0x03, 0xA7, 0x03, 0x66, 0x03, 0x26, 0x03, 0x06, 0x03, 0xC5, 0x02, 0x85, 0x02, 0x65, 0x06, 
    0x44, 0x06, 0x04, 0x02, 0xE3, 0x01, 0x83, 0x01, 0x43, 0x01, 0x03, 0x05, 0xC3, 0x04, 0xC3, 0x08, 
    0xC3, 0x08, 0xE3, 0x08, 0x04, 0x09, 0x03, 0x09, 0x03, 0x05, 0x03, 0x09, 0x03, 0x09, 0x03, 0x09, 
    0x23, 0x09, 0x23, 0x09, 0x44, 0x09, 0x44, 0x09, 0x44, 0x09, 0x24, 0x09, 0x23, 0x09, 0x03, 0x09, 
    0xE3, 0x08, 0xE3, 0x08, 0xE3, 0x08, 0xE3, 0x04, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0x63, 0x05, 
    0xE5, 0x05, 0x86, 0x02, 0x27, 0x03, 0xA8, 0x03, 0xC7, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE6, 0x03, 0xE6, 0x03, 0xEB, 0x0F, 0xF3, 0x3B, 0xFB, 0x67, 0x36, 0x00, 
    0x4A, 0x00, 0xFD, 0x6F, 0xF9, 0x5B, 0xF5, 0x47, 0xEF, 0x2B, 0xEA, 0x0B, 0xE6, 0x03, 0xE4, 0x03, 
    0xE5, 0x03, 0xE6, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xC8, 0x03, 0xA7, 0x03, 0x47, 0x03, 0xE6, 0x02, 0xA5, 0x02, 
    0x65, 0x02, 0x24, 0x02, 0x04, 0x06, 0xE4, 0x05, 0xA3, 0x05, 0x83, 0x01, 0x43, 0x01, 0x22, 0x01, 
    0xE2, 0x04, 0xC2, 0x04, 0xA2, 0x08, 0xC3, 0x08, 0xE3, 0x08, 0x03, 0x09, 0x24, 0x09, 0x24, 0x09, 
    0x44, 0x09, 0x44, 0x09, 0x44, 0x09, 0x24, 0x09, 0x44, 0x09, 0x64, 0x09, 0x65, 0x09, 0x65, 0x09, 
    0x64, 0x09, 0x44, 0x09, 0x23, 0x09, 0x03, 0x09, 0xE3, 0x08, 0xC3, 0x08, 0xE3, 0x08, 0x03, 0x09, 
    0x23, 0x09, 0x03, 0x09, 0xE3, 0x04, 0x23, 0x05, 0x83, 0x01, 0x25, 0x02, 0xC6, 0x02, 0x47, 0x03, 
    0xA7, 0x03, 0xC7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE6, 0x03, 0xE6, 0x03, 
    0xEB, 0x0F, 0xF3, 0x3B, 0xFB, 0x67, 0x36, 0x00, 0x4A, 0x00, 0xFA, 0x5F, 0xF3, 0x3B, 0xED, 0x1F, 
    0xE9, 0x13, 0xE8, 0x07, 0xE8, 0x03, 0xE7, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xA7, 0x03, 
    0x47, 0x03, 0xE6, 0x02, 0x65, 0x02, 0x24, 0x02, 0xE4, 0x05, 0xA3, 0x05, 0x63, 0x05, 0x63, 0x05, 
    0x43, 0x01, 0x23, 0x01, 0x02, 0x01, 0xE2, 0x00, 0xC2, 0x04, 0xC2, 0x04, 0xC2, 0x08, 0xE3, 0x08, 
    0x03, 0x09, 0x24, 0x09, 0x44, 0x09, 0x65, 0x09, 0x65, 0x09, 0x65, 0x09, 0x65, 0x09, 0x64, 0x09, 
    0x64, 0x09, 0x85, 0x0D, 0x86, 0x0D, 0x86, 0x0D, 0x65, 0x0D, 0x44, 0x0D, 0x23, 0x0D, 0xE3, 0x0C, 
    0xC3, 0x08, 0xC3, 0x08, 0x03, 0x09, 0x24, 0x0D, 0x45, 0x0D, 0x24, 0x09, 0x03, 0x05, 0x02, 0x05, 
    0x63, 0x01, 0xE3, 0x01, 0x65, 0x02, 0x06, 0x03, 0x67, 0x03, 0xC8, 0x03, 0xE9, 0x03, 0xE9, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE6, 0x03, 0xE6, 0x03, 0xEB, 0x0F, 0xF3, 0x3B, 0xFB, 0x67, 0x34, 0x00, 
    0x4C, 0x00, 0xFF, 0x7B, 0xFC, 0x6F, 0xF5, 0x47, 0xED, 0x1B, 0xE7, 0x03, 0xE5, 0x03, 0xE7, 0x03, 
    0xE8, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE9, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xC8, 0x03, 0xA7, 0x03, 0x46, 0x03, 0xC6, 0x02, 0x45, 0x02, 
    0xE5, 0x01, 0x84, 0x05, 0x63, 0x05, 0x23, 0x05, 0x03, 0x05, 0x03, 0x05, 0x03, 0x05, 0xE3, 0x00, 
    0xC2, 0x00, 0xC2, 0x04, 0xC2, 0x04, 0xE2, 0x08, 0xE3, 0x08, 0x03, 0x09, 0x24, 0x09, 0x44, 0x09, 
    0x65, 0x09, 0x86, 0x09, 0x86, 0x0D, 0xA6, 0x0D, 0x86, 0x0D, 0x85, 0x0D, 0x85, 0x0D, 0xA6, 0x0D, 
    0xA6, 0x0D, 0xA6, 0x0D, 0x86, 0x0D, 0x65, 0x0D, 0x24, 0x0D, 0x03, 0x0D, 0xE3, 0x0C, 0xE3, 0x08, 
    0x24, 0x0D, 0x65, 0x0D, 0x65, 0x0D, 0x44, 0x09, 0x03, 0x05, 0xE2, 0x04, 0x22, 0x01, 0xA3, 0x01, 
    0x24, 0x02, 0xC5, 0x02, 0x47, 0x03, 0xA8, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE6, 0x03, 0xE6, 0x03, 0xEB, 0x0F, 0xF3, 0x3B, 0xFB, 0x67, 0x32, 0x00, 0x4E, 0x00, 0xFE, 0x7B, 
    0xFC, 0x6B, 0xF9, 0x5B, 0xF5, 0x4B, 0xEF, 0x2B, 0xEA, 0x0B, 0xE5, 0x03, 0xE5, 0x03, 0xE7, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xC7, 0x03, 0x87, 0x03, 0x46, 0x03, 0xC6, 0x02, 0x45, 0x02, 0xC4, 0x01, 
    0x64, 0x01, 0x43, 0x05, 0x23, 0x05, 0x03, 0x09, 0x03, 0x09, 0x04, 0x09, 0x04, 0x05, 0x04, 0x05, 
    0xE3, 0x04, 0xE3, 0x04, 0x03, 0x09, 0x03, 0x09, 0x23, 0x0D, 0x44, 0x0D, 0x44, 0x0D, 0x65, 0x0D, 
    0x85, 0x0D, 0xA6, 0x0D, 0xA6, 0x0D, 0xA6, 0x0D, 0xA6, 0x0D, 0xA6, 0x11, 0xA6, 0x11, 0xC6, 0x11, 
    0xC7, 0x0D, 0xA7, 0x0D, 0x86, 0x0D, 0x65, 0x0D, 0x45, 0x0D, 0x24, 0x0D, 0x04, 0x0D, 0x04, 0x0D, 
    0x44, 0x0D, 0x65, 0x0D, 0x85, 0x0D, 0x44, 0x09, 0x03, 0x05, 0xE2, 0x04, 0x22, 0x01, 0x63, 0x01, 
    0x04, 0x02, 0xA5, 0x02, 0x26, 0x03, 0xA7, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE5, 0x03, 0xE4, 0x03, 0xE9, 0x07, 0xF2, 0x37, 0xFB, 0x67, 0x32, 0x00, 0x4E, 0x00, 0xFD, 0x77, 
    0xF8, 0x57, 0xF2, 0x37, 0xED, 0x23, 0xEA, 0x13, 0xE9, 0x03, 0xE7, 0x03, 0xE7, 0x03, 0xE7, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xC7, 0x03, 0x87, 0x03, 0x27, 0x03, 0xC6, 0x02, 0x45, 0x02, 0xC4, 0x01, 0x63, 0x01, 
    0x23, 0x01, 0x03, 0x05, 0x23, 0x05, 0x23, 0x09, 0x24, 0x09, 0x45, 0x09, 0x45, 0x09, 0x45, 0x09, 
    0x44, 0x09, 0x44, 0x09, 0x44, 0x09, 0x44, 0x0D, 0x64, 0x0D, 0x65, 0x0D, 0x85, 0x0D, 0x86, 0x0D, 
    0xA6, 0x0D, 0xA6, 0x0D, 0xA6, 0x0D, 0xA6, 0x0D, 0xC6, 0x11, 0xC6, 0x11, 0xC6, 0x11, 0xC6, 0x11, 
    0xC6, 0x11, 0xA6, 0x0D, 0xA6, 0x0D, 0x86, 0x0D, 0x66, 0x0D, 0x45, 0x0D, 0x45, 0x0D, 0x45, 0x0D, 
    0x65, 0x0D, 0x85, 0x0D, 0x85, 0x09, 0x44, 0x09, 0x03, 0x05, 0xE3, 0x04, 0x23, 0x01, 0x83, 0x01, 
    0x04, 0x02, 0xA5, 0x02, 0x26, 0x03, 0x87, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE7, 0x03, 
    0xE4, 0x03, 0xE3, 0x03, 0xE8, 0x03, 0xF1, 0x33, 0xFA, 0x63, 0x32, 0x00, 0x4E, 0x00, 0xFD, 0x73, 
    0xF5, 0x47, 0xED, 0x17, 0xE7, 0x03, 0xE6, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xC8, 0x03, 
    0xA7, 0x03, 0x66, 0x03, 0x06, 0x03, 0xA5, 0x02, 0x25, 0x06, 0xA4, 0x05, 0x43, 0x05, 0x02, 0x01, 
    0xE2, 0x04, 0x03, 0x05, 0x23, 0x05, 0x44, 0x09, 0x65, 0x09, 0x65, 0x0D, 0x65, 0x0D, 0x65, 0x0D, 
    0x65, 0x09, 0x85, 0x09, 0x84, 0x09, 0x84, 0x0D, 0x85, 0x0D, 0x85, 0x0D, 0x85, 0x0D, 0x86, 0x0D, 
    0x86, 0x0D, 0x85, 0x0D, 0x85, 0x0D, 0x85, 0x0D, 0x85, 0x11, 0x85, 0x11, 0xA6, 0x11, 0xA6, 0x11, 
    0xA6, 0x11, 0xA6, 0x11, 0xA6, 0x0D, 0x86, 0x0D, 0x86, 0x0D, 0x66, 0x0D, 0x66, 0x11, 0x65, 0x0D, 
    0x65, 0x0D, 0x85, 0x0D, 0x64, 0x09, 0x44, 0x09, 0x04, 0x05, 0x03, 0x05, 0x44, 0x01, 0x84, 0x01, 
    0x05, 0x02, 0xA6, 0x02, 0x26, 0x03, 0x87, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE6, 0x03, 0xE6, 0x03, 0xEB, 0x13, 0xF3, 0x3B, 0xFB, 0x67, 0x32, 0x00, 0x4E, 0x00, 0xFC, 0x6F, 
    0xF4, 0x3F, 0xEB, 0x0F, 0xE5, 0x03, 0xE4, 0x03, 0xE7, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xC8, 0x03, 0x87, 0x03, 
    0x46, 0x03, 0xE6, 0x02, 0x65, 0x02, 0x04, 0x02, 0xA4, 0x05, 0x23, 0x05, 0xE2, 0x04, 0xC2, 0x04, 
    0xC2, 0x04, 0xE3, 0x08, 0x24, 0x09, 0x64, 0x0D, 0x65, 0x0D, 0x65, 0x0D, 0x85, 0x0D, 0x85, 0x0D, 
    0x85, 0x0D, 0x85, 0x09, 0x85, 0x09, 0x85, 0x09, 0x85, 0x0D, 0x85, 0x0D, 0x85, 0x0D, 0x65, 0x0D, 
    0x65, 0x0D, 0x45, 0x0D, 0x44, 0x09, 0x24, 0x0D, 0x24, 0x0D, 0x24, 0x0D, 0x44, 0x11, 0x65, 0x11, 
    0x85, 0x11, 0x86, 0x11, 0xA6, 0x11, 0x87, 0x11, 0x87, 0x0D, 0x87, 0x0D, 0x86, 0x11, 0x86, 0x0D, 
    0x85, 0x0D, 0x85, 0x0D, 0x64, 0x09, 0x24, 0x09, 0x04, 0x05, 0x04, 0x01, 0x44, 0x01, 0xC4, 0x01, 
    0x45, 0x02, 0xC6, 0x02, 0x46, 0x03, 0xA7, 0x03, 0xE7, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xE9, 0x07, 
    0xEA, 0x17, 0xED, 0x23, 0xF1, 0x33, 0xF7, 0x53, 0xFC, 0x6F, 0x32, 0x00, 0x4E, 0x00, 0xFD, 0x6F, 
    0xF4, 0x43, 0xEC, 0x13, 0xE6, 0x03, 0xE5, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xC8, 0x03, 0xA7, 0x03, 0x26, 0x03, 
    0xC6, 0x02, 0x45, 0x02, 0xC4, 0x01, 0x63, 0x01, 0x23, 0x05, 0xE2, 0x04, 0xC2, 0x04, 0xC2, 0x04, 
    0xC2, 0x08, 0x03, 0x09, 0x44, 0x0D, 0x65, 0x0D, 0x85, 0x0D, 0x85, 0x11, 0x85, 0x0D, 0x85, 0x0D, 
    0x85, 0x09, 0x85, 0x09, 0x85, 0x09, 0x65, 0x09, 0x65, 0x09, 0x64, 0x09, 0x44, 0x09, 0x44, 0x09, 
    0x24, 0x09, 0x04, 0x09, 0xE3, 0x08, 0xC3, 0x08, 0xC3, 0x08, 0xC2, 0x08, 0xE3, 0x0C, 0x03, 0x0D, 
    0x44, 0x0D, 0x65, 0x11, 0x86, 0x11, 0xA7, 0x11, 0xA7, 0x11, 0xA7, 0x0D, 0xA6, 0x0D, 0x85, 0x0D, 
    0x85, 0x0D, 0x65, 0x0D, 0x45, 0x09, 0x24, 0x09, 0x04, 0x05, 0x23, 0x01, 0x64, 0x01, 0xE5, 0x01, 
    0x86, 0x02, 0x06, 0x03, 0x67, 0x03, 0xA8, 0x03, 0xE8, 0x03, 0xE7, 0x03, 0xE7, 0x03, 0xEB, 0x0F, 
    0xEF, 0x2B, 0xF4, 0x4B, 0xF8, 0x5B, 0xFB, 0x6B, 0xFE, 0x77, 0x32, 0x00, 0x4B, 0x00, 0xFD, 0x73, 
    0xF5, 0x47, 0xED, 0x1B, 0xE7, 0x03, 0xE6, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xC8, 0x03, 0x87, 0x03, 0x46, 0x03, 0xA5, 0x02, 
    0x24, 0x02, 0xA4, 0x01, 0x23, 0x01, 0xE2, 0x00, 0xC2, 0x04, 0xC2, 0x08, 0xA2, 0x08, 0xC2, 0x08, 
    0xE3, 0x08, 0x24, 0x0D, 0x64, 0x0D, 0x85, 0x11, 0x85, 0x11, 0x85, 0x0D, 0x85, 0x0D, 0x85, 0x0D, 
    0x85, 0x09, 0x65, 0x09, 0x65, 0x05, 0x65, 0x05, 0x64, 0x05, 0x44, 0x05, 0x43, 0x05, 0x23, 0x05, 
    0xE3, 0x04, 0xC3, 0x04, 0xA3, 0x04, 0x62, 0x04, 0x61, 0x04, 0x41, 0x04, 0x81, 0x08, 0xA2, 0x08, 
    0x03, 0x0D, 0x44, 0x0D, 0x66, 0x11, 0x87, 0x11, 0xA7, 0x11, 0xC7, 0x0D, 0xA6, 0x0D, 0xA5, 0x0D, 
    0x85, 0x0D, 0x65, 0x0D, 0x44, 0x09, 0x24, 0x09, 0x03, 0x05, 0x23, 0x01, 0xA4, 0x01, 0x25, 0x02, 
    0xC6, 0x02, 0x47, 0x03, 0x87, 0x03, 0xA8, 0x03, 0xE8, 0x03, 0xE6, 0x03, 0xE6, 0x03, 0xEC, 0x13, 
    0xF4, 0x3F, 0xFB, 0x6B, 0x35, 0x00, 0x4B, 0x00, 0xFD, 0x73, 0xF5, 0x47, 0xED, 0x1B, 0xE7, 0x03, 
    0xE6, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 
    0xC8, 0x03, 0x87, 0x03, 0x26, 0x03, 0xA5, 0x02, 0x04, 0x02, 0x83, 0x01, 0x02, 0x01, 0xA2, 0x00, 
    0x82, 0x04, 0xA2, 0x04, 0xA2, 0x08, 0xC2, 0x08, 0xE3, 0x08, 0x24, 0x0D, 0x44, 0x0D, 0x64, 0x0D, 
    0x65, 0x0D, 0x64, 0x0D, 0x64, 0x0D, 0x44, 0x0D, 0x64, 0x09, 0x64, 0x09, 0x64, 0x05, 0x84, 0x05, 
    0x84, 0x05, 0x84, 0x05, 0x64, 0x01, 0x43, 0x01, 0x22, 0x01, 0xE2, 0x00, 0xA2, 0x04, 0x82, 0x04, 
    0x41, 0x04, 0x21, 0x04, 0x21, 0x04, 0x41, 0x04, 0x81, 0x08, 0xC2, 0x08, 0x24, 0x0D, 0x65, 0x0D, 
    0x86, 0x0D, 0xC7, 0x11, 0xC6, 0x0D, 0xC6, 0x0D, 0xA5, 0x0D, 0x84, 0x0D, 0x44, 0x09, 0x24, 0x09, 
    0x23, 0x05, 0x23, 0x05, 0x64, 0x01, 0xE4, 0x01, 0x66, 0x02, 0x06, 0x03, 0x67, 0x03, 0x88, 0x03, 
    0xA8, 0x03, 0xC7, 0x03, 0xC5, 0x03, 0xC5, 0x03, 0xEB, 0x13, 0xF5, 0x47, 0xFE, 0x77, 0x35, 0x00, 
    0x4B, 0x00, 0xFD, 0x73, 0xF5, 0x47, 0xEC, 0x1B, 0xE6, 0x03, 0xE6, 0x03, 0xE7, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xA8, 0x03, 0x47, 0x03, 0xC6, 0x02, 
    0x24, 0x02, 0x83, 0x01, 0x02, 0x01, 0xA1, 0x00, 0x61, 0x00, 0x82, 0x04, 0xA2, 0x08, 0xC3, 0x08, 
    0xE3, 0x08, 0x24, 0x0D, 0x44, 0x0D, 0x64, 0x0D, 0x64, 0x0D, 0x64, 0x0D, 0x44, 0x0D, 0x24, 0x0D, 
    0x24, 0x09, 0x24, 0x09, 0x44, 0x05, 0x63, 0x05, 0x84, 0x01, 0x84, 0x01, 0xA4, 0x01, 0x83, 0x01, 
    0x63, 0x01, 0x22, 0x01, 0xE2, 0x00, 0xC1, 0x00, 0xA1, 0x00, 0x61, 0x00, 0x41, 0x04, 0x21, 0x04, 
    0x41, 0x04, 0x61, 0x04, 0xA2, 0x04, 0xE3, 0x08, 0x44, 0x0D, 0x86, 0x0D, 0xC6, 0x0D, 0xC6, 0x11, 
    0xC5, 0x0D, 0xA5, 0x0D, 0x64, 0x09, 0x44, 0x09, 0x23, 0x05, 0x23, 0x05, 0x43, 0x05, 0xA4, 0x05, 
    0x25, 0x02, 0xA6, 0x02, 0x27, 0x03, 0x87, 0x03, 0xA8, 0x03, 0xA7, 0x03, 0xC6, 0x03, 0xC4, 0x03, 
    0xC4, 0x03, 0xEA, 0x0B, 0xF4, 0x3F, 0xFD, 0x73, 0x35, 0x00, 0x4B, 0x00, 0xFD, 0x73, 0xF4, 0x47, 
    0xEC, 0x1B, 0xE6, 0x03, 0xE5, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE7, 0x03, 
    0xE8, 0x03, 0xC8, 0x03, 0x68, 0x03, 0xE6, 0x02, 0x25, 0x02, 0x84, 0x05, 0xE2, 0x04, 0xA1, 0x00, 
    0x81, 0x00, 0x61, 0x00, 0x82, 0x04, 0xA3, 0x08, 0xE4, 0x08, 0x24, 0x0D, 0x65, 0x0D, 0x85, 0x0D, 
    0x85, 0x09, 0x64, 0x09, 0x44, 0x09, 0x44, 0x09, 0x24, 0x09, 0x24, 0x09, 0x43, 0x05, 0x63, 0x05, 
    0x83, 0x01, 0xA3, 0x01, 0xE3, 0x01, 0xE4, 0x01, 0xC3, 0x01, 0xA3, 0x01, 0x63, 0x01, 0x42, 0x01, 
    0x02, 0x01, 0xE2, 0x00, 0xA1, 0x00, 0x61, 0x00, 0x41, 0x04, 0x41, 0x04, 0x61, 0x04, 0x82, 0x04, 
    0xE3, 0x04, 0x24, 0x09, 0x85, 0x0D, 0xC6, 0x0D, 0xC6, 0x11, 0xC5, 0x0D, 0xA5, 0x0D, 0x64, 0x09, 
    0x23, 0x09, 0x03, 0x05, 0x23, 0x05, 0x63, 0x05, 0xC4, 0x05, 0x65, 0x02, 0xC6, 0x02, 0x47, 0x03, 
    0x87, 0x03, 0xA7, 0x03, 0x87, 0x03, 0xA6, 0x03, 0xC5, 0x03, 0xC5, 0x03, 0xEB, 0x0F, 0xF4, 0x3F, 
    0xFC, 0x6B, 0x35, 0x00, 0x4B, 0x00, 0xFD, 0x73, 0xF5, 0x47, 0xEC, 0x1B, 0xE6, 0x03, 0xE6, 0x03, 
    0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE7, 0x03, 0xC7, 0x03, 0x87, 0x03, 0x06, 0x03, 
    0x45, 0x02, 0xA4, 0x01, 0x02, 0x05, 0x82, 0x04, 0x81, 0x04, 0x81, 0x00, 0x82, 0x04, 0xA2, 0x04, 
    0xC3, 0x08, 0x04, 0x09, 0x44, 0x09, 0x65, 0x0D, 0x85, 0x0D, 0x65, 0x09, 0x44, 0x09, 0x44, 0x09, 
    0x44, 0x05, 0x64, 0x05, 0x84, 0x05, 0xA4, 0x05, 0xC3, 0x01, 0x03, 0x02, 0x24, 0x02, 0x44, 0x02, 
    0x64, 0x02, 0x44, 0x02, 0x24, 0x02, 0x04, 0x02, 0xC3, 0x01, 0xA3, 0x01, 0x63, 0x01, 0x02, 0x01, 
    0xA1, 0x00, 0x61, 0x00, 0x41, 0x04, 0x61, 0x04, 0xA2, 0x04, 0xE3, 0x08, 0x44, 0x09, 0x85, 0x0D, 
    0xA6, 0x0D, 0xA6, 0x11, 0xA5, 0x0D, 0x85, 0x0D, 0x44, 0x09, 0x23, 0x05, 0x02, 0x05, 0x23, 0x01, 
    0x63, 0x01, 0xE4, 0x01, 0x65, 0x02, 0xE6, 0x02, 0x67, 0x03, 0xA7, 0x03, 0xA6, 0x03, 0x86, 0x03, 
    0xA7, 0x07, 0xC9, 0x13, 0xEB, 0x1B, 0xF1, 0x2F, 0xF7, 0x4F, 0xFD, 0x73, 0x35, 0x00, 0x4B, 0x00, 
    0xFD, 0x73, 0xF5, 0x47, 0xED, 0x1B, 0xE7, 0x03, 0xE6, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xE9, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0x87, 0x03, 0x26, 0x03, 0xA5, 0x02, 0xE4, 0x01, 0x42, 0x01, 0xC2, 0x00, 
    0x61, 0x00, 0x82, 0x04, 0xC2, 0x04, 0xC3, 0x04, 0xC3, 0x04, 0xC3, 0x08, 0x03, 0x09, 0x44, 0x09, 
    0x64, 0x09, 0x85, 0x09, 0x44, 0x09, 0x24, 0x09, 0x23, 0x09, 0x64, 0x05, 0xA4, 0x05, 0x04, 0x02, 
    0x44, 0x02, 0x64, 0x02, 0x84, 0x02, 0xC5, 0x02, 0xC5, 0x02, 0xC6, 0x02, 0xC6, 0x02, 0xC6, 0x02, 
    0xA5, 0x02, 0x65, 0x02, 0x45, 0x02, 0x04, 0x02, 0x83, 0x01, 0xE2, 0x00, 0x81, 0x00, 0x41, 0x00, 
    0x81, 0x04, 0xE2, 0x08, 0x24, 0x09, 0x65, 0x0D, 0x86, 0x0D, 0xA6, 0x11, 0xA6, 0x11, 0x85, 0x0D, 
    0x65, 0x0D, 0x24, 0x09, 0x03, 0x05, 0x02, 0x05, 0x23, 0x01, 0x63, 0x01, 0xC4, 0x01, 0x45, 0x02, 
    0xC6, 0x02, 0x46, 0x03, 0x86, 0x03, 0x85, 0x03, 0x86, 0x03, 0xA9, 0x0F, 0xCE, 0x2B, 0xF3, 0x43, 
    0xF7, 0x53, 0xFB, 0x67, 0xFE, 0x77, 0x35, 0x00, 0x4A, 0x00, 0xFD, 0x73, 0xF5, 0x47, 0xED, 0x1B, 
    0xE7, 0x03, 0xE6, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xC8, 0x03, 0x67, 0x03, 
    0xE6, 0x02, 0x24, 0x02, 0x63, 0x01, 0xE1, 0x00, 0x81, 0x00, 0x81, 0x00, 0xC3, 0x04, 0x04, 0x05, 
    0x04, 0x09, 0x04, 0x09, 0x03, 0x05, 0x03, 0x09, 0x43, 0x09, 0x64, 0x09, 0x64, 0x09, 0x24, 0x09, 
    0x03, 0x09, 0x24, 0x05, 0x84, 0x05, 0x04, 0x02, 0x85, 0x02, 0xC5, 0x02, 0x05, 0x03, 0x26, 0x03, 
    0x46, 0x03, 0x47, 0x03, 0x47, 0x03, 0x47, 0x03, 0x47, 0x03, 0x27, 0x03, 0x07, 0x03, 0xE7, 0x02, 
    0xA6, 0x02, 0x04, 0x02, 0x43, 0x01, 0xA1, 0x00, 0x61, 0x00, 0xA2, 0x04, 0x03, 0x09, 0x44, 0x0D, 
    0x65, 0x0D, 0x86, 0x0D, 0x86, 0x0D, 0x66, 0x0D, 0x45, 0x0D, 0x24, 0x09, 0x24, 0x09, 0x03, 0x05, 
    0x23, 0x05, 0x43, 0x01, 0x63, 0x01, 0xC4, 0x01, 0x45, 0x02, 0xC5, 0x02, 0x46, 0x03, 0x86, 0x03, 
    0x84, 0x03, 0x85, 0x03, 0xAB, 0x17, 0xD3, 0x3F, 0xFB, 0x67, 0xFE, 0x77, 0xFE, 0x7B, 0x36, 0x00, 
    0x48, 0x00, 0xFD, 0x73, 0xF5, 0x47, 0xED, 0x1B, 0xE7, 0x03, 0xE6, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE9, 0x03, 0xE9, 0x03, 0xC8, 0x03, 0x26, 0x03, 0x85, 0x02, 0xC3, 0x01, 0x02, 0x01, 0xA1, 0x00, 
    0x61, 0x00, 0x62, 0x04, 0xC3, 0x04, 0x25, 0x09, 0x45, 0x09, 0x44, 0x09, 0x24, 0x09, 0x23, 0x09, 
    0x23, 0x09, 0x43, 0x09, 0x43, 0x05, 0x43, 0x05, 0x43, 0x05, 0x84, 0x05, 0x04, 0x02, 0x65, 0x02, 
    0x05, 0x03, 0x46, 0x03, 0x66, 0x03, 0x87, 0x03, 0x87, 0x03, 0x87, 0x03, 0x88, 0x03, 0xA8, 0x03, 
    0xA8, 0x03, 0x88, 0x03, 0x87, 0x03, 0x67, 0x03, 0x27, 0x03, 0x65, 0x02, 0xA3, 0x01, 0xE2, 0x00, 
    0x81, 0x00, 0xA2, 0x04, 0x03, 0x09, 0x24, 0x09, 0x44, 0x0D, 0x44, 0x0D, 0x24, 0x0D, 0x24, 0x0D, 
    0x04, 0x09, 0x04, 0x09, 0xE3, 0x08, 0x03, 0x05, 0x23, 0x05, 0x63, 0x01, 0xA4, 0x01, 0x05, 0x02, 
    0x85, 0x02, 0xE6, 0x02, 0x46, 0x03, 0x85, 0x03, 0x83, 0x03, 0x84, 0x03, 0xAC, 0x1B, 0xD5, 0x4B, 
    0xFF, 0x7B, 0x38, 0x00, 0x48, 0x00, 0xFD, 0x73, 0xF5, 0x47, 0xED, 0x1B, 0xE7, 0x03, 0xE6, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xA7, 0x03, 0x06, 0x03, 0x45, 0x02, 0x83, 0x01, 
    0xE2, 0x00, 0x81, 0x00, 0x61, 0x04, 0x82, 0x04, 0xE4, 0x08, 0x45, 0x09, 0x66, 0x09, 0x65, 0x09, 
    0x45, 0x09, 0x24, 0x09, 0x23, 0x09, 0x03, 0x05, 0x23, 0x05, 0x43, 0x05, 0x83, 0x05, 0xE4, 0x01, 
    0x65, 0x02, 0xC6, 0x02, 0x26, 0x03, 0x67, 0x03, 0x87, 0x03, 0x87, 0x03, 0xA7, 0x03, 0xA7, 0x03, 
    0xA7, 0x03, 0xA7, 0x03, 0xA7, 0x03, 0xA7, 0x03, 0xA7, 0x03, 0x87, 0x03, 0x47, 0x03, 0xA5, 0x02, 
    0xC4, 0x01, 0x22, 0x01, 0xA2, 0x00, 0xA2, 0x04, 0xC2, 0x04, 0xC2, 0x08, 0xC3, 0x08, 0xC3, 0x08, 
    0xC3, 0x08, 0xC3, 0x08, 0xA3, 0x08, 0xC3, 0x08, 0xC2, 0x04, 0xE2, 0x04, 0x22, 0x01, 0x83, 0x01, 
    0xE4, 0x01, 0x45, 0x02, 0xC6, 0x02, 0x06, 0x03, 0x47, 0x03, 0x85, 0x03, 0x82, 0x03, 0x63, 0x03, 
    0x8A, 0x13, 0xD5, 0x47, 0xFE, 0x7B, 0x38, 0x00, 0x48, 0x00, 0xFD, 0x73, 0xF5, 0x47, 0xED, 0x1B, 
    0xE7, 0x03, 0xE6, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0x87, 0x03, 0xC5, 0x02, 
    0x24, 0x02, 0x63, 0x01, 0xC2, 0x00, 0x82, 0x00, 0x62, 0x04, 0x83, 0x08, 0xE4, 0x08, 0x45, 0x09, 
    0x66, 0x09, 0x86, 0x0D, 0x65, 0x0D, 0x44, 0x0D, 0x03, 0x09, 0x03, 0x05, 0x22, 0x01, 0x63, 0x01, 
    0xE4, 0x01, 0x65, 0x02, 0xC6, 0x02, 0x06, 0x03, 0x47, 0x03, 0x68, 0x03, 0x68, 0x03, 0x87, 0x03, 
    0x87, 0x03, 0x87, 0x03, 0x87, 0x03, 0xA7, 0x03, 0xA7, 0x03, 0x87, 0x03, 0x87, 0x03, 0x87, 0x03, 
    0x67, 0x03, 0xC5, 0x02, 0x24, 0x02, 0x63, 0x01, 0xC2, 0x00, 0xA2, 0x00, 0xA2, 0x00, 0x81, 0x04, 
    0x81, 0x04, 0x81, 0x04, 0x81, 0x04, 0x81, 0x04, 0x82, 0x04, 0xA2, 0x04, 0xC2, 0x04, 0x02, 0x01, 
    0x63, 0x01, 0xC3, 0x01, 0x24, 0x02, 0xA6, 0x02, 0x07, 0x03, 0x47, 0x03, 0x67, 0x03, 0x86, 0x03, 
    0x63, 0x03, 0x64, 0x03, 0x8B, 0x13, 0xD4, 0x43, 0xFD, 0x73, 0x38, 0x00, 0x48, 0x00, 0xFD, 0x73, 
    0xF5, 0x47, 0xED, 0x1B, 0xE7, 0x03, 0xE6, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xC7, 0x03, 
    0x46, 0x03, 0x85, 0x02, 0xC4, 0x01, 0x03, 0x01, 0xA2, 0x00, 0x82, 0x04, 0x82, 0x04, 0xC3, 0x08, 
    0x04, 0x09, 0x65, 0x09, 0x86, 0x0D, 0x86, 0x0D, 0x65, 0x0D, 0x45, 0x0D, 0x03, 0x09, 0xE2, 0x04, 
    0x22, 0x01, 0xA3, 0x01, 0x44, 0x02, 0xC5, 0x02, 0x26, 0x03, 0x47, 0x03, 0x88, 0x03, 0x88, 0x03, 
    0x68, 0x03, 0x67, 0x03, 0x67, 0x03, 0x67, 0x03, 0x66, 0x03, 0x66, 0x03, 0x66, 0x03, 0x66, 0x03, 
    0x66, 0x03, 0x87, 0x03, 0x66, 0x03, 0x06, 0x03, 0x85, 0x02, 0xE4, 0x01, 0x63, 0x01, 0x23, 0x01, 
    0xE2, 0x00, 0xA1, 0x00, 0x61, 0x00, 0x61, 0x00, 0x41, 0x00, 0x41, 0x00, 0x61, 0x04, 0xA2, 0x04, 
    0x02, 0x01, 0x42, 0x01, 0xC3, 0x01, 0x44, 0x02, 0x85, 0x02, 0xE6, 0x02, 0x47, 0x03, 0x67, 0x03, 
    0x67, 0x03, 0x88, 0x07, 0x88, 0x0B, 0x8A, 0x13, 0xAF, 0x2B, 0xD6, 0x4F, 0xFD, 0x73, 0x38, 0x00, 
    0x48, 0x00, 0xFF, 0x7B, 0xF6, 0x4F, 0xEE, 0x1B, 0xE7, 0x03, 0xE6, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xC8, 0x03, 0xA8, 0x03, 0x26, 0x03, 0x65, 0x02, 0xA3, 0x01, 0xE2, 0x00, 0x81, 0x00, 0x82, 0x00, 
    0xA2, 0x04, 0xC3, 0x08, 0x24, 0x09, 0x65, 0x0D, 0x85, 0x0D, 0x85, 0x0D, 0x65, 0x0D, 0x44, 0x0D, 
    0x23, 0x09, 0x02, 0x05, 0x62, 0x05, 0xE3, 0x01, 0x85, 0x02, 0x26, 0x03, 0x67, 0x03, 0x87, 0x03, 
    0x87, 0x03, 0x88, 0x03, 0x68, 0x03, 0x47, 0x03, 0x47, 0x03, 0x46, 0x03, 0x46, 0x03, 0x46, 0x03, 
    0x46, 0x03, 0x46, 0x03, 0x46, 0x03, 0x86, 0x03, 0x87, 0x03, 0x46, 0x03, 0x06, 0x03, 0x85, 0x02, 
    0x24, 0x02, 0xC4, 0x01, 0x63, 0x01, 0x02, 0x01, 0xA1, 0x00, 0x61, 0x00, 0x41, 0x00, 0x41, 0x00, 
    0x81, 0x00, 0xE2, 0x00, 0x43, 0x01, 0xA3, 0x01, 0x25, 0x02, 0xA5, 0x02, 0xE6, 0x02, 0x27, 0x03, 
    0x47, 0x03, 0x66, 0x03, 0x67, 0x03, 0x8A, 0x0F, 0xAD, 0x27, 0xB2, 0x3B, 0xD6, 0x4F, 0xFA, 0x63, 
    0xFE, 0x7B, 0x38, 0x00, 0x47, 0x00, 0xFF, 0x7B, 0xF6, 0x4F, 0xEE, 0x1B, 0xE7, 0x03, 0xE6, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xC8, 0x03, 0x88, 0x03, 0x06, 0x03, 0x24, 0x02, 0x63, 0x01, 0xC1, 0x00, 
    0x61, 0x00, 0x81, 0x00, 0xC2, 0x04, 0xE3, 0x08, 0x24, 0x0D, 0x65, 0x0D, 0x65, 0x0D, 0x65, 0x0D, 
    0x44, 0x0D, 0x44, 0x09, 0x23, 0x09, 0x22, 0x05, 0x83, 0x05, 0x24, 0x02, 0xC5, 0x02, 0x46, 0x03, 
    0x66, 0x03, 0x87, 0x03, 0x67, 0x03, 0x67, 0x03, 0x47, 0x03, 0x27, 0x03, 0x06, 0x03, 0x06, 0x03, 
    0x05, 0x03, 0xE5, 0x02, 0xE5, 0x02, 0x06, 0x03, 0x26, 0x03, 0x46, 0x03, 0x66, 0x03, 0x66, 0x03, 
    0x46, 0x03, 0x06, 0x03, 0xA5, 0x02, 0x64, 0x02, 0x04, 0x02, 0x83, 0x01, 0xE2, 0x00, 0xA2, 0x00, 
    0x62, 0x00, 0x81, 0x00, 0xC2, 0x00, 0x42, 0x01, 0xC4, 0x01, 0x25, 0x02, 0xA6, 0x02, 0x07, 0x03, 
    0x27, 0x03, 0x47, 0x03, 0x66, 0x03, 0x65, 0x03, 0x67, 0x03, 0xAC, 0x1B, 0xD3, 0x3F, 0xFA, 0x63, 
    0xFC, 0x6F, 0xFE, 0x77, 0x37, 0x00, 0x46, 0x00, 0xFE, 0x7B, 0xFD, 0x73, 0xFA, 0x63, 0xF3, 0x3F, 
    0xEC, 0x17, 0xE7, 0x03, 0xE6, 0x03, 0xE8, 0x03, 0xC8, 0x03, 0x88, 0x03, 0x47, 0x03, 0xA6, 0x02, 
    0xE4, 0x01, 0x22, 0x01, 0x81, 0x00, 0x61, 0x00, 0x82, 0x00, 0xE3, 0x04, 0x23, 0x09, 0x44, 0x0D, 
    0x64, 0x0D, 0x65, 0x11, 0x44, 0x0D, 0x44, 0x0D, 0x23, 0x09, 0x23, 0x09, 0x22, 0x05, 0x83, 0x05, 
    0x04, 0x02, 0x85, 0x02, 0x06, 0x03, 0x26, 0x03, 0x26, 0x03, 0x06, 0x03, 0xE6, 0x02, 0xC6, 0x02, 
    0xA6, 0x02, 0x85, 0x02, 0x85, 0x02, 0x65, 0x02, 0x64, 0x02, 0x65, 0x02, 0x85, 0x02, 0xA5, 0x02, 
    0xC5, 0x02, 0xE5, 0x02, 0x06, 0x03, 0x26, 0x03, 0x26, 0x03, 0x06, 0x03, 0xC5, 0x02, 0x85, 0x02, 
    0x04, 0x02, 0x83, 0x01, 0x23, 0x01, 0xE2, 0x00, 0xE2, 0x00, 0x43, 0x01, 0xC3, 0x01, 0x24, 0x02, 
    0xA6, 0x02, 0x07, 0x03, 0x47, 0x03, 0x67, 0x03, 0x67, 0x03, 0x66, 0x03, 0x64, 0x03, 0x86, 0x03, 
    0xAD, 0x1F, 0xD7, 0x53, 0x39, 0x00, 0x47, 0x00, 0xFE, 0x77, 0xFA, 0x63, 0xF6, 0x4F, 0xF2, 0x3F, 
    0xEE, 0x27, 0xEA, 0x0F, 0xE7, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xC8, 0x03, 0x67, 0x03, 0x06, 0x03, 
    0x65, 0x02, 0xA3, 0x01, 0xE2, 0x00, 0x61, 0x00, 0x61, 0x04, 0xA2, 0x04, 0xE3, 0x08, 0x24, 0x09, 
    0x64, 0x0D, 0x65, 0x0D, 0x65, 0x0D, 0x44, 0x0D, 0x24, 0x0D, 0x03, 0x09, 0x02, 0x05, 0x22, 0x05, 
    0x62, 0x01, 0xC3, 0x01, 0x24, 0x02, 0x85, 0x02, 0x85, 0x02, 0x84, 0x02, 0x64, 0x02, 0x44, 0x02, 
    0x24, 0x02, 0x04, 0x02, 0xE4, 0x01, 0xE4, 0x01, 0xE4, 0x01, 0xE4, 0x01, 0xE4, 0x01, 0x04, 0x02, 
    0x04, 0x02, 0x24, 0x02, 0x44, 0x02, 0x65, 0x02, 0xA5, 0x02, 0xC5, 0x02, 0xE6, 0x02, 0x06, 0x03, 
    0xE5, 0x02, 0xA5, 0x02, 0x24, 0x02, 0xA4, 0x01, 0x83, 0x01, 0x83, 0x01, 0xC4, 0x01, 0x24, 0x02, 
    0x85, 0x02, 0xE6, 0x02, 0x27, 0x03, 0x67, 0x03, 0x68, 0x03, 0x88, 0x03, 0x86, 0x03, 0x63, 0x03, 
    0x84, 0x03, 0xAC, 0x1B, 0xD6, 0x4F, 0x39, 0x00, 0x48, 0x00, 0xFC, 0x6F, 0xF6, 0x4F, 0xEF, 0x2B, 
    0xEA, 0x17, 0xE8, 0x0F, 0xE8, 0x07, 0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xC8, 0x03, 0x47, 0x03, 
    0xC6, 0x02, 0x24, 0x02, 0x63, 0x01, 0xC2, 0x00, 0x61, 0x04, 0x62, 0x04, 0xA3, 0x08, 0x04, 0x09, 
    0x44, 0x0D, 0x65, 0x0D, 0x85, 0x0D, 0x65, 0x0D, 0x44, 0x0D, 0x04, 0x09, 0xE3, 0x08, 0xE3, 0x04, 
    0x02, 0x01, 0x22, 0x01, 0x62, 0x01, 0xA3, 0x01, 0xE3, 0x01, 0xE3, 0x01, 0xE3, 0x01, 0xC3, 0x05, 
    0xA3, 0x01, 0x83, 0x01, 0x63, 0x01, 0x63, 0x01, 0x63, 0x01, 0x63, 0x01, 0x63, 0x01, 0x84, 0x01, 
    0x84, 0x01, 0x84, 0x01, 0x83, 0x01, 0x83, 0x01, 0xC3, 0x01, 0xE4, 0x01, 0x45, 0x06, 0x85, 0x02, 
    0xE6, 0x02, 0x06, 0x03, 0xE6, 0x02, 0xA5, 0x02, 0x44, 0x02, 0x24, 0x02, 0x24, 0x02, 0x45, 0x02, 
    0x85, 0x02, 0xC6, 0x02, 0x06, 0x03, 0x46, 0x03, 0x67, 0x03, 0x67, 0x03, 0x88, 0x03, 0x85, 0x03, 
    0x83, 0x03, 0x83, 0x03, 0xAB, 0x17, 0xD5, 0x4B, 0xFE, 0x77, 0x38, 0x00, 0x48, 0x00, 0xFB, 0x6B, 
    0xF3, 0x3F, 0xEA, 0x0F, 0xE4, 0x03, 0xE4, 0x03, 0xE6, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 
    0xA8, 0x03, 0x26, 0x03, 0x85, 0x02, 0xC3, 0x01, 0x22, 0x01, 0xA1, 0x00, 0x61, 0x04, 0x62, 0x04, 
    0xA3, 0x08, 0x04, 0x09, 0x45, 0x0D, 0x65, 0x0D, 0x65, 0x0D, 0x65, 0x0D, 0x45, 0x0D, 0x04, 0x0D, 
    0xE4, 0x08, 0xE3, 0x04, 0x03, 0x05, 0x02, 0x01, 0x22, 0x01, 0x43, 0x01, 0x63, 0x01, 0x63, 0x05, 
    0x63, 0x05, 0x42, 0x05, 0x42, 0x05, 0x22, 0x05, 0x02, 0x01, 0x02, 0x01, 0x02, 0x05, 0x23, 0x05, 
    0x23, 0x05, 0x23, 0x05, 0x44, 0x05, 0x44, 0x05, 0x23, 0x01, 0x23, 0x01, 0x43, 0x01, 0x83, 0x05, 
    0xC4, 0x05, 0x25, 0x06, 0x85, 0x02, 0xC5, 0x02, 0x06, 0x03, 0xE5, 0x02, 0xC5, 0x02, 0xA5, 0x02, 
    0xC6, 0x02, 0xC6, 0x02, 0xE6, 0x02, 0x06, 0x03, 0x26, 0x03, 0x46, 0x03, 0x66, 0x03, 0x87, 0x03, 
    0x87, 0x03, 0x87, 0x03, 0x86, 0x07, 0x88, 0x0B, 0xAE, 0x27, 0xD6, 0x4F, 0xFD, 0x77, 0x38, 0x00, 
    0x48, 0x00, 0xFB, 0x6B, 0xF2, 0x3B, 0xE9, 0x0B, 0xE4, 0x03, 0xE4, 0x03, 0xE7, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xA7, 0x03, 0x06, 0x03, 0x64, 0x02, 0xA3, 0x01, 0x02, 0x01, 0x81, 0x00, 
    0x41, 0x04, 0x41, 0x04, 0x82, 0x04, 0xE3, 0x08, 0x24, 0x09, 0x45, 0x0D, 0x65, 0x0D, 0x65, 0x0D, 
    0x45, 0x0D, 0x25, 0x0D, 0x24, 0x09, 0x04, 0x09, 0x24, 0x05, 0x23, 0x05, 0x23, 0x05, 0x43, 0x05, 
    0x43, 0x05, 0x43, 0x05, 0x43, 0x09, 0x43, 0x09, 0x43, 0x09, 0x43, 0x05, 0x43, 0x05, 0x43, 0x05, 
    0x23, 0x05, 0x23, 0x05, 0x23, 0x05, 0x44, 0x05, 0x44, 0x05, 0x44, 0x05, 0x44, 0x05, 0x23, 0x05, 
    0x43, 0x05, 0x43, 0x05, 0x84, 0x05, 0xC4, 0x05, 0x04, 0x06, 0x44, 0x02, 0xA5, 0x02, 0xC5, 0x02, 
    0xE5, 0x02, 0x06, 0x03, 0x06, 0x03, 0x27, 0x03, 0x27, 0x03, 0x47, 0x03, 0x66, 0x03, 0x66, 0x03, 
    0x66, 0x03, 0x66, 0x03, 0x87, 0x03, 0x89, 0x0F, 0xAC, 0x23, 0xD0, 0x33, 0xD4, 0x47, 0xF9, 0x63, 
    0xFE, 0x7B, 0x38, 0x00, 0x47, 0x00, 0xFC, 0x6B, 0xF3, 0x3F, 0xEB, 0x13, 0xE6, 0x03, 0xE5, 0x03, 
    0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0x87, 0x03, 0x06, 0x03, 0x44, 0x02, 0x83, 0x01, 
    0xE1, 0x00, 0x81, 0x00, 0x61, 0x00, 0x41, 0x00, 0x81, 0x04, 0xC2, 0x04, 0x03, 0x09, 0x24, 0x0D, 
    0x45, 0x0D, 0x66, 0x11, 0x65, 0x11, 0x45, 0x0D, 0x45, 0x0D, 0x45, 0x09, 0x45, 0x09, 0x44, 0x05, 
    0x44, 0x05, 0x44, 0x09, 0x63, 0x09, 0x63, 0x09, 0x63, 0x09, 0x84, 0x09, 0x84, 0x09, 0x85, 0x09, 
    0x85, 0x09, 0x85, 0x05, 0x84, 0x09, 0x64, 0x05, 0x64, 0x05, 0x64, 0x05, 0x84, 0x05, 0x84, 0x05, 
    0x85, 0x05, 0x85, 0x05, 0x64, 0x05, 0x64, 0x05, 0x63, 0x05, 0x63, 0x05, 0x83, 0x05, 0xA3, 0x05, 
    0x04, 0x06, 0x65, 0x02, 0xC6, 0x02, 0x06, 0x03, 0x27, 0x03, 0x47, 0x03, 0x47, 0x03, 0x67, 0x03, 
    0x67, 0x03, 0x86, 0x03, 0x85, 0x03, 0x64, 0x03, 0x86, 0x03, 0x8C, 0x1B, 0xB2, 0x3F, 0xF8, 0x5F, 
    0xFB, 0x6B, 0xFD, 0x73, 0x39, 0x00, 0x44, 0x00, 0xFC, 0x6B, 0xF4, 0x43, 0xEC, 0x13, 0xE7, 0x03, 
    0xE6, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0x87, 0x03, 0x05, 0x03, 0x64, 0x02, 
    0x83, 0x01, 0x02, 0x01, 0xA1, 0x00, 0x61, 0x00, 0x41, 0x00, 0x61, 0x00, 0xA2, 0x04, 0xE3, 0x08, 
    0x04, 0x09, 0x45, 0x0D, 0x66, 0x11, 0x66, 0x11, 0x65, 0x0D, 0x65, 0x0D, 0x65, 0x0D, 0x65, 0x09, 
    0x65, 0x09, 0x44, 0x09, 0x44, 0x09, 0x43, 0x09, 0x63, 0x09, 0x64, 0x09, 0x64, 0x09, 0x84, 0x09, 
    0x85, 0x09, 0xA5, 0x09, 0xA5, 0x09, 0xA5, 0x09, 0xA5, 0x09, 0xA5, 0x09, 0xA5, 0x09, 0xA5, 0x09, 
    0xA5, 0x09, 0xA5, 0x09, 0xA6, 0x09, 0x85, 0x09, 0x64, 0x05, 0x44, 0x05, 0x43, 0x05, 0x22, 0x05, 
    0x42, 0x05, 0x83, 0x05, 0x04, 0x02, 0x65, 0x02, 0xE6, 0x02, 0x27, 0x03, 0x47, 0x03, 0x67, 0x03, 
    0x87, 0x03, 0x87, 0x03, 0x87, 0x03, 0x85, 0x03, 0x84, 0x03, 0x86, 0x03, 0xAE, 0x27, 0xD7, 0x57, 
    0x3C, 0x00, 0x44, 0x00, 0xFC, 0x6B, 0xF3, 0x3B, 0xEB, 0x0F, 0xE5, 0x03, 0xE5, 0x03, 0xE8, 0x03, 
    0xE9, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xA7, 0x03, 0x26, 0x03, 0x84, 0x02, 0xC3, 0x01, 0x22, 0x01, 
    0xA1, 0x00, 0x61, 0x00, 0x41, 0x04, 0x82, 0x04, 0xC2, 0x04, 0xE3, 0x08, 0x24, 0x09, 0x45, 0x0D, 
    0x65, 0x0D, 0x66, 0x0D, 0x86, 0x0D, 0x86, 0x0D, 0x85, 0x0D, 0x65, 0x09, 0x65, 0x09, 0x44, 0x09, 
    0x44, 0x09, 0x23, 0x09, 0x23, 0x09, 0x23, 0x09, 0x24, 0x09, 0x24, 0x09, 0x44, 0x09, 0x65, 0x09, 
    0x85, 0x09, 0xA5, 0x09, 0xA5, 0x09, 0xA5, 0x09, 0xA5, 0x09, 0xA5, 0x09, 0xA5, 0x09, 0xA5, 0x09, 
    0xA6, 0x09, 0xA5, 0x09, 0x85, 0x09, 0x64, 0x09, 0x44, 0x09, 0x23, 0x09, 0x23, 0x09, 0x63, 0x05, 
    0xA3, 0x01, 0x04, 0x02, 0x85, 0x02, 0xE6, 0x02, 0x27, 0x03, 0x67, 0x03, 0x87, 0x03, 0x87, 0x03, 
    0x87, 0x03, 0x85, 0x03, 0x84, 0x03, 0x87, 0x03, 0xAF, 0x27, 0xF8, 0x5B, 0x3C, 0x00, 0x44, 0x00, 
    0xFB, 0x6B, 0xF3, 0x3B, 0xEA, 0x0B, 0xE4, 0x03, 0xE5, 0x03, 0xE7, 0x03, 0xE9, 0x03, 0xE9, 0x03, 
    0xE9, 0x03, 0xC8, 0x03, 0x46, 0x03, 0xC5, 0x02, 0x03, 0x02, 0x42, 0x01, 0xC2, 0x00, 0x61, 0x04, 
    0x62, 0x04, 0x82, 0x08, 0xC3, 0x08, 0x04, 0x09, 0x24, 0x09, 0x44, 0x09, 0x65, 0x0D, 0x85, 0x0D, 
    0x86, 0x0D, 0x85, 0x0D, 0x85, 0x0D, 0x65, 0x09, 0x64, 0x09, 0x44, 0x09, 0x23, 0x09, 0x03, 0x09, 
    0xE3, 0x08, 0xE3, 0x08, 0xE3, 0x08, 0xE3, 0x08, 0xE3, 0x04, 0x03, 0x05, 0x44, 0x05, 0x85, 0x09, 
    0xA6, 0x0D, 0xC6, 0x0D, 0xA6, 0x0D, 0x85, 0x0D, 0xA5, 0x0D, 0xA5, 0x09, 0xA5, 0x09, 0xA5, 0x09, 
    0xA5, 0x0D, 0xA5, 0x0D, 0x85, 0x0D, 0x64, 0x09, 0x43, 0x09, 0x63, 0x05, 0x83, 0x01, 0xA3, 0x01, 
    0x24, 0x02, 0x85, 0x02, 0x06, 0x03, 0x67, 0x03, 0x87, 0x03, 0x87, 0x03, 0x87, 0x03, 0xA5, 0x03, 
    0xA4, 0x03, 0xA7, 0x03, 0xCF, 0x27, 0xF8, 0x57, 0x3C, 0x00, 0x45, 0x00, 0xFC, 0x6F, 0xF4, 0x43, 
    0xEC, 0x17, 0xE7, 0x03, 0xE6, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xC8, 0x03, 
    0x67, 0x03, 0x06, 0x03, 0x64, 0x02, 0xA3, 0x01, 0x22, 0x01, 0xA2, 0x04, 0x82, 0x04, 0xA3, 0x08, 
    0xE3, 0x08, 0x04, 0x09, 0x24, 0x09, 0x44, 0x09, 0x64, 0x09, 0x65, 0x09, 0x65, 0x0D, 0x65, 0x0D, 
    0x65, 0x09, 0x64, 0x09, 0x43, 0x05, 0x43, 0x05, 0x23, 0x05, 0x03, 0x05, 0xE3, 0x04, 0xA3, 0x04, 
    0xA2, 0x04, 0x82, 0x04, 0x82, 0x04, 0xC2, 0x04, 0x03, 0x05, 0x45, 0x09, 0xA6, 0x0D, 0xC6, 0x0D, 
    0xA6, 0x0D, 0x86, 0x0D, 0xA6, 0x0D, 0xA5, 0x0D, 0xA5, 0x0D, 0xC5, 0x0D, 0xC6, 0x0D, 0xC6, 0x0D, 
    0xA6, 0x0D, 0x85, 0x09, 0x64, 0x09, 0x63, 0x05, 0x43, 0x01, 0x63, 0x01, 0xA3, 0x01, 0x24, 0x02, 
    0xC6, 0x02, 0x47, 0x03, 0x87, 0x03, 0x87, 0x03, 0xA7, 0x03, 0xA6, 0x03, 0xA5, 0x03, 0xC7, 0x03, 
    0xCE, 0x23, 0xF7, 0x53, 0xFE, 0x7B, 0x3B, 0x00, 0x45, 0x00, 0xFD, 0x73, 0xF8, 0x57, 0xF2, 0x37, 
    0xEE, 0x27, 0xEB, 0x17, 0xEA, 0x0B, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xC8, 0x03, 0xA7, 0x03, 
    0x47, 0x03, 0xC6, 0x02, 0x24, 0x02, 0xA3, 0x01, 0x23, 0x01, 0xC2, 0x04, 0xC3, 0x04, 0xE3, 0x04, 
    0xE3, 0x08, 0xE3, 0x08, 0x03, 0x09, 0x23, 0x09, 0x23, 0x09, 0x24, 0x09, 0x44, 0x09, 0x44, 0x09, 
    0x44, 0x05, 0x43, 0x05, 0x43, 0x05, 0x23, 0x01, 0x02, 0x01, 0xC2, 0x00, 0x82, 0x04, 0x61, 0x04, 
    0x41, 0x04, 0x41, 0x04, 0x81, 0x04, 0xC2, 0x04, 0x24, 0x09, 0x65, 0x09, 0x86, 0x0D, 0xA6, 0x0D, 
    0xA6, 0x11, 0xA6, 0x11, 0xA6, 0x11, 0xC6, 0x0D, 0xC6, 0x0D, 0xC6, 0x11, 0xC6, 0x11, 0xA6, 0x0D, 
    0xA6, 0x09, 0x85, 0x09, 0x64, 0x05, 0x23, 0x05, 0x22, 0x05, 0x63, 0x01, 0xE4, 0x01, 0x85, 0x02, 
    0x06, 0x03, 0x67, 0x03, 0x87, 0x03, 0xA7, 0x03, 0xC6, 0x03, 0xC5, 0x03, 0xC7, 0x03, 0xEE, 0x23, 
    0xF7, 0x53, 0xFE, 0x7B, 0x3B, 0x00, 0x45, 0x00, 0xFE, 0x7B, 0xFC, 0x6B, 0xF9, 0x5F, 0xF6, 0x4F, 
    0xF0, 0x2F, 0xEB, 0x13, 0xE8, 0x03, 0xE7, 0x03, 0xE7, 0x03, 0xE7, 0x03, 0xC7, 0x03, 0x87, 0x03, 
    0x27, 0x03, 0xA5, 0x02, 0x24, 0x02, 0x83, 0x01, 0x22, 0x01, 0xE2, 0x00, 0xC2, 0x04, 0xA2, 0x04, 
    0xA2, 0x04, 0xC2, 0x04, 0xE2, 0x04, 0xE2, 0x04, 0xE2, 0x04, 0x03, 0x05, 0x03, 0x05, 0x03, 0x01, 
    0x23, 0x01, 0x23, 0x01, 0x43, 0x01, 0x22, 0x01, 0xC2, 0x00, 0x81, 0x00, 0x41, 0x00, 0x20, 0x00, 
    0x40, 0x04, 0x61, 0x04, 0xA2, 0x04, 0xE3, 0x04, 0x24, 0x09, 0x65, 0x0D, 0x85, 0x0D, 0xA6, 0x11, 
    0xC6, 0x11, 0xC7, 0x11, 0xC7, 0x11, 0xC7, 0x11, 0xC7, 0x11, 0xC7, 0x0D, 0xA6, 0x0D, 0xA6, 0x09, 
    0x85, 0x09, 0x65, 0x05, 0x44, 0x05, 0x23, 0x05, 0x63, 0x05, 0xC3, 0x01, 0x44, 0x02, 0xE5, 0x02, 
    0x46, 0x03, 0x86, 0x03, 0xC7, 0x03, 0xC6, 0x03, 0xC5, 0x03, 0xC7, 0x03, 0xEE, 0x23, 0xF7, 0x53, 
    0xFE, 0x7B, 0x3E, 0x00, 0x42, 0x00, 0xFC, 0x6F, 0xF5, 0x47, 0xED, 0x1B, 0xE7, 0x03, 0xE5, 0x03, 
    0xE7, 0x03, 0xE7, 0x03, 0xC7, 0x03, 0xC8, 0x03, 0x87, 0x03, 0x06, 0x03, 0xA5, 0x02, 0x24, 0x02, 
    0x83, 0x01, 0x43, 0x01, 0xE2, 0x00, 0xC2, 0x00, 0xC2, 0x04, 0xC2, 0x04, 0xE2, 0x04, 0xE2, 0x04, 
    0x02, 0x01, 0x02, 0x01, 0x23, 0x01, 0x23, 0x01, 0x43, 0x01, 0x83, 0x01, 0x83, 0x01, 0x62, 0x01, 
    0x02, 0x01, 0xA1, 0x00, 0x60, 0x00, 0x20, 0x00, 0x20, 0x04, 0x41, 0x04, 0x81, 0x04, 0xA2, 0x04, 
    0x03, 0x09, 0x44, 0x09, 0x85, 0x0D, 0xC6, 0x11, 0xC7, 0x15, 0xC7, 0x15, 0xC7, 0x15, 0xC7, 0x11, 
    0xC7, 0x11, 0xA7, 0x0D, 0xA6, 0x09, 0xA6, 0x09, 0x86, 0x09, 0x65, 0x09, 0x44, 0x09, 0x23, 0x09, 
    0x43, 0x05, 0xA3, 0x05, 0x24, 0x02, 0xA5, 0x02, 0x26, 0x03, 0x86, 0x03, 0xC7, 0x03, 0xE6, 0x03, 
    0xE4, 0x03, 0xC7, 0x03, 0xEE, 0x23, 0xF6, 0x53, 0xFE, 0x7B, 0x3F, 0x00, 0x41, 0x00, 0xF6, 0x4F, 
    0xED, 0x1F, 0xE6, 0x03, 0xE5, 0x03, 0xE6, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xA8, 0x03, 
    0x67, 0x03, 0x06, 0x03, 0xA5, 0x02, 0x24, 0x02, 0xC4, 0x01, 0x63, 0x01, 0x23, 0x01, 0x22, 0x01, 
    0x42, 0x05, 0x42, 0x05, 0x62, 0x01, 0x63, 0x01, 0x83, 0x01, 0xA4, 0x01, 0xC4, 0x01, 0xE4, 0x01, 
    0x04, 0x02, 0x24, 0x02, 0x03, 0x02, 0xA3, 0x01, 0x22, 0x01, 0xC1, 0x00, 0x60, 0x00, 0x40, 0x00, 
    0x20, 0x04, 0x61, 0x04, 0xA2, 0x04, 0x03, 0x09, 0x44, 0x0D, 0x85, 0x11, 0xC6, 0x11, 0xC7, 0x15, 
    0xC7, 0x15, 0xA7, 0x11, 0xA7, 0x11, 0xA7, 0x11, 0xA7, 0x0D, 0xA6, 0x0D, 0x86, 0x09, 0x65, 0x09, 
    0x44, 0x05, 0x24, 0x05, 0x03, 0x09, 0x43, 0x05, 0x83, 0x05, 0xE4, 0x01, 0x85, 0x02, 0x06, 0x03, 
    0x66, 0x03, 0xC7, 0x03, 0xE6, 0x03, 0xE5, 0x03, 0xC7, 0x03, 0xEE, 0x23, 0xF7, 0x53, 0xFE, 0x7B, 
    0x3E, 0x00, 0x42, 0x00, 0xFE, 0x7B, 0xF6, 0x4B, 0xED, 0x1B, 0xE6, 0x03, 0xE5, 0x03, 0xE7, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xC7, 0x03, 0xA7, 0x03, 0x67, 0x03, 0x46, 0x03, 0x06, 0x03, 0xA5, 0x02, 
    0x45, 0x02, 0x05, 0x02, 0xE4, 0x01, 0xC4, 0x01, 0xC3, 0x01, 0xE3, 0x01, 0x04, 0x02, 0x24, 0x02, 
    0x45, 0x02, 0x45, 0x02, 0x65, 0x02, 0x85, 0x02, 0xA5, 0x02, 0xC5, 0x02, 0x84, 0x02, 0x44, 0x02, 
    0xE3, 0x01, 0x42, 0x01, 0xC1, 0x00, 0x40, 0x00, 0x20, 0x00, 0x41, 0x04, 0xA2, 0x04, 0x24, 0x09, 
    0x65, 0x0D, 0xA5, 0x11, 0xC6, 0x11, 0xC6, 0x11, 0xA6, 0x11, 0xA7, 0x11, 0xA7, 0x11, 0xA7, 0x11, 
    0xC7, 0x11, 0xA6, 0x0D, 0x85, 0x09, 0x44, 0x09, 0x24, 0x05, 0x03, 0x05, 0x03, 0x05, 0x43, 0x05, 
    0x83, 0x01, 0xE4, 0x01, 0x65, 0x02, 0xE6, 0x02, 0x66, 0x03, 0xC7, 0x03, 0xE6, 0x03, 0xE5, 0x03, 
    0xC7, 0x03, 0xEE, 0x23, 0xF7, 0x53, 0xFE, 0x7B, 0x3E, 0x00, 0x42, 0x00, 0xFD, 0x73, 0xF4, 0x47, 
    0xEC, 0x1B, 0xE6, 0x03, 0xE5, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xC8, 0x03, 0xC7, 0x03, 0xA7, 0x03, 
    0x87, 0x03, 0x67, 0x03, 0x47, 0x03, 0x06, 0x03, 0xE6, 0x02, 0xA6, 0x02, 0x85, 0x02, 0x65, 0x02, 
    0x65, 0x02, 0x85, 0x02, 0xA5, 0x02, 0xC6, 0x02, 0xE6, 0x02, 0x06, 0x03, 0x06, 0x03, 0x26, 0x03, 
    0x46, 0x03, 0x46, 0x03, 0x26, 0x03, 0xC5, 0x02, 0x64, 0x06, 0xC3, 0x05, 0x02, 0x01, 0x60, 0x00, 
    0x20, 0x00, 0x41, 0x04, 0xC3, 0x08, 0x45, 0x0D, 0x86, 0x0D, 0xA6, 0x11, 0xC6, 0x11, 0xC6, 0x11, 
    0xA6, 0x11, 0x86, 0x0D, 0x87, 0x0D, 0xA7, 0x11, 0xC7, 0x11, 0xA6, 0x0D, 0x65, 0x0D, 0x24, 0x09, 
    0x03, 0x05, 0x02, 0x05, 0x03, 0x05, 0x43, 0x01, 0x84, 0x01, 0xC4, 0x01, 0x45, 0x02, 0xE6, 0x02, 
    0x46, 0x03, 0xC7, 0x03, 0xE6, 0x03, 0xE5, 0x03, 0xE8, 0x03, 0xEF, 0x23, 0xF7, 0x53, 0xFE, 0x7B, 
    0x3E, 0x00, 0x42, 0x00, 0xFD, 0x77, 0xF5, 0x4B, 0xEC, 0x1B, 0xE6, 0x03, 0xE5, 0x03, 0xE7, 0x03, 
    0xE8, 0x03, 0xC8, 0x03, 0xC7, 0x03, 0xA7, 0x03, 0xA7, 0x03, 0x87, 0x03, 0x87, 0x03, 0x47, 0x03, 
    0x27, 0x03, 0x06, 0x03, 0xE6, 0x02, 0xE6, 0x02, 0xE6, 0x02, 0xE6, 0x02, 0x06, 0x03, 0x27, 0x03, 
    0x47, 0x03, 0x67, 0x03, 0x67, 0x03, 0x67, 0x03, 0xA7, 0x03, 0xA7, 0x03, 0x67, 0x03, 0x06, 0x03, 
    0x85, 0x02, 0xC3, 0x05, 0x02, 0x01, 0x61, 0x00, 0x20, 0x00, 0x62, 0x04, 0xE3, 0x08, 0x65, 0x0D, 
    0xA6, 0x11, 0xC6, 0x11, 0xC6, 0x11, 0xC6, 0x11, 0xA6, 0x11, 0xA7, 0x0D, 0xA7, 0x0D, 0xA7, 0x11, 
    0xA6, 0x11, 0x86, 0x0D, 0x44, 0x09, 0x03, 0x09, 0xE2, 0x04, 0xE2, 0x04, 0x02, 0x05, 0x43, 0x05, 
    0x83, 0x01, 0xC4, 0x01, 0x45, 0x02, 0xC6, 0x02, 0x46, 0x03, 0xC7, 0x03, 0xE6, 0x03, 0xE5, 0x03, 
    0xE8, 0x03, 0xEF, 0x23, 0xF7, 0x53, 0xFE, 0x7B, 0x3F, 0x00, 0x41, 0x00, 0xF6, 0x4F, 0xED, 0x1B, 
    0xE6, 0x03, 0xE5, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xC8, 0x03, 0xC8, 0x03, 0xC8, 0x03, 0xA7, 0x03, 
    0x88, 0x03, 0x87, 0x03, 0x67, 0x03, 0x47, 0x03, 0x26, 0x03, 0x26, 0x03, 0x06, 0x03, 0x06, 0x03, 
    0x27, 0x03, 0x27, 0x03, 0x47, 0x03, 0x47, 0x03, 0x67, 0x03, 0x67, 0x03, 0x87, 0x03, 0xA8, 0x03, 
    0xA8, 0x03, 0x67, 0x03, 0xE6, 0x02, 0x44, 0x02, 0x83, 0x01, 0xE2, 0x00, 0x61, 0x00, 0x41, 0x00, 
    0x82, 0x04, 0x03, 0x09, 0x85, 0x0D, 0xC6, 0x11, 0xC6, 0x11, 0xC6, 0x11, 0xC6, 0x11, 0xC7, 0x11, 
    0xC7, 0x11, 0xA7, 0x0D, 0xA7, 0x11, 0x86, 0x11, 0x65, 0x0D, 0x24, 0x09, 0x03, 0x05, 0xE2, 0x04, 
    0xE2, 0x04, 0x02, 0x05, 0x43, 0x05, 0x63, 0x05, 0xA3, 0x01, 0x24, 0x02, 0xC5, 0x02, 0x46, 0x03, 
    0xC7, 0x03, 0xE6, 0x03, 0xE5, 0x03, 0xE7, 0x03, 0xEE, 0x23, 0xF7, 0x53, 0xFE, 0x7B, 0x3E, 0x00, 
    0x42, 0x00, 0xFE, 0x77, 0xF6, 0x4B, 0xED, 0x1B, 0xE7, 0x03, 0xE6, 0x03, 0xE7, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xC8, 0x03, 0xC8, 0x03, 0xA8, 0x03, 0x88, 0x03, 0x87, 0x03, 0x67, 0x03, 0x46, 0x03, 
    0x46, 0x03, 0x26, 0x03, 0x26, 0x03, 0x27, 0x03, 0x27, 0x03, 0x47, 0x03, 0x47, 0x03, 0x47, 0x03, 
    0x47, 0x03, 0x67, 0x03, 0x67, 0x03, 0x88, 0x03, 0x88, 0x03, 0x27, 0x03, 0x85, 0x02, 0xE3, 0x01, 
    0x22, 0x01, 0xA1, 0x00, 0x61, 0x00, 0x62, 0x04, 0xA3, 0x08, 0x24, 0x09, 0xA5, 0x0D, 0xC5, 0x11, 
    0xC6, 0x11, 0xC6, 0x11, 0xC6, 0x11, 0xE7, 0x11, 0xE7, 0x11, 0xC7, 0x11, 0xA7, 0x11, 0x86, 0x11, 
    0x45, 0x0D, 0x24, 0x09, 0x03, 0x05, 0xE2, 0x04, 0xE2, 0x04, 0x02, 0x05, 0x43, 0x05, 0x83, 0x05, 
    0xC3, 0x01, 0x44, 0x02, 0xC5, 0x02, 0x46, 0x03, 0xC7, 0x03, 0xE6, 0x03, 0xE5, 0x03, 0xE7, 0x03, 
    0xEE, 0x23, 0xF7, 0x53, 0xFE, 0x7B, 0x3C, 0x00, 0x44, 0x00, 0xFE, 0x77, 0xFC, 0x6B, 0xF8, 0x5B, 
    0xF2, 0x3B, 0xEC, 0x17, 0xE7, 0x03, 0xE6, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xC8, 0x03, 0xA8, 0x03, 0xA8, 0x03, 0x88, 0x03, 0x67, 0x03, 0x67, 0x03, 0x66, 0x03, 0x46, 0x03, 
    0x47, 0x03, 0x47, 0x03, 0x47, 0x03, 0x67, 0x03, 0x67, 0x03, 0x67, 0x03, 0x67, 0x03, 0x67, 0x03, 
    0x67, 0x03, 0x67, 0x03, 0x67, 0x03, 0xE6, 0x02, 0x44, 0x02, 0x83, 0x01, 0xE2, 0x00, 0xA1, 0x00, 
    0x82, 0x04, 0xA3, 0x04, 0xE3, 0x08, 0x44, 0x0D, 0xA5, 0x11, 0xC5, 0x11, 0xC6, 0x11, 0xC6, 0x11, 
    0xC7, 0x11, 0xE7, 0x11, 0xE7, 0x11, 0xC7, 0x11, 0xA6, 0x11, 0x66, 0x11, 0x45, 0x0D, 0x04, 0x09, 
    0xE3, 0x04, 0xE2, 0x04, 0xE2, 0x04, 0x03, 0x05, 0x43, 0x05, 0x83, 0x05, 0xE4, 0x01, 0x64, 0x02, 
    0xE5, 0x02, 0x46, 0x03, 0xA7, 0x03, 0xE6, 0x03, 0xE5, 0x03, 0xE7, 0x03, 0xEE, 0x23, 0xF7, 0x53, 
    0xFE, 0x7B, 0x3C, 0x00, 0x44, 0x00, 0xFB, 0x63, 0xF5, 0x47, 0xF1, 0x33, 0xED, 0x1F, 0xEA, 0x0B, 
    0xE8, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xC8, 0x03, 0xC8, 0x03, 
    0xA8, 0x03, 0xA8, 0x03, 0x87, 0x03, 0x87, 0x03, 0x67, 0x03, 0x67, 0x03, 0x67, 0x03, 0x67, 0x03, 
    0x67, 0x03, 0x67, 0x03, 0x67, 0x03, 0x87, 0x03, 0x87, 0x03, 0x87, 0x03, 0x67, 0x03, 0x67, 0x03, 
    0x27, 0x03, 0xA5, 0x02, 0x04, 0x02, 0x42, 0x01, 0xC1, 0x00, 0xA1, 0x04, 0xA2, 0x04, 0xE3, 0x04, 
    0x24, 0x09, 0x64, 0x0D, 0xA5, 0x11, 0xC6, 0x11, 0xC6, 0x11, 0xC6, 0x11, 0xC7, 0x11, 0xC7, 0x11, 
    0xC7, 0x11, 0xC7, 0x11, 0xA6, 0x11, 0x66, 0x11, 0x45, 0x0D, 0x24, 0x09, 0xE3, 0x04, 0xE2, 0x04, 
    0xE2, 0x04, 0xE3, 0x04, 0x43, 0x05, 0xA4, 0x05, 0x04, 0x06, 0x85, 0x02, 0x06, 0x03, 0x66, 0x03, 
    0xA7, 0x03, 0xC6, 0x03, 0xC5, 0x03, 0xC7, 0x03, 0xEE, 0x23, 0xF7, 0x53, 0xFE, 0x7B, 0x3B, 0x00, 
    0x45, 0x00, 0xFE, 0x77, 0xF6, 0x4F, 0xEF, 0x23, 0xE9, 0x0F, 0xE8, 0x0B, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE7, 0x03, 0xC7, 0x03, 0xC7, 0x03, 0xC8, 0x03, 
    0xC8, 0x03, 0xA8, 0x03, 0xA8, 0x03, 0x87, 0x03, 0x67, 0x03, 0x67, 0x03, 0x66, 0x03, 0x67, 0x03, 
    0x67, 0x03, 0x67, 0x03, 0x87, 0x03, 0x87, 0x03, 0x87, 0x03, 0x46, 0x03, 0x26, 0x03, 0xE6, 0x02, 
    0x44, 0x02, 0xA3, 0x01, 0x22, 0x05, 0xC1, 0x04, 0xC2, 0x04, 0xE2, 0x04, 0x23, 0x05, 0x64, 0x09, 
    0x85, 0x0D, 0xA5, 0x11, 0xA6, 0x11, 0xA6, 0x15, 0xA7, 0x11, 0xA7, 0x11, 0xC7, 0x11, 0xC6, 0x11, 
    0xA6, 0x11, 0xA6, 0x11, 0x66, 0x11, 0x45, 0x0D, 0x24, 0x09, 0x03, 0x05, 0xE2, 0x04, 0xE2, 0x00, 
    0xE3, 0x00, 0x44, 0x01, 0xA4, 0x05, 0x25, 0x06, 0xA6, 0x06, 0x26, 0x03, 0x66, 0x03, 0xA7, 0x03, 
    0xC6, 0x03, 0xC5, 0x03, 0xC8, 0x03, 0xCF, 0x23, 0xF7, 0x53, 0xFE, 0x7B, 0x39, 0x00, 0x47, 0x00, 
    0xFE, 0x77, 0xFC, 0x6F, 0xF8, 0x5B, 0xF1, 0x33, 0xEA, 0x07, 0xE5, 0x03, 0xE5, 0x03, 0xE7, 0x03, 
    0xE9, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE7, 0x03, 0xE7, 0x03, 
    0xE8, 0x03, 0xC8, 0x03, 0xC8, 0x03, 0xC8, 0x03, 0xA8, 0x03, 0x87, 0x03, 0x87, 0x03, 0x86, 0x03, 
    0x66, 0x03, 0x87, 0x03, 0x87, 0x03, 0x67, 0x03, 0x47, 0x03, 0x26, 0x03, 0xE5, 0x02, 0xA5, 0x02, 
    0x64, 0x02, 0xE4, 0x01, 0x63, 0x01, 0x02, 0x05, 0xE2, 0x08, 0xE3, 0x08, 0x23, 0x09, 0x64, 0x09, 
    0x85, 0x0D, 0xA5, 0x11, 0xA6, 0x11, 0xA6, 0x11, 0xA7, 0x15, 0xA7, 0x11, 0xA7, 0x11, 0xA6, 0x11, 
    0xA6, 0x11, 0xA6, 0x11, 0x85, 0x11, 0x65, 0x0D, 0x45, 0x0D, 0x24, 0x09, 0x03, 0x05, 0x03, 0x05, 
    0xE3, 0x04, 0x03, 0x01, 0x44, 0x01, 0xC4, 0x01, 0x45, 0x06, 0xE6, 0x06, 0x46, 0x03, 0x66, 0x03, 
    0x87, 0x03, 0xA6, 0x03, 0xA5, 0x03, 0xA7, 0x03, 0xCE, 0x23, 0xF7, 0x53, 0xFE, 0x7B, 0x39, 0x00, 
    0x47, 0x00, 0xFA, 0x63, 0xF6, 0x4B, 0xF1, 0x37, 0xEC, 0x1B, 0xE8, 0x03, 0xE6, 0x03, 0xE6, 0x03, 
    0xE8, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xC8, 0x03, 0xC7, 0x03, 0xC7, 0x03, 
    0xA7, 0x03, 0xA7, 0x03, 0xA7, 0x03, 0x87, 0x03, 0x46, 0x03, 0x06, 0x03, 0xC6, 0x02, 0x65, 0x02, 
    0x04, 0x02, 0xE4, 0x01, 0x83, 0x01, 0x43, 0x05, 0x23, 0x05, 0x23, 0x09, 0x24, 0x09, 0x64, 0x09, 
    0x85, 0x0D, 0xA5, 0x0D, 0xC6, 0x11, 0xC7, 0x11, 0xA7, 0x11, 0x87, 0x11, 0x87, 0x11, 0x86, 0x11, 
    0xA6, 0x11, 0xA6, 0x11, 0xA5, 0x11, 0x65, 0x0D, 0x44, 0x0D, 0x24, 0x09, 0x24, 0x09, 0x24, 0x09, 
    0x24, 0x09, 0x03, 0x05, 0x03, 0x05, 0x43, 0x05, 0xC4, 0x01, 0x65, 0x02, 0x06, 0x03, 0x46, 0x03, 
    0x66, 0x03, 0x87, 0x03, 0xA6, 0x03, 0xA4, 0x03, 0xA7, 0x03, 0xCE, 0x23, 0xF7, 0x53, 0xFE, 0x7B, 
    0x38, 0x00, 0x48, 0x00, 0xFE, 0x73, 0xF6, 0x4B, 0xEF, 0x23, 0xE9, 0x13, 0xE8, 0x0B, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xC7, 0x03, 0xE7, 0x03, 0xC7, 0x03, 0xA7, 0x03, 0xA7, 0x03, 0x66, 0x03, 0x06, 0x03, 0xA6, 0x02, 
    0x45, 0x02, 0xC4, 0x01, 0x83, 0x01, 0x63, 0x01, 0x43, 0x05, 0x43, 0x05, 0x44, 0x05, 0x65, 0x09, 
    0x65, 0x0D, 0x85, 0x0D, 0xA5, 0x11, 0xC6, 0x11, 0xC7, 0x11, 0xC7, 0x11, 0xA7, 0x11, 0x87, 0x11, 
    0x66, 0x11, 0x86, 0x15, 0xA6, 0x15, 0xA6, 0x11, 0x85, 0x11, 0x64, 0x0D, 0x24, 0x09, 0x23, 0x09, 
    0x24, 0x09, 0x44, 0x09, 0x44, 0x09, 0x23, 0x09, 0x23, 0x05, 0x63, 0x05, 0xE4, 0x01, 0x85, 0x02, 
    0x06, 0x03, 0x66, 0x03, 0x66, 0x03, 0x87, 0x03, 0xA5, 0x03, 0xA4, 0x03, 0xA7, 0x03, 0xCE, 0x23, 
    0xF6, 0x53, 0xFE, 0x7B, 0x36, 0x00, 0x4A, 0x00, 0xFE, 0x77, 0xFD, 0x73, 0xF8, 0x5B, 0xF0, 0x2F, 
    0xE9, 0x07, 0xE5, 0x03, 0xE5, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xC8, 0x03, 0xC8, 0x03, 0xA7, 0x03, 0xA7, 0x03, 0xA7, 0x03, 0xA7, 0x03, 0xA7, 0x03, 0x86, 0x03, 
    0x46, 0x03, 0x06, 0x03, 0x85, 0x02, 0x25, 0x02, 0xC4, 0x01, 0x64, 0x01, 0x23, 0x01, 0x23, 0x05, 
    0x23, 0x05, 0x44, 0x05, 0x65, 0x09, 0xA6, 0x0D, 0xA6, 0x0D, 0xA6, 0x11, 0xC6, 0x11, 0xC7, 0x11, 
    0xE7, 0x11, 0xE8, 0x11, 0xC8, 0x11, 0x87, 0x11, 0x87, 0x15, 0x86, 0x15, 0x86, 0x11, 0xA6, 0x11, 
    0x85, 0x11, 0x44, 0x0D, 0x23, 0x09, 0x03, 0x05, 0x23, 0x09, 0x44, 0x09, 0x44, 0x09, 0x43, 0x09, 
    0x63, 0x05, 0xA3, 0x05, 0x24, 0x02, 0xA5, 0x02, 0x26, 0x03, 0x66, 0x03, 0x86, 0x03, 0x87, 0x03, 
    0xA5, 0x03, 0xA4, 0x03, 0xA6, 0x03, 0xCE, 0x23, 0xF6, 0x53, 0xFE, 0x7B, 0x35, 0x00, 0x4B, 0x00, 
    0xFD, 0x73, 0xF9, 0x5F, 0xF6, 0x4B, 0xF1, 0x37, 0xEC, 0x1B, 0xE8, 0x03, 0xE5, 0x03, 0xE6, 0x03, 
    0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xC8, 0x03, 0xA8, 0x03, 0x87, 0x03, 0x67, 0x03, 
    0x46, 0x03, 0x46, 0x03, 0x66, 0x03, 0x66, 0x03, 0x26, 0x03, 0xE5, 0x02, 0x85, 0x02, 0x04, 0x02, 
    0xC4, 0x01, 0x84, 0x01, 0x43, 0x05, 0x23, 0x05, 0x23, 0x05, 0x23, 0x05, 0x44, 0x09, 0x85, 0x0D, 
    0xA6, 0x0D, 0xC7, 0x11, 0xC6, 0x11, 0xC6, 0x11, 0xC7, 0x15, 0xE7, 0x15, 0xE8, 0x15, 0xC8, 0x15, 
    0xA8, 0x15, 0x87, 0x15, 0x86, 0x15, 0x86, 0x11, 0x85, 0x11, 0x65, 0x0D, 0x44, 0x09, 0x24, 0x09, 
    0x03, 0x09, 0x03, 0x09, 0x03, 0x09, 0x43, 0x05, 0x63, 0x05, 0xA3, 0x05, 0x04, 0x02, 0x65, 0x02, 
    0xE6, 0x02, 0x47, 0x03, 0x67, 0x03, 0x87, 0x03, 0x87, 0x03, 0xA5, 0x03, 0xA4, 0x03, 0xA7, 0x03, 
    0xCE, 0x23, 0xF7, 0x53, 0xFE, 0x7B, 0x35, 0x00, 0x4B, 0x00, 0xFB, 0x67, 0xF5, 0x43, 0xEE, 0x23, 
    0xEA, 0x13, 0xE9, 0x0B, 0xE8, 0x03, 0xE7, 0x03, 0xE7, 0x03, 0xE7, 0x03, 0xE7, 0x03, 0xE7, 0x03, 
    0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xC7, 0x03, 0xA8, 0x03, 0x67, 0x03, 0x27, 0x03, 0x06, 0x03, 0xE5, 0x02, 0xE5, 0x02, 0x05, 0x03, 
    0x05, 0x03, 0xC5, 0x02, 0x65, 0x02, 0x04, 0x06, 0xA4, 0x05, 0x64, 0x05, 0x63, 0x05, 0x43, 0x05, 
    0x23, 0x05, 0x23, 0x05, 0x44, 0x09, 0x65, 0x0D, 0xA6, 0x0D, 0xC7, 0x11, 0xC7, 0x11, 0xC6, 0x11, 
    0xC6, 0x11, 0xC7, 0x15, 0xC8, 0x15, 0xC8, 0x15, 0xC8, 0x15, 0xC8, 0x15, 0xC7, 0x15, 0xA7, 0x11, 
    0x86, 0x11, 0x85, 0x0D, 0x64, 0x0D, 0x44, 0x09, 0x24, 0x09, 0x04, 0x09, 0xE3, 0x04, 0xE3, 0x04, 
    0x23, 0x05, 0x83, 0x01, 0xE3, 0x01, 0x64, 0x02, 0xC5, 0x02, 0x06, 0x03, 0x47, 0x03, 0x67, 0x03, 
    0x87, 0x03, 0x87, 0x03, 0x86, 0x03, 0xA5, 0x03, 0xA7, 0x03, 0xCE, 0x23, 0xF7, 0x53, 0xFE, 0x7B, 
    0x35, 0x00, 0x4B, 0x00, 0xFA, 0x5F, 0xF1, 0x33, 0xE9, 0x03, 0xE5, 0x03, 0xE6, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE7, 0x03, 0xE7, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xC7, 0x03, 0xA7, 0x03, 0x67, 0x03, 0x27, 0x03, 0xE6, 0x02, 
    0x86, 0x02, 0x65, 0x02, 0x44, 0x02, 0x44, 0x02, 0x64, 0x02, 0x65, 0x02, 0x24, 0x02, 0xE4, 0x05, 
    0x84, 0x05, 0x43, 0x05, 0x23, 0x05, 0x23, 0x05, 0x23, 0x05, 0x23, 0x05, 0x44, 0x09, 0x64, 0x09, 
    0x85, 0x0D, 0xA6, 0x11, 0xC7, 0x15, 0xC7, 0x15, 0xC7, 0x11, 0xC7, 0x11, 0xC7, 0x11, 0xC7, 0x15, 
    0xC8, 0x15, 0xC8, 0x15, 0xC8, 0x15, 0xC7, 0x15, 0xA7, 0x11, 0x86, 0x11, 0x65, 0x0D, 0x44, 0x09, 
    0x24, 0x09, 0x24, 0x09, 0x03, 0x09, 0xE3, 0x04, 0xE2, 0x04, 0x42, 0x01, 0xA3, 0x01, 0x24, 0x02, 
    0xA5, 0x02, 0x06, 0x03, 0x27, 0x03, 0x67, 0x03, 0x67, 0x03, 0x87, 0x03, 0x87, 0x03, 0x86, 0x03, 
    0xA5, 0x03, 0xA7, 0x03, 0xCE, 0x23, 0xF7, 0x53, 0xFE, 0x7B, 0x35, 0x00, 0x4B, 0x00, 0xFA, 0x5F, 
    0xF1, 0x2F, 0xE8, 0x03, 0xE4, 0x03, 0xE5, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xC8, 0x03, 0xC8, 0x03, 
    0xA7, 0x03, 0x46, 0x03, 0xE6, 0x02, 0xA6, 0x02, 0x45, 0x02, 0xE5, 0x01, 0xC4, 0x01, 0xC4, 0x01, 
    0xA4, 0x01, 0xC4, 0x01, 0xC4, 0x01, 0xA4, 0x05, 0x63, 0x05, 0x43, 0x05, 0x03, 0x09, 0x03, 0x09, 
    0x03, 0x09, 0x24, 0x09, 0x44, 0x09, 0x65, 0x09, 0x85, 0x0D, 0xA6, 0x0D, 0xC7, 0x11, 0xC7, 0x11, 
    0xC7, 0x11, 0xE7, 0x11, 0xC7, 0x11, 0xC7, 0x11, 0xC7, 0x15, 0xC7, 0x15, 0xC7, 0x15, 0xC7, 0x15, 
    0xC7, 0x11, 0xA7, 0x11, 0xA6, 0x11, 0x85, 0x0D, 0x45, 0x0D, 0x24, 0x09, 0x04, 0x09, 0x03, 0x05, 
    0xE2, 0x04, 0x02, 0x01, 0x62, 0x01, 0xE3, 0x01, 0x65, 0x02, 0xE6, 0x02, 0x26, 0x03, 0x47, 0x03, 
    0x67, 0x03, 0x67, 0x03, 0x87, 0x03, 0x87, 0x03, 0xA6, 0x03, 0xA5, 0x03, 0xA7, 0x03, 0xCE, 0x23, 
    0xF7, 0x53, 0xFE, 0x7B, 0x35, 0x00, 0x4B, 0x00, 0xFA, 0x63, 0xF2, 0x33, 0xEA, 0x07, 0xE6, 0x03, 
    0xE6, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xA8, 0x03, 0x87, 0x03, 0x47, 0x03, 0xE6, 0x02, 0x65, 0x02, 
    0x05, 0x02, 0xA4, 0x01, 0x64, 0x01, 0x44, 0x05, 0x44, 0x05, 0x43, 0x05, 0x43, 0x05, 0x43, 0x05, 
    0x43, 0x05, 0x43, 0x05, 0x23, 0x09, 0x03, 0x09, 0x03, 0x09, 0x03, 0x09, 0x24, 0x09, 0x45, 0x09, 
    0x65, 0x09, 0x86, 0x0D, 0xA7, 0x0D, 0xC7, 0x11, 0xC8, 0x11, 0xC8, 0x11, 0xE8, 0x11, 0xC8, 0x11, 
    0xC7, 0x11, 0xC7, 0x11, 0xA6, 0x11, 0xA6, 0x11, 0xA7, 0x11, 0xA7, 0x11, 0xA7, 0x11, 0x86, 0x11, 
    0x86, 0x0D, 0x65, 0x0D, 0x24, 0x09, 0x03, 0x09, 0x03, 0x05, 0x02, 0x01, 0x22, 0x01, 0x83, 0x01, 
    0x04, 0x02, 0x85, 0x02, 0x06, 0x03, 0x46, 0x03, 0x46, 0x03, 0x46, 0x03, 0x66, 0x03, 0x86, 0x03, 
    0xA7, 0x03, 0xA5, 0x03, 0xA4, 0x03, 0xA7, 0x03, 0xCE, 0x23, 0xF6, 0x53, 0xFE, 0x7B, 0x35, 0x00, 
    0x4B, 0x00, 0xFA, 0x63, 0xF2, 0x37, 0xEA, 0x0B, 0xE6, 0x03, 0xE6, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xC8, 0x03, 0xA8, 0x03, 0x67, 0x03, 
    0x27, 0x03, 0xE6, 0x02, 0xA6, 0x02, 0x45, 0x02, 0xC4, 0x01, 0x64, 0x01, 0x23, 0x01, 0xE3, 0x04, 
    0xE3, 0x04, 0xE3, 0x08, 0xE3, 0x08, 0x03, 0x09, 0x03, 0x09, 0x03, 0x09, 0x23, 0x09, 0x23, 0x09, 
    0x23, 0x09, 0x03, 0x09, 0x04, 0x09, 0x04, 0x09, 0x25, 0x0D, 0x66, 0x0D, 0x86, 0x0D, 0xA7, 0x0D, 
    0xC7, 0x11, 0xC7, 0x11, 0xC8, 0x11, 0xC7, 0x11, 0xC7, 0x11, 0xA7, 0x11, 0xA6, 0x11, 0xA6, 0x0D, 
    0x86, 0x0D, 0x86, 0x0D, 0x86, 0x0D, 0x86, 0x0D, 0x86, 0x0D, 0x86, 0x0D, 0x45, 0x0D, 0x24, 0x09, 
    0x03, 0x05, 0x02, 0x05, 0x22, 0x01, 0x63, 0x01, 0xE3, 0x01, 0x45, 0x02, 0xC6, 0x02, 0x27, 0x03, 
    0x47, 0x03, 0x46, 0x03, 0x46, 0x03, 0x66, 0x03, 0x86, 0x03, 0xA7, 0x03, 0xA5, 0x03, 0xA4, 0x03, 
    0xC7, 0x03, 0xCE, 0x23, 0xF6, 0x53, 0xFE, 0x7B, 0x35, 0x00, 0x4B, 0x00, 0xFA, 0x63, 0xF2, 0x37, 
    0xEA, 0x0B, 0xE6, 0x03, 0xE6, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xC8, 0x03, 0x87, 0x03, 0x47, 0x03, 0xE6, 0x02, 0x85, 0x02, 0x45, 0x02, 0x04, 0x02, 
    0xC4, 0x01, 0x63, 0x01, 0x23, 0x05, 0x03, 0x05, 0xE3, 0x04, 0xE3, 0x08, 0xE3, 0x08, 0x03, 0x09, 
    0x03, 0x09, 0x03, 0x09, 0x04, 0x09, 0x24, 0x09, 0x44, 0x0D, 0x24, 0x0D, 0x04, 0x0D, 0xE3, 0x08, 
    0xE3, 0x08, 0x04, 0x09, 0x45, 0x09, 0x66, 0x0D, 0xA6, 0x11, 0xA7, 0x11, 0xC7, 0x11, 0xA7, 0x11, 
    0xA6, 0x11, 0x86, 0x0D, 0x86, 0x0D, 0x86, 0x0D, 0x86, 0x0D, 0x86, 0x0D, 0x86, 0x0D, 0x86, 0x0D, 
    0x66, 0x0D, 0x65, 0x0D, 0x45, 0x0D, 0x24, 0x09, 0x03, 0x09, 0x03, 0x05, 0x22, 0x05, 0x63, 0x01, 
    0xC3, 0x01, 0x24, 0x02, 0x85, 0x02, 0xE6, 0x02, 0x27, 0x03, 0x47, 0x03, 0x46, 0x03, 0x66, 0x03, 
    0x67, 0x03, 0x87, 0x03, 0xA7, 0x03, 0xA6, 0x03, 0xC4, 0x03, 0xC7, 0x03, 0xCE, 0x23, 0xF7, 0x53, 
    0xFE, 0x7B, 0x35, 0x00, 0x4B, 0x00, 0xFA, 0x63, 0xF1, 0x37, 0xEA, 0x0B, 0xE5, 0x03, 0xE6, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE7, 0x03, 0xC7, 0x03, 0xA7, 0x03, 0x26, 0x03, 
    0xC5, 0x02, 0x65, 0x02, 0xE4, 0x01, 0x83, 0x01, 0x63, 0x01, 0x43, 0x01, 0x23, 0x05, 0x03, 0x05, 
    0x03, 0x09, 0x03, 0x09, 0x23, 0x09, 0x23, 0x09, 0x24, 0x09, 0x24, 0x09, 0x44, 0x09, 0x44, 0x09, 
    0x65, 0x0D, 0x65, 0x0D, 0x65, 0x0D, 0x24, 0x0D, 0xE3, 0x08, 0xC3, 0x08, 0xE3, 0x08, 0x04, 0x09, 
    0x45, 0x0D, 0x86, 0x11, 0xA6, 0x11, 0xA6, 0x15, 0x86, 0x11, 0x65, 0x0D, 0x45, 0x0D, 0x45, 0x0D, 
    0x65, 0x0D, 0x86, 0x11, 0x86, 0x11, 0x86, 0x0D, 0x86, 0x0D, 0x65, 0x0D, 0x45, 0x09, 0x24, 0x09, 
    0x03, 0x09, 0x03, 0x09, 0x02, 0x05, 0x63, 0x05, 0xA3, 0x01, 0x24, 0x02, 0x85, 0x02, 0xC5, 0x02, 
    0xE6, 0x02, 0x26, 0x03, 0x47, 0x03, 0x47, 0x03, 0x67, 0x03, 0x87, 0x03, 0x87, 0x03, 0xA7, 0x03, 
    0xA6, 0x03, 0xC5, 0x03, 0xC7, 0x03, 0xEE, 0x23, 0xF7, 0x53, 0xFE, 0x7B, 0x35, 0x00, 0x4B, 0x00, 
    0xFA, 0x63, 0xF1, 0x37, 0xE9, 0x0B, 0xE5, 0x03, 0xE6, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xC7, 0x03, 0x87, 0x03, 0x46, 0x03, 0xA5, 0x02, 0x24, 0x02, 0xC3, 0x05, 0x42, 0x05, 
    0x02, 0x05, 0xE2, 0x00, 0xE2, 0x00, 0xC2, 0x04, 0xE2, 0x08, 0x03, 0x09, 0x03, 0x09, 0x23, 0x09, 
    0x43, 0x09, 0x44, 0x09, 0x64, 0x09, 0x64, 0x09, 0x85, 0x09, 0xA6, 0x0D, 0xA6, 0x11, 0x86, 0x0D, 
    0x24, 0x0D, 0xE3, 0x08, 0xC2, 0x04, 0xC3, 0x04, 0xE3, 0x08, 0x24, 0x0D, 0x65, 0x0D, 0x86, 0x11, 
    0xA6, 0x11, 0x85, 0x11, 0x44, 0x0D, 0x24, 0x09, 0x24, 0x09, 0x45, 0x0D, 0x65, 0x0D, 0x66, 0x0D, 
    0x65, 0x0D, 0x65, 0x0D, 0x44, 0x09, 0x24, 0x09, 0x03, 0x05, 0x02, 0x05, 0x22, 0x05, 0x42, 0x05, 
    0xA3, 0x05, 0x04, 0x02, 0x65, 0x02, 0xC5, 0x02, 0xE5, 0x02, 0x05, 0x03, 0x26, 0x03, 0x46, 0x03, 
    0x47, 0x03, 0x67, 0x03, 0x87, 0x03, 0x87, 0x03, 0xA7, 0x03, 0xA6, 0x03, 0xC5, 0x03, 0xC8, 0x03, 
    0xEF, 0x23, 0xF7, 0x53, 0xFE, 0x7B, 0x35, 0x00, 0x4B, 0x00, 0xFA, 0x63, 0xF1, 0x37, 0xEA, 0x0B, 
    0xE6, 0x03, 0xE6, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xA7, 0x03, 0x46, 0x03, 
    0xC5, 0x02, 0x24, 0x02, 0xA3, 0x01, 0x42, 0x05, 0xE2, 0x04, 0xA2, 0x04, 0xA2, 0x04, 0xA2, 0x04, 
    0xA2, 0x04, 0xA2, 0x04, 0xC2, 0x04, 0xC2, 0x04, 0xE3, 0x04, 0x03, 0x05, 0x44, 0x09, 0x65, 0x09, 
    0x85, 0x0D, 0xA6, 0x0D, 0xA6, 0x11, 0xA7, 0x11, 0x86, 0x11, 0x45, 0x0D, 0x04, 0x09, 0xE3, 0x08, 
    0xC3, 0x08, 0xE4, 0x08, 0x04, 0x09, 0x45, 0x0D, 0x85, 0x11, 0x85, 0x11, 0x85, 0x0D, 0x44, 0x09, 
    0x24, 0x09, 0x24, 0x09, 0x44, 0x09, 0x45, 0x0D, 0x45, 0x0D, 0x44, 0x0D, 0x24, 0x0D, 0x23, 0x09, 
    0x03, 0x05, 0x03, 0x05, 0x22, 0x01, 0x62, 0x01, 0xA3, 0x05, 0x04, 0x02, 0x65, 0x02, 0xA5, 0x02, 
    0x06, 0x03, 0x06, 0x03, 0x05, 0x03, 0x26, 0x03, 0x26, 0x03, 0x47, 0x03, 0x67, 0x03, 0x87, 0x03, 
    0x87, 0x03, 0xA7, 0x03, 0xC5, 0x03, 0xC4, 0x03, 0xC6, 0x03, 0xED, 0x1F, 0xF6, 0x4F, 0xFE, 0x7B, 
    0x35, 0x00, 0x4B, 0x00, 0xFA, 0x63, 0xF2, 0x37, 0xEA, 0x0B, 0xE6, 0x03, 0xE6, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0x87, 0x03, 0x06, 0x03, 0x65, 0x02, 0xC3, 0x01, 0x42, 0x01, 
    0x02, 0x05, 0xC2, 0x08, 0xA2, 0x08, 0xA2, 0x04, 0x82, 0x04, 0x82, 0x04, 0x61, 0x04, 0x81, 0x04, 
    0x81, 0x00, 0xA2, 0x04, 0xC3, 0x04, 0x04, 0x09, 0x45, 0x0D, 0x86, 0x0D, 0xA6, 0x11, 0xC6, 0x11, 
    0xA6, 0x11, 0x86, 0x0D, 0x65, 0x0D, 0x25, 0x09, 0x04, 0x09, 0xE4, 0x08, 0xE4, 0x08, 0x04, 0x09, 
    0x45, 0x0D, 0x65, 0x0D, 0x85, 0x0D, 0x85, 0x0D, 0x64, 0x09, 0x44, 0x09, 0x44, 0x09, 0x44, 0x09, 
    0x24, 0x09, 0x23, 0x09, 0x03, 0x09, 0x03, 0x09, 0x02, 0x09, 0x02, 0x05, 0x22, 0x01, 0x63, 0x01, 
    0xC3, 0x01, 0x04, 0x02, 0x64, 0x02, 0xA5, 0x02, 0xC6, 0x02, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
    0x26, 0x03, 0x26, 0x03, 0x46, 0x03, 0x66, 0x03, 0x87, 0x03, 0xA7, 0x03, 0xA7, 0x03, 0xC5, 0x03, 
    0xC2, 0x03, 0xC4, 0x03, 0xEC, 0x1B, 0xF6, 0x4B, 0xFE, 0x7B, 0x35, 0x00, 0x4B, 0x00, 0xFA, 0x63, 
    0xF2, 0x37, 0xEA, 0x0B, 0xE6, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xE8, 0x03, 
    0x67, 0x03, 0xC6, 0x02, 0x04, 0x02, 0x62, 0x01, 0x02, 0x01, 0xC2, 0x04, 0xA2, 0x08, 0x82, 0x08, 
    0xA2, 0x08, 0x82, 0x04, 0x61, 0x04, 0x40, 0x00, 0x40, 0x00, 0x41, 0x00, 0x62, 0x00, 0xA3, 0x04, 
    0xE4, 0x08, 0x25, 0x0D, 0x66, 0x11, 0xA6, 0x11, 0xA6, 0x11, 0xA6, 0x11, 0x86, 0x11, 0x66, 0x0D, 
    0x45, 0x0D, 0x25, 0x09, 0x05, 0x09, 0x04, 0x09, 0x04, 0x09, 0x24, 0x09, 0x45, 0x09, 0x65, 0x0D, 
    0x64, 0x09, 0x64, 0x09, 0x44, 0x09, 0x43, 0x05, 0x43, 0x05, 0x23, 0x05, 0x03, 0x05, 0x02, 0x05, 
    0xE2, 0x04, 0x02, 0x05, 0x22, 0x05, 0x63, 0x01, 0xC3, 0x01, 0x24, 0x02, 0x64, 0x02, 0xA5, 0x02, 
    0xC6, 0x02, 0xE6, 0x02, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x26, 0x03, 0x46, 0x03, 
    0x66, 0x03, 0x86, 0x03, 0xA7, 0x03, 0xC7, 0x03, 0xC5, 0x03, 0xC4, 0x03, 0xC6, 0x03, 0xEE, 0x23, 
    0xF6, 0x4F, 0xFE, 0x7B, 0x35, 0x00, 0x4B, 0x00, 0xFA, 0x63, 0xF2, 0x37, 0xEA, 0x0B, 0xE6, 0x03, 
    0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0x47, 0x03, 0x85, 0x02, 0xC3, 0x01, 
    0x02, 0x01, 0xA1, 0x00, 0x81, 0x04, 0x61, 0x04, 0x61, 0x08, 0x62, 0x04, 0x62, 0x04, 0x41, 0x04, 
    0x20, 0x00, 0x00, 0x00, 0x21, 0x00, 0x62, 0x04, 0xA3, 0x04, 0xE4, 0x08, 0x25, 0x0D, 0x45, 0x0D, 
    0x86, 0x11, 0xA6, 0x11, 0xA6, 0x11, 0xA6, 0x11, 0x86, 0x11, 0x66, 0x0D, 0x45, 0x0D, 0x25, 0x09, 
    0x04, 0x09, 0x04, 0x09, 0x24, 0x09, 0x24, 0x09, 0x44, 0x09, 0x44, 0x09, 0x44, 0x09, 0x23, 0x05, 
    0x23, 0x05, 0x23, 0x05, 0x22, 0x05, 0x22, 0x05, 0x22, 0x05, 0x43, 0x05, 0x63, 0x05, 0x83, 0x01, 
    0xC3, 0x01, 0x24, 0x02, 0x64, 0x02, 0xA5, 0x02, 0xE6, 0x02, 0xE6, 0x02, 0xE6, 0x02, 0xE6, 0x02, 
    0x06, 0x03, 0x06, 0x03, 0x05, 0x03, 0x25, 0x03, 0x45, 0x03, 0x65, 0x03, 0x85, 0x03, 0x85, 0x03, 
    0xA6, 0x03, 0xC7, 0x07, 0xC9, 0x17, 0xED, 0x23, 0xF3, 0x3F, 0xF9, 0x5F, 0xFF, 0x7B, 0x35, 0x00, 
    0x4A, 0x00, 0xFA, 0x63, 0xF2, 0x37, 0xEA, 0x0B, 0xE6, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xE8, 0x03, 0xC8, 0x03, 0x46, 0x03, 0x65, 0x02, 0xA3, 0x01, 0xE1, 0x00, 0x81, 0x00, 0x60, 0x04, 
    0x40, 0x04, 0x21, 0x04, 0x41, 0x04, 0x41, 0x04, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x04, 
    0x82, 0x04, 0xC4, 0x08, 0x04, 0x0D, 0x04, 0x0D, 0x24, 0x0D, 0x65, 0x0D, 0x85, 0x11, 0xA6, 0x11, 
    0xA6, 0x11, 0xA6, 0x11, 0x86, 0x11, 0x45, 0x0D, 0x25, 0x09, 0x24, 0x09, 0x04, 0x09, 0x04, 0x09, 
    0x24, 0x09, 0x24, 0x09, 0x04, 0x09, 0x03, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x22, 0x05, 
    0x43, 0x05, 0x63, 0x05, 0xA4, 0x01, 0xE4, 0x01, 0x04, 0x02, 0x44, 0x02, 0x84, 0x02, 0xA5, 0x02, 
    0xC6, 0x02, 0xE6, 0x02, 0xE6, 0x02, 0xE6, 0x02, 0xE6, 0x02, 0xE6, 0x02, 0x06, 0x03, 0x05, 0x03, 
    0x25, 0x03, 0x24, 0x03, 0x44, 0x03, 0x63, 0x03, 0x82, 0x03, 0xA4, 0x03, 0xC9, 0x13, 0xCF, 0x33, 
    0xF6, 0x4F, 0xF9, 0x5F, 0xFC, 0x6F, 0x36, 0x00, 0x49, 0x00, 0xFA, 0x63, 0xF2, 0x37, 0xEA, 0x0B, 
    0xE6, 0x03, 0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xC7, 0x03, 0x46, 0x03, 0x65, 0x02, 
    0xA3, 0x01, 0xE2, 0x00, 0x81, 0x00, 0x61, 0x04, 0x40, 0x04, 0x40, 0x04, 0x60, 0x00, 0x61, 0x00, 
    0x21, 0x00, 0x00, 0x00, 0x01, 0x04, 0x42, 0x04, 0xA3, 0x08, 0xE4, 0x0C, 0x04, 0x0D, 0x04, 0x09, 
    0x04, 0x09, 0x24, 0x0D, 0x65, 0x11, 0x86, 0x11, 0xA6, 0x15, 0x86, 0x11, 0x65, 0x0D, 0x45, 0x0D, 
    0x24, 0x09, 0x04, 0x09, 0x03, 0x09, 0x04, 0x09, 0x04, 0x09, 0x04, 0x09, 0x03, 0x09, 0xE3, 0x04, 
    0xE2, 0x04, 0x02, 0x05, 0x22, 0x05, 0x62, 0x05, 0xA3, 0x05, 0xC4, 0x01, 0x05, 0x02, 0x45, 0x02, 
    0x65, 0x02, 0x85, 0x02, 0xA5, 0x02, 0xC5, 0x02, 0xC6, 0x02, 0xC6, 0x02, 0xC6, 0x02, 0xC5, 0x02, 
    0xE5, 0x02, 0xE5, 0x02, 0xE5, 0x02, 0x06, 0x03, 0x26, 0x03, 0x46, 0x03, 0x66, 0x03, 0x65, 0x03, 
    0x83, 0x03, 0xA6, 0x03, 0xCE, 0x27, 0xF6, 0x53, 0xFE, 0x77, 0xFF, 0x7B, 0x37, 0x00, 0x47, 0x00, 
    0xFA, 0x63, 0xF1, 0x33, 0xEA, 0x07, 0xE5, 0x03, 0xE6, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xE8, 0x03, 
    0xC8, 0x03, 0x46, 0x03, 0xA5, 0x02, 0x04, 0x02, 0x43, 0x01, 0x02, 0x01, 0xE1, 0x00, 0xA1, 0x00, 
    0xA1, 0x00, 0xA1, 0x00, 0xA1, 0x00, 0x61, 0x00, 0x21, 0x00, 0x21, 0x04, 0x42, 0x04, 0x83, 0x08, 
    0xC4, 0x08, 0x04, 0x09, 0x03, 0x09, 0x03, 0x09, 0x24, 0x09, 0x44, 0x0D, 0x65, 0x11, 0x65, 0x11, 
    0x65, 0x0D, 0x44, 0x0D, 0x24, 0x09, 0x03, 0x09, 0xE3, 0x08, 0xE3, 0x08, 0xE3, 0x08, 0x03, 0x09, 
    0x03, 0x05, 0x23, 0x05, 0x23, 0x05, 0x43, 0x01, 0x63, 0x01, 0x83, 0x01, 0xC3, 0x01, 0x04, 0x02, 
    0x25, 0x02, 0x65, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0xC5, 0x02, 0xC5, 0x02, 0xC5, 0x02, 0xC6, 0x02, 
    0xC6, 0x02, 0xC6, 0x02, 0xC5, 0x02, 0xC5, 0x02, 0xC4, 0x02, 0xE4, 0x02, 0x05, 0x03, 0x28, 0x0B, 
    0x4B, 0x17, 0x8D, 0x1F, 0x8C, 0x1F, 0xAA, 0x1F, 0xAD, 0x23, 0xD4, 0x43, 0xFB, 0x6B, 0x39, 0x00, 
    0x47, 0x00, 0xF9, 0x5F, 0xF1, 0x2F, 0xE8, 0x03, 0xE4, 0x03, 0xE5, 0x03, 0xE8, 0x03, 0xE9, 0x03, 
    0xE8, 0x03, 0xE8, 0x03, 0x87, 0x03, 0xE6, 0x02, 0x65, 0x02, 0xC4, 0x01, 0x83, 0x01, 0x63, 0x01, 
    0x42, 0x01, 0x22, 0x01, 0x02, 0x01, 0xE2, 0x00, 0xA1, 0x00, 0x61, 0x00, 0x21, 0x00, 0x42, 0x04, 
    0x62, 0x04, 0xA3, 0x04, 0xE3, 0x08, 0x03, 0x09, 0x23, 0x09, 0x24, 0x09, 0x45, 0x0D, 0x45, 0x0D, 
    0x25, 0x0D, 0x24, 0x09, 0x03, 0x09, 0xE3, 0x08, 0xC3, 0x08, 0xC3, 0x08, 0xC3, 0x04, 0xE2, 0x04, 
    0x03, 0x05, 0x23, 0x05, 0x43, 0x01, 0x83, 0x01, 0xA4, 0x01, 0xE4, 0x01, 0x04, 0x02, 0x24, 0x02, 
    0x44, 0x02, 0x65, 0x02, 0x85, 0x02, 0xA5, 0x02, 0xC5, 0x02, 0xC5, 0x02, 0xC5, 0x02, 0xC5, 0x02, 
    0xC5, 0x02, 0xC5, 0x02, 0xC6, 0x02, 0xC6, 0x02, 0xC5, 0x02, 0xC3, 0x02, 0xC2, 0x02, 0xE5, 0x02, 
    0x2B, 0x17, 0x91, 0x37, 0xD6, 0x4B, 0xD5, 0x4B, 0xD4, 0x4B, 0xD5, 0x4F, 0xF9, 0x5F, 0xFE, 0x77, 
    0x39, 0x00, 0x46, 0x00, 0xFA, 0x5F, 0xF1, 0x33, 0xE9, 0x03, 0xE5, 0x03, 0xE6, 0x03, 0xE8, 0x03, 
    0xE9, 0x03, 0xE9, 0x03, 0xE8, 0x03, 0xA8, 0x03, 0x47, 0x03, 0xE6, 0x02, 0x65, 0x02, 0x25, 0x02, 
    0x04, 0x02, 0xC3, 0x01, 0xA3, 0x01, 0x83, 0x01, 0x42, 0x01, 0xE2, 0x00, 0x82, 0x00, 0x41, 0x00, 
    0x41, 0x00, 0x42, 0x00, 0x82, 0x04, 0xA3, 0x04, 0xE3, 0x08, 0x24, 0x09, 0x44, 0x09, 0x24, 0x09, 
    0x25, 0x09, 0x04, 0x09, 0xC3, 0x04, 0xC2, 0x04, 0xA2, 0x04, 0x82, 0x04, 0x82, 0x04, 0xA2, 0x04, 
    0xE2, 0x04, 0x02, 0x01, 0x63, 0x01, 0xA3, 0x01, 0xE4, 0x01, 0x25, 0x02, 0x65, 0x02, 0x65, 0x02, 
    0x85, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 
    0xA5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0xC6, 0x02, 0xC6, 0x02, 0xC6, 0x02, 0xC3, 0x02, 0xC3, 0x02, 
    0xE7, 0x02, 0x4F, 0x2B, 0xB8, 0x57, 0xFD, 0x77, 0xFD, 0x77, 0xFD, 0x77, 0xFD, 0x77, 0xFE, 0x7B, 
    0x3A, 0x00, 0x41, 0x00, 0xFB, 0x67, 0xF5, 0x43, 0xEE, 0x23, 0xEA, 0x13, 0xE9, 0x0B, 0xE8, 0x03, 
    0xE7, 0x03, 0xE8, 0x03, 0xE8, 0x03, 0xC8, 0x03, 0x88, 0x03, 0x47, 0x03, 0xE6, 0x02, 0xC6, 0x02, 
    0xA5, 0x02, 0x64, 0x02, 0x24, 0x02, 0x04, 0x02, 0xC3, 0x01, 0x42, 0x01, 0xE2, 0x00, 0x81, 0x00, 
    0x41, 0x00, 0x42, 0x00, 0x62, 0x00, 0xA2, 0x04, 0xE3, 0x04, 0x03, 0x05, 0x24, 0x09, 0x04, 0x09, 
    0xE4, 0x08, 0xC3, 0x04, 0xA2, 0x04, 0x82, 0x04, 0x81, 0x04, 0x81, 0x04, 0x82, 0x04, 0xC2, 0x04, 
    0x02, 0x01, 0x63, 0x01, 0xC3, 0x01, 0x04, 0x02, 0x45, 0x02, 0x85, 0x02, 0xA6, 0x02, 0xC5, 0x02, 
    0xC5, 0x02, 0xC5, 0x02, 0xC5, 0x02, 0xC5, 0x02, 0xC5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 
    0xA4, 0x02, 0xA4, 0x02, 0xA4, 0x02, 0xA4, 0x02, 0xA4, 0x02, 0xC6, 0x02, 0xE6, 0x0A, 0xE8, 0x12, 
    0x2D, 0x23, 0x95, 0x4B, 0xDD, 0x73, 0x3F, 0x00, 0x41, 0x00, 0xFD, 0x73, 0xF9, 0x5F, 0xF6, 0x4B, 
    0xF1, 0x37, 0xEC, 0x1B, 0xE8, 0x03, 0xE5, 0x03, 0xE6, 0x03, 0xE7, 0x03, 0xC8, 0x03, 0xA7, 0x03, 
    0x67, 0x03, 0x46, 0x03, 0x06, 0x03, 0xE6, 0x02, 0xA5, 0x02, 0x85, 0x02, 0x64, 0x02, 0x04, 0x02, 
    0x83, 0x01, 0x02, 0x01, 0xA1, 0x00, 0x61, 0x00, 0x42, 0x00, 0x62, 0x04, 0x82, 0x04, 0xA2, 0x04, 
    0xE2, 0x04, 0xE3, 0x04, 0xE3, 0x04, 0xC3, 0x08, 0xA3, 0x04, 0x82, 0x04, 0x61, 0x04, 0x61, 0x00, 
    0x81, 0x00, 0xA1, 0x04, 0xE2, 0x00, 0x43, 0x01, 0xA3, 0x01, 0x24, 0x02, 0x65, 0x02, 0x85, 0x02, 
    0xA5, 0x02, 0xC6, 0x02, 0xC6, 0x02, 0xC6, 0x02, 0xC6, 0x02, 0xC6, 0x02, 0xC6, 0x02, 0xA5, 0x02, 
    0xA5, 0x02, 0xA5, 0x02, 0xA4, 0x02, 0x84, 0x02, 0x83, 0x02, 0x82, 0x02, 0x81, 0x02, 0x81, 0x02, 
    0xC5, 0x02, 0x0A, 0x1B, 0x4F, 0x37, 0x95, 0x4B, 0xBA, 0x63, 0xFE, 0x7B, 0x40, 0x00, 0x3F, 0x00, 
    0xFE, 0x77, 0xFD, 0x73, 0xF8, 0x5B, 0xF1, 0x2F, 0xE9, 0x07, 0xE5, 0x03, 0xE5, 0x03, 0xE7, 0x03, 
    0xC7, 0x03, 0xA7, 0x03, 0x87, 0x03, 0x66, 0x03, 0x46, 0x03, 0x26, 0x03, 0xE5, 0x02, 0xC5, 0x02, 
    0xA5, 0x02, 0x44, 0x02, 0xC3, 0x01, 0x42, 0x01, 0xE1, 0x00, 0x81, 0x00, 0x82, 0x00, 0x82, 0x04, 
    0x82, 0x04, 0xA2, 0x04, 0xC2, 0x04, 0xC2, 0x04, 0xC3, 0x04, 0xC3, 0x08, 0xA3, 0x04, 0x82, 0x04, 
    0x81, 0x04, 0x81, 0x00, 0xA1, 0x00, 0xC2, 0x00, 0x22, 0x01, 0xA3, 0x01, 0x04, 0x02, 0x65, 0x02, 
    0xA5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0xC5, 0x02, 0xA5, 0x02, 0xC6, 0x02, 0xC6, 0x02, 0xC6, 0x02, 
    0xA6, 0x02, 0xA6, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0xA4, 0x02, 0xA4, 0x02, 0xA3, 0x02, 
    0x81, 0x02, 0x81, 0x02, 0xC6, 0x06, 0x2E, 0x2F, 0xB7, 0x5B, 0xFD, 0x73, 0xFE, 0x77, 0x43, 0x00, 
    0x3B, 0x00, 0xFE, 0x73, 0xF6, 0x4B, 0xEF, 0x23, 0xE9, 0x13, 0xE7, 0x0B, 0xE7, 0x03, 0xC6, 0x03, 
    0xC6, 0x03, 0xA7, 0x03, 0x87, 0x03, 0x66, 0x03, 0x46, 0x03, 0x06, 0x03, 0xE5, 0x02, 0xC5, 0x02, 
    0x64, 0x02, 0x04, 0x02, 0xA3, 0x01, 0x42, 0x01, 0xE2, 0x00, 0xC2, 0x00, 0xC2, 0x04, 0xC2, 0x04, 
    0xC2, 0x00, 0xE2, 0x00, 0xE2, 0x00, 0xE2, 0x04, 0xC2, 0x04, 0xA2, 0x04, 0x82, 0x04, 0x81, 0x00, 
    0xA1, 0x00, 0xC1, 0x00, 0x02, 0x01, 0x83, 0x01, 0xE4, 0x01, 0x65, 0x02, 0xA6, 0x02, 0xC6, 0x02, 
    0xC5, 0x02, 0xC5, 0x02, 0xC5, 0x02, 0xA5, 0x02, 0xA6, 0x02, 0xA6, 0x02, 0xA6, 0x02, 0xA6, 0x02, 
    0xA5, 0x02, 0x84, 0x02, 0x84, 0x02, 0xA5, 0x02, 0xC7, 0x0A, 0xE9, 0x12, 0xE9, 0x16, 0xC7, 0x16, 
    0xC7, 0x16, 0x0C, 0x23, 0x74, 0x4B, 0xFD, 0x73, 0x46, 0x00, 0x39, 0x00, 0xFA, 0x63, 0xF6, 0x4B, 
    0xF0, 0x37, 0xEB, 0x1B, 0xC7, 0x03, 0xC4, 0x03, 0xA5, 0x03, 0x86, 0x03, 0x67, 0x03, 0x47, 0x03, 
    0x26, 0x03, 0x05, 0x03, 0xE5, 0x02, 0xC5, 0x02, 0x84, 0x02, 0x24, 0x02, 0xE3, 0x01, 0x83, 0x01, 
    0x42, 0x01, 0x22, 0x01, 0x02, 0x01, 0x02, 0x01, 0x23, 0x01, 0x23, 0x01, 0x23, 0x01, 0x03, 0x01, 
    0xE2, 0x04, 0xC2, 0x04, 0xA1, 0x00, 0x81, 0x00, 0xA1, 0x00, 0xE2, 0x00, 0x43, 0x01, 0xC4, 0x01, 
    0x24, 0x02, 0x65, 0x02, 0xA5, 0x02, 0xC5, 0x02, 0xC5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 
    0xA5, 0x02, 0xA5, 0x02, 0xA6, 0x02, 0xA5, 0x02, 0x84, 0x02, 0x62, 0x02, 0x62, 0x02, 0xA5, 0x02, 
    0xEB, 0x1E, 0x51, 0x37, 0x52, 0x43, 0x51, 0x43, 0x51, 0x43, 0x74, 0x4B, 0xB9, 0x63, 0x47, 0x00, 
    0x39, 0x00, 0xFE, 0x77, 0xFC, 0x6F, 0xF8, 0x5B, 0xF0, 0x33, 0xC9, 0x07, 0xA4, 0x03, 0xA4, 0x03, 
    0x86, 0x03, 0x47, 0x03, 0x26, 0x03, 0x06, 0x03, 0xE5, 0x02, 0xC5, 0x02, 0xA5, 0x02, 0x84, 0x02, 
    0x44, 0x02, 0x24, 0x02, 0xE3, 0x01, 0xA3, 0x01, 0x83, 0x01, 0x63, 0x01, 0x63, 0x01, 0x83, 0x01, 
    0xA4, 0x01, 0x84, 0x01, 0x43, 0x01, 0x22, 0x01, 0xE2, 0x00, 0xC1, 0x00, 0xA1, 0x00, 0xC2, 0x00, 
    0x22, 0x01, 0x83, 0x01, 0xE4, 0x01, 0x45, 0x02, 0x65, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 
    0xA5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0x83, 0x02, 
    0x61, 0x02, 0x61, 0x02, 0xC7, 0x0E, 0x30, 0x37, 0xB9, 0x5F, 0xDB, 0x6B, 0xDB, 0x6B, 0xDB, 0x6B, 
    0xDC, 0x6F, 0xFD, 0x77, 0x49, 0x00, 0x32, 0x00, 0xFE, 0x77, 0xF6, 0x4F, 0xEE, 0x23, 0xA9, 0x0F, 
    0x87, 0x07, 0x67, 0x03, 0x26, 0x03, 0x05, 0x03, 0xE5, 0x02, 0xC5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 
    0x85, 0x02, 0x65, 0x02, 0x64, 0x02, 0x44, 0x02, 0x24, 0x02, 0x03, 0x02, 0xE3, 0x01, 0xE4, 0x01, 
    0xE4, 0x01, 0x04, 0x02, 0xE4, 0x01, 0xA3, 0x01, 0x83, 0x01, 0x42, 0x01, 0x02, 0x01, 0x02, 0x01, 
    0x22, 0x01, 0x63, 0x01, 0xC4, 0x01, 0x25, 0x02, 0x65, 0x02, 0x85, 0x02, 0xA4, 0x02, 0xA5, 0x02, 
    0xA5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0xA4, 0x02, 0x84, 0x02, 0xA4, 0x02, 
    0xA4, 0x02, 0x84, 0x0A, 0xA6, 0x0E, 0x0D, 0x27, 0x96, 0x53, 0xFE, 0x7B, 0x4F, 0x00, 0x30, 0x00, 
    0xFB, 0x63, 0xF5, 0x47, 0xD0, 0x33, 0x8B, 0x1B, 0x47, 0x03, 0x03, 0x03, 0xE2, 0x02, 0xC3, 0x02, 
    0xA3, 0x02, 0xA4, 0x02, 0xA4, 0x02, 0xA5, 0x02, 0x85, 0x02, 0x85, 0x02, 0x85, 0x02, 0x65, 0x02, 
    0x44, 0x02, 0x24, 0x02, 0x24, 0x02, 0x24, 0x02, 0x24, 0x02, 0x04, 0x02, 0xE4, 0x01, 0xC3, 0x01, 
    0x82, 0x01, 0x62, 0x01, 0x62, 0x01, 0x83, 0x01, 0xC3, 0x01, 0x04, 0x02, 0x45, 0x02, 0x65, 0x02, 
    0x85, 0x02, 0x84, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0x84, 0x02, 0x84, 0x02, 0x83, 0x02, 
    0x82, 0x02, 0x61, 0x02, 0x82, 0x02, 0xA6, 0x06, 0xE9, 0x1E, 0x2F, 0x37, 0x74, 0x4B, 0xBA, 0x67, 
    0x50, 0x00, 0x30, 0x00, 0xFE, 0x77, 0xFC, 0x6B, 0xD8, 0x5B, 0x90, 0x33, 0x48, 0x0B, 0xE2, 0x02, 
    0xC1, 0x02, 0xC3, 0x02, 0xA3, 0x02, 0xA4, 0x02, 0xA4, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 
    0xA5, 0x02, 0x86, 0x02, 0x65, 0x02, 0x65, 0x02, 0x45, 0x02, 0x65, 0x02, 0x64, 0x02, 0x44, 0x02, 
    0x24, 0x02, 0x03, 0x02, 0xE3, 0x01, 0xC3, 0x01, 0xC3, 0x01, 0xC3, 0x01, 0x04, 0x02, 0x24, 0x02, 
    0x64, 0x02, 0x64, 0x02, 0x85, 0x02, 0x85, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0xA5, 0x02, 0xA4, 0x02, 
    0x84, 0x02, 0x83, 0x02, 0x82, 0x02, 0x61, 0x02, 0x82, 0x02, 0xC8, 0x0E, 0x30, 0x37, 0x98, 0x5F, 
    0xDB, 0x6F, 0xFD, 0x77, 0x52, 0x00, 0x2B, 0x00, 0xFE, 0x7B, 0xB6, 0x4F, 0x6D, 0x23, 0x06, 0x0B, 
    0x05, 0x0B, 0xE7, 0x0A, 0xE8, 0x0A, 0xC7, 0x06, 0xC6, 0x02, 0xC5, 0x02, 0xA5, 0x02, 0xC5, 0x02, 
    0xA6, 0x02, 0xA6, 0x02, 0x86, 0x02, 0x85, 0x02, 0x85, 0x02, 0x85, 0x02, 0x84, 0x02, 0x64, 0x02, 
    0x64, 0x02, 0x44, 0x02, 0x24, 0x02, 0x24, 0x02, 0x24, 0x02, 0x24, 0x02, 0x44, 0x02, 0x44, 0x02, 
    0x64, 0x02, 0x84, 0x02, 0x84, 0x02, 0x84, 0x02, 0x84, 0x02, 0xA4, 0x02, 0xA5, 0x02, 0xC6, 0x02, 
    0xC7, 0x06, 0xC8, 0x0A, 0xC7, 0x0A, 0xA5, 0x0A, 0xC7, 0x0A, 0x0E, 0x2B, 0x97, 0x57, 0x56, 0x00, 
    0x2A, 0x00, 0xDA, 0x67, 0x94, 0x47, 0x6F, 0x37, 0x4F, 0x37, 0x50, 0x37, 0x50, 0x33, 0x0C, 0x1F, 
    0xE7, 0x06, 0xA3, 0x02, 0xA2, 0x02, 0xA3, 0x02, 0xA3, 0x02, 0x84, 0x02, 0x84, 0x02, 0x84, 0x02, 
    0x64, 0x02, 0x63, 0x02, 0x63, 0x02, 0x63, 0x02, 0x43, 0x02, 0x43, 0x02, 0x43, 0x02, 0x22, 0x02, 
    0x23, 0x02, 0x23, 0x02, 0x43, 0x02, 0x43, 0x02, 0x63, 0x02, 0x63, 0x02, 0x63, 0x02, 0x62, 0x02, 
    0x62, 0x02, 0x81, 0x02, 0xA3, 0x02, 0xC7, 0x0A, 0x0C, 0x23, 0x50, 0x33, 0x30, 0x37, 0x2F, 0x37, 
    0x30, 0x37, 0x75, 0x4B, 0xDB, 0x6B, 0x56, 0x00, 0x2A, 0x00, 0xFD, 0x77, 0xDB, 0x6B, 0xD9, 0x63, 
    0xB9, 0x63, 0xB9, 0x63, 0xB8, 0x5F, 0x71, 0x3B, 0x09, 0x13, 0xC3, 0x02, 0xA0, 0x02, 0xA1, 0x02, 
    0x82, 0x02, 0x82, 0x02, 0x62, 0x02, 0x63, 0x02, 0x43, 0x02, 0x63, 0x02, 0x62, 0x02, 0x42, 0x02, 
    0x42, 0x02, 0x42, 0x02, 0x42, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x42, 0x02, 0x42, 0x02, 
    0x42, 0x02, 0x42, 0x02, 0x42, 0x02, 0x62, 0x02, 0x60, 0x02, 0x60, 0x02, 0xA2, 0x02, 0x0A, 0x17, 
    0x52, 0x3F, 0xB9, 0x5F, 0xB9, 0x63, 0xB9, 0x63, 0xB9, 0x63, 0xDB, 0x6B, 0xFE, 0x77, 0x5C, 0x00, 
    0x1E, 0x00, 0xB7, 0x57, 0x4F, 0x2B, 0xE7, 0x06, 0xC4, 0x06, 0xC5, 0x06, 0xC6, 0x06, 0xA6, 0x06, 
    0xA6, 0x06, 0x87, 0x06, 0x87, 0x06, 0x87, 0x06, 0x87, 0x06, 0x87, 0x06, 0x87, 0x06, 0x87, 0x06, 
    0x87, 0x06, 0x87, 0x06, 0x87, 0x06, 0x87, 0x06, 0x87, 0x06, 0x87, 0x06, 0x87, 0x06, 0x86, 0x06, 
    0x86, 0x06, 0xA6, 0x06, 0xA4, 0x06, 0xA3, 0x06, 0xE7, 0x0A, 0x4F, 0x2F, 0xB8, 0x5B, 0x62, 0x00, 
    0x1E, 0x00, 0xDB, 0x6B, 0x95, 0x4B, 0x4F, 0x2F, 0x2D, 0x2F, 0x2E, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 
    0x0F, 0x2F, 0x0F, 0x2F, 0x0F, 0x2F, 0x0F, 0x2F, 0x0F, 0x2F, 0x0F, 0x2F, 0x0F, 0x2F, 0x0F, 0x2F, 
    0x0F, 0x2F, 0x0F, 0x2F, 0x0F, 0x2F, 0x0F, 0x2F, 0x0F, 0x2F, 0x0F, 0x2F, 0x0F, 0x2F, 0x0F, 0x2F, 
    0x0F, 0x2F, 0x0E, 0x2F, 0x0D, 0x2F, 0x0C, 0x2F, 0x4F, 0x33, 0x95, 0x4F, 0xDC, 0x6F, 0x62, 0x00, 
    0x1E, 0x00, 0xFE, 0x77, 0xDB, 0x67, 0xB8, 0x5F, 0xB7, 0x5F, 0xB8, 0x5F, 0xB8, 0x5F, 0x98, 0x5F, 
    0x98, 0x5F, 0x98, 0x5F, 0x98, 0x5F, 0x98, 0x5F, 0x98, 0x5F, 0x98, 0x5F, 0x98, 0x5F, 0x98, 0x5F, 
    0x98, 0x5F, 0x98, 0x5F, 0x98, 0x5F, 0x98, 0x5F, 0x98, 0x5F, 0x98, 0x5F, 0x98, 0x5F, 0x98, 0x5F, 
    0x98, 0x5F, 0x98, 0x5F, 0x97, 0x5F, 0x97, 0x5F, 0xB8, 0x5F, 0xDB, 0x6B, 0xFE, 0x7B, 0x3F, 0x08, 
    0x00, 0x00
};



--- NEW FILE: libkbd.cpp ---
/*
# _____     ___ ____     ___ ____
#  ____|   |    ____|   |        | |____|
# |     ___|   |____ ___|    ____| |    \    PS2DEV Open Source Project.
#-----------------------------------------------------------------------
# Copyright 2001-2004, ps2dev - http://www.ps2dev.org
# Licenced under Academic Free License version 2.0
# Review ps2sdk README & LICENSE files for further details.
#
# $Id: libkbd.cpp,v 1.1 2005/03/31 05:35:04 lavosspawn Exp $
# USB Keyboard Driver for PS2
*/


/*   *
	 *  This is the normal Ps2Kbd EE Sourcecode, slightly changed
	 *  and merged into ScummVM's source to work with its
	 *  asynchronous fio.
	 *
 */


#include <tamtypes.h>
#include <fileio.h>
#include "libkbd.h"
#include "backends/ps2/asyncfio.h"

static int kbd_fd = -1;
static int curr_blockmode = PS2KBD_NONBLOCKING;
static int curr_readmode = PS2KBD_READMODE_NORMAL;

extern AsyncFio fio;

int PS2KbdInit(void)
/* Initialise the keyboard library */
{
  if(kbd_fd >= 0) /* Already initialised */
    {
      return 0;
    }

  kbd_fd = fio.open(PS2KBD_DEVFILE, 0);
  if(kbd_fd < 0)
    {
      return 0;
    }

  return 1;
}

int PS2KbdRead(char *key)
/* Reads 1 character from the keyboard */
{
  if((kbd_fd >= 0) && (curr_readmode == PS2KBD_READMODE_NORMAL))
    {
      fio.read(kbd_fd, key, 1);
	  return fio.sync(kbd_fd);
    }

  return 0;
}

int PS2KbdReadRaw(PS2KbdRawKey *key)
/* Reads 1 raw character from the keyboard */
{
  if((kbd_fd >= 0) && (curr_readmode == PS2KBD_READMODE_RAW))
    {
      fio.read(kbd_fd, key, 2);
	  return fio.sync(kbd_fd) / 2;
    }

  return 0;
}

int PS2KbdSetReadmode(u32 readmode)
/* Sets the read mode to normal or raw */
{
  if((kbd_fd >= 0) && (curr_readmode != readmode))
    {
      curr_readmode = readmode;
      return fioIoctl(kbd_fd, PS2KBD_IOCTL_SETREADMODE, &readmode);
    }
  return 0;
}

int PS2KbdSetBlockingMode(u32 blockmode)
/* Sets the blocking mode on or off */
{
  if((kbd_fd >= 0) && (curr_blockmode != blockmode))
    {
      return fioIoctl(kbd_fd, PS2KBD_IOCTL_SETBLOCKMODE, &blockmode);
    }

  return 0;
}

int PS2KbdSetRepeatRate(u32 repeat)
/* Sets the repeat rate in millseconds */
{
  if(kbd_fd >= 0)
    {
      return fioIoctl(kbd_fd, PS2KBD_IOCTL_SETREPEATRATE, &repeat);
    }
  return 0;
}

int PS2KbdSetLeds(u8 leds)
/* Sets all connected keyboards leds */
{
  if(kbd_fd >= 0)
    {
      return fioIoctl(kbd_fd, PS2KBD_IOCTL_SETLEDS, &leds);
    }
  return 0;
}

int PS2KbdSetKeymap(PS2KbdKeyMap *keymaps)
/* Sets the current keymap */
{
  if(kbd_fd >= 0)
    {
      return fioIoctl(kbd_fd, PS2KBD_IOCTL_SETKEYMAP, keymaps);
    }
  return 0;
}

int PS2KbdSetCtrlmap(u8 *ctrlmap)
/* Sets the control key mappings */
{
  if(kbd_fd >= 0)
    {
      return fioIoctl(kbd_fd, PS2KBD_IOCTL_SETCTRLMAP, ctrlmap);
    }
  return 0;
}

int PS2KbdSetAltmap(u8 *altmap)
/* Sets the alt key mappings */
{
  if(kbd_fd >= 0)
    {
      return fioIoctl(kbd_fd, PS2KBD_IOCTL_SETALTMAP, altmap);
    }
  return 0;
}

int PS2KbdSetSpecialmap(u8 *special)
/* Sets the special key mappings */
{
  if(kbd_fd >= 0)
    {
      return fioIoctl(kbd_fd, PS2KBD_IOCTL_SETSPECIALMAP, special);
    }
  return 0;
}

int PS2KbdFlushBuffer(void)
/* Flushes the keyboard buffer */
{
  int dummy;

  if(kbd_fd >= 0)
    {
      return fioIoctl(kbd_fd, PS2KBD_IOCTL_FLUSHBUFFER, &dummy);
    }
  return 0;
}

int PS2KbdResetKeymap(void)
/* Resets the keymap to the default US mapping */
{
  int dummy;

  if(kbd_fd >= 0)
    {
      return fioIoctl(kbd_fd, PS2KBD_IOCTL_RESETKEYMAP, &dummy);
    }
  return 0;
}

int PS2KbdClose(void)
/* Close down the keyboard library */
{
  if(kbd_fd >= 0)
    {
      fio.close(kbd_fd);
      kbd_fd = -1;
    }

  return 1;
}

--- NEW FILE: ps2input.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2001-2004 The ScummVM project
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/backends/ps2/ps2input.cpp,v 1.1 2005/03/31 05:35:04 lavosspawn Exp $
 *
 */

#include <kernel.h>
#include <malloc.h>
#include <assert.h>
#include <libmouse.h>
#include <libkbd.h>
#include "backends/ps2/ps2input.h"
#include "backends/ps2/ps2pad.h"
#include "backends/ps2/systemps2.h"
#include "backends/ps2/sdlkeys.h"
#include "common/system.h"

Ps2Input::Ps2Input(OSystem_PS2 *system, bool mouseLoaded, bool kbdLoaded) {
	_system = system;
	_mouseLoaded = mouseLoaded;
	_kbdLoaded = kbdLoaded;
	_pad = new Ps2Pad(system);
	_lastPadCheck = 0;
	_posX = _posY = _mButtons = _padLastButtons = 0;
	_padAccel = 0;
	_minx = _miny = 0;
	_maxy = 239;
	_maxx = 319;
	_keyFlags = 0;
	if (_mouseLoaded) {
		if (PS2MouseInit() >= 0) {
			PS2MouseSetReadMode(PS2MOUSE_READMODE_ABS);
			printf("PS2Mouse initialized\n");
		} else { // shouldn't happen if the drivers were correctly loaded
			printf("unable to initialize PS2Mouse!\n");
			_mouseLoaded = false;
		}
	}
	if (_kbdLoaded) {
		if (PS2KbdInit() >= 0) {
			PS2KbdSetReadmode(PS2KBD_READMODE_RAW);
			PS2KbdSetBlockingMode(PS2KBD_NONBLOCKING);
			printf("PS2Kbd initialized\n");
		} else {
			printf("unable to initialize PS2Kbd!\n");
			_kbdLoaded = false;
		}
	}
}

Ps2Input::~Ps2Input(void) {
}

void Ps2Input::newRange(uint16 minx, uint16 miny, uint16 maxx, uint16 maxy) {
	_minx = minx;
	_miny = miny;
	_maxx = maxx;
	_maxy = maxy;
	if (_mouseLoaded)
		PS2MouseSetBoundary(minx, maxx, miny, maxy);
	warpTo(_posX, _posY);
}

void Ps2Input::warpTo(uint16 x, uint16 y) {
	if ((x >= _minx) && (x <= _maxx) && (y >= _miny) && (y <= _maxy)) {
		_posX = x;
		_posY = y;
	} else {
		_posX = (x < _minx) ? (_minx) : ((x > _maxx) ? (_maxx) : (x));
		_posY = (y < _miny) ? (_miny) : ((y > _maxy) ? (_maxy) : (y));
	}
	if (_mouseLoaded)
		PS2MouseSetPosition(_posX, _posY);
}

#define JOY_THRESHOLD 30
#define PAD_CHECK_TIME 20

int Ps2Input::mapKey(int key, int mod) { // copied from sdl backend
	if (key >= SDLK_F1 && key <= SDLK_F9) {
		return key - SDLK_F1 + 315;
	} else if (key >= SDLK_KP0 && key <= SDLK_KP9) {
		return key - SDLK_KP0 + '0';
	} else if (key >= SDLK_UP && key <= SDLK_PAGEDOWN) {
		return key;
	} else if (key >= 'a' && key <= 'z' && mod & OSystem::KBD_SHIFT) {
		return key & ~0x20;
	} else if (key >= SDLK_NUMLOCK && key <= SDLK_EURO) {
		return 0;
	}
	return key;
}

bool Ps2Input::pollEvent(OSystem::Event *event) {
	bool checkPadMouse, checkPadKbd;
	checkPadMouse = checkPadKbd = _pad->padAlive();

	if (_mouseLoaded && (PS2MouseEnum() > 0)) { // usb mouse connected
		mouse_data mData;
		PS2MouseRead(&mData);
		if ((_posX != mData.x) || (_posY != mData.y)) {
			event->mouse.x = _posX = mData.x;
			event->mouse.y = _posY = mData.y;
			event->type = OSystem::EVENT_MOUSEMOVE;
            return true;
		}
		if (mData.buttons != _mButtons) {
			uint16 change = _mButtons ^ mData.buttons;
			_mButtons = mData.buttons;
			if (change & (PS2MOUSE_BTN1 | PS2MOUSE_BTN2)) {
				if (change & PS2MOUSE_BTN1)
					event->type = (_mButtons & PS2MOUSE_BTN1) ? OSystem::EVENT_LBUTTONDOWN : OSystem::EVENT_LBUTTONUP;
				else 
					event->type = (_mButtons & PS2MOUSE_BTN2) ? OSystem::EVENT_RBUTTONDOWN : OSystem::EVENT_RBUTTONUP;
				event->mouse.x = _posX;
				event->mouse.y = _posY;
				return true;
			}
		}
		checkPadMouse = false;
	}
	if (_kbdLoaded) { // there's no way to tell if there's actually a keyboard connected
		PS2KbdRawKey key;
		if (PS2KbdReadRaw(&key) == 1) {
			if (_usbToSdlk[key.key]) {
				if ((_usbToSdlk[key.key] == SDLK_LSHIFT) || (_usbToSdlk[key.key] == SDLK_RSHIFT)) {
					if (key.state & 1)
						_keyFlags |= OSystem::KBD_SHIFT;
					else
						_keyFlags &= ~OSystem::KBD_SHIFT;
				} else if ((_usbToSdlk[key.key] == SDLK_LCTRL) || (_usbToSdlk[key.key] == SDLK_RCTRL)) {
					if (key.state & 1)
						_keyFlags |= OSystem::KBD_CTRL;
					else
						_keyFlags &= ~OSystem::KBD_CTRL;
				} else if ((_usbToSdlk[key.key] == SDLK_LALT) || (_usbToSdlk[key.key] == SDLK_RALT)) {
					if (key.state & 1)
						_keyFlags |= OSystem::KBD_ALT;
					else
						_keyFlags &= ~OSystem::KBD_ALT;
				}
				if (key.state & 1) // down
					event->type = OSystem::EVENT_KEYDOWN;
				else
					event->type = OSystem::EVENT_KEYUP;
				event->kbd.flags = 0;
				event->kbd.keycode = _usbToSdlk[key.key];
				event->kbd.ascii = mapKey(_usbToSdlk[key.key], _keyFlags);
				return true;
			} else
				printf("unknown keycode %02X - %02X\n", key.state, key.key);
		}
	}
	if (checkPadMouse || checkPadKbd) {
		// no usb mouse, simulate it using the pad
        uint16 buttons;
		int16 joyh, joyv;
		_pad->readPad(&buttons, &joyh, &joyv);
		uint16 btnChange = buttons ^ _padLastButtons;
		
		if (checkPadMouse) {
			if (btnChange & (PAD_CROSS | PAD_CIRCLE)) {
				if (btnChange & PAD_CROSS) 
					event->type = (buttons & PAD_CROSS) ?  OSystem::EVENT_LBUTTONDOWN : OSystem::EVENT_LBUTTONUP;
				else
					event->type = (buttons & PAD_CIRCLE) ? OSystem::EVENT_RBUTTONDOWN : OSystem::EVENT_RBUTTONUP;
				event->mouse.x = _posX;
				event->mouse.y = _posY;
				_padLastButtons = buttons;
				return true;
			}
			uint32 time = _system->getMillis();
			if (time - _lastPadCheck > PAD_CHECK_TIME) {
				_lastPadCheck = time;
				int16 newX = _posX;
				int16 newY = _posY;
				if ((ABS(joyh) > JOY_THRESHOLD) || (ABS(joyv) > JOY_THRESHOLD)) {
					newX += joyh / 20;
					newY += joyv / 20;
				} else if (buttons & PAD_DIR_MASK) {
					if (_padLastButtons & PAD_DIR_MASK) {
						if (_padAccel < 16)
							_padAccel++;
					} else
						_padAccel = 0;
					_padLastButtons = buttons;
					if (buttons & PAD_LEFT)
						newX -= _padAccel >> 2;
					if (buttons & PAD_RIGHT)
						newX += _padAccel >> 2;
					if (buttons & PAD_UP)
						newY -= _padAccel >> 2;
					if (buttons & PAD_DOWN)
						newY += _padAccel >> 2;
				}
				newX = ((newX < (int16)_minx) ? (_minx) : ((newX > (int16)_maxx) ? (_maxx) : ((int16)newX)));
				newY = ((newY < (int16)_miny) ? (_miny) : ((newY > (int16)_maxy) ? (_maxy) : ((int16)newY)));
				if ((_posX != newX) || (_posY != newY)) {
					event->type = OSystem::EVENT_MOUSEMOVE;
					event->mouse.x = _posX = newX;
					event->mouse.y = _posY = newY;
					return true;
				}
			}
		}
		if (checkPadKbd) {
			if (getKeyEvent(event, btnChange, (btnChange & buttons) != 0)) {
				_padLastButtons = buttons;
				return true;
			}
		}
	}
	return false;
}

bool Ps2Input::getKeyEvent(OSystem::Event *event, uint16 buttonCode, bool down) {
	// for simulating key presses with the pad
	if (buttonCode) {
		uint8 entry = 0;
		while (!(buttonCode & 1)) {
			entry++;
			buttonCode >>= 1;
		}
		if (_asciiCodes[entry] || _keyCodes[entry]) {
			event->type = (down) ? OSystem::EVENT_KEYDOWN : OSystem::EVENT_KEYUP;
			event->kbd.ascii = _asciiCodes[entry];
			event->kbd.keycode = _keyCodes[entry];
			event->kbd.flags = 0;
			return true;
		}
	}
	return false;
}

const int Ps2Input::_usbToSdlk[0x100] = {
	/* 00 */	0,
	/* 01 */	0,
	/* 02 */	0,
	/* 03 */	0,
	/* 04 */	SDLK_a,
	/* 05 */	SDLK_b,
	/* 06 */	SDLK_c,
	/* 07 */	SDLK_d,
	/* 08 */	SDLK_e,
	/* 09 */	SDLK_f,
	/* 0A */	SDLK_g,
	/* 0B */	SDLK_h,
	/* 0C */	SDLK_i,
	/* 0D */	SDLK_j,
	/* 0E */	SDLK_k,
	/* 0F */	SDLK_l,
	/* 10 */	SDLK_m,
	/* 11 */	SDLK_n,
	/* 12 */	SDLK_o,
	/* 13 */	SDLK_p,
	/* 14 */	SDLK_q,
	/* 15 */	SDLK_r,
	/* 16 */	SDLK_s,
	/* 17 */	SDLK_t,
	/* 18 */	SDLK_u,
	/* 19 */	SDLK_v,
	/* 1A */	SDLK_w,
	/* 1B */	SDLK_x,
	/* 1C */	SDLK_y,
	/* 1D */	SDLK_z,
	/* 1E */	SDLK_1,
	/* 1F */	SDLK_2,
	/* 20 */	SDLK_3,
	/* 21 */	SDLK_4,
	/* 22 */	SDLK_5,
	/* 23 */	SDLK_6,
	/* 24 */	SDLK_7,
	/* 25 */	SDLK_8,
	/* 26 */	SDLK_9,
	/* 27 */	SDLK_0,
	/* 28 */	SDLK_RETURN,
	/* 29 */	SDLK_ESCAPE,
	/* 2A */	SDLK_BACKSPACE,
	/* 2B */	SDLK_TAB,
	/* 2C */	SDLK_SPACE,
	/* 2D */	SDLK_MINUS,
	/* 2E */	SDLK_EQUALS,
	/* 2F */	SDLK_LEFTBRACKET,
	/* 30 */	SDLK_RIGHTBRACKET,
	/* 31 */	SDLK_BACKSLASH,
	/* 32 */	SDLK_HASH,
	/* 33 */	SDLK_SEMICOLON,
	/* 34 */	SDLK_QUOTE,
	/* 35 */	SDLK_BACKQUOTE,
	/* 36 */	SDLK_COMMA,
	/* 37 */	SDLK_PERIOD,
	/* 38 */	SDLK_SLASH,
	/* 39 */	SDLK_CAPSLOCK,
	/* 3A */	SDLK_F1,
	/* 3B */	SDLK_F2,
	/* 3C */	SDLK_F3,
	/* 3D */	SDLK_F4,
	/* 3E */	SDLK_F5,
	/* 3F */	SDLK_F6,
	/* 40 */	SDLK_F7,
	/* 41 */	SDLK_F8,
	/* 42 */	SDLK_F9,
	/* 43 */	SDLK_F10,
	/* 44 */	SDLK_F11,
	/* 45 */	SDLK_F12,
	/* 46 */	SDLK_PRINT,
	/* 47 */	SDLK_SCROLLOCK,
	/* 48 */	SDLK_PAUSE,
	/* 49 */	SDLK_INSERT,
	/* 4A */	SDLK_HOME,
	/* 4B */	SDLK_PAGEUP,
	/* 4C */	SDLK_DELETE,
	/* 4D */	SDLK_END,
	/* 4E */	SDLK_PAGEDOWN,
	/* 4F */	SDLK_RIGHT,
	/* 50 */	SDLK_LEFT,
	/* 51 */	SDLK_DOWN,
	/* 52 */	SDLK_UP,
	/* 53 */	SDLK_NUMLOCK,
	/* 54 */	SDLK_KP_DIVIDE,
	/* 55 */	SDLK_KP_MULTIPLY,
	/* 56 */	SDLK_KP_MINUS,
	/* 57 */	SDLK_KP_PLUS,
	/* 58 */	SDLK_KP_ENTER,
	/* 59 */	SDLK_KP1,
	/* 5A */	SDLK_KP2,
	/* 5B */	SDLK_KP3,
	/* 5C */	SDLK_KP4,
	/* 5D */	SDLK_KP5,
	/* 5E */	SDLK_KP6,
	/* 5F */	SDLK_KP7,
	/* 60 */	SDLK_KP8,
	/* 61 */	SDLK_KP9,
	/* 62 */	SDLK_KP0,
	/* 63 */	SDLK_KP_PERIOD,
	/* 64 */	0,
	/* 65 */	0,
	/* 66 */	0,
	/* 67 */	SDLK_KP_EQUALS,
	/* 68 */	0,
	/* 69 */	0,
	/* 6A */	0,
	/* 6B */	0,
	/* 6C */	0,
	/* 6D */	0,
	/* 6E */	0,
	/* 6F */	0,
	/* 70 */	0,
	/* 71 */	0,
	/* 72 */	0,
	/* 73 */	0,
	/* 74 */	0,
	/* 75 */	0,
	/* 76 */	0,
	/* 77 */	0,
	/* 78 */	0,
	/* 79 */	0,
	/* 7A */	0,
	/* 7B */	0,
	/* 7C */	0,
	/* 7D */	0,
	/* 7E */	0,
	/* 7F */	0,
	/* 80 */	0,
	/* 81 */	0,
	/* 82 */	0,
	/* 83 */	0,
	/* 84 */	0,
	/* 85 */	0,
	/* 86 */	0,
	/* 87 */	0,
	/* 88 */	0,
	/* 89 */	0,
	/* 8A */	0,
	/* 8B */	0,
	/* 8C */	0,
	/* 8D */	0,
	/* 8E */	0,
	/* 8F */	0,
	/* 90 */	0,
	/* 91 */	0,
	/* 92 */	0,
	/* 93 */	0,
	/* 94 */	0,
	/* 95 */	0,
	/* 96 */	0,
	/* 97 */	0,
	/* 98 */	0,
	/* 99 */	0,
	/* 9A */	0,
	/* 9B */	0,
	/* 9C */	0,
	/* 9D */	0,
	/* 9E */	0,
	/* 9F */	0,
	/* A0 */	0,
	/* A1 */	0,
	/* A2 */	0,
	/* A3 */	0,
	/* A4 */	0,
	/* A5 */	0,
	/* A6 */	0,
	/* A7 */	0,
	/* A8 */	0,
	/* A9 */	0,
	/* AA */	0,
	/* AB */	0,
	/* AC */	0,
	/* AD */	0,
	/* AE */	0,
	/* AF */	0,
	/* B0 */	0,
	/* B1 */	0,
	/* B2 */	0,
	/* B3 */	0,
	/* B4 */	0,
	/* B5 */	0,
	/* B6 */	0,
	/* B7 */	0,
	/* B8 */	0,
	/* B9 */	0,
	/* BA */	0,
	/* BB */	0,
	/* BC */	0,
	/* BD */	0,
	/* BE */	0,
	/* BF */	0,
	/* C0 */	0,
	/* C1 */	0,
	/* C2 */	0,
	/* C3 */	0,
	/* C4 */	0,
	/* C5 */	0,
	/* C6 */	0,
	/* C7 */	0,
	/* C8 */	0,
	/* C9 */	0,
	/* CA */	0,
	/* CB */	0,
	/* CC */	0,
	/* CD */	0,
	/* CE */	0,
	/* CF */	0,
	/* D0 */	0,
	/* D1 */	0,
	/* D2 */	0,
	/* D3 */	0,
	/* D4 */	0,
	/* D5 */	0,
	/* D6 */	0,
	/* D7 */	0,
	/* D8 */	0,
	/* D9 */	0,
	/* DA */	0,
	/* DB */	0,
	/* DC */	0,
	/* DD */	0,
	/* DE */	0,
	/* DF */	0,
	/* E0 */    SDLK_LCTRL,
	/* E1 */	SDLK_LSHIFT,
	/* E2 */	SDLK_LALT,
	/* E3 */	0,
	/* E4 */    SDLK_RCTRL,
	/* E5 */	SDLK_RSHIFT,
	/* E6 */	SDLK_RALT,
	/* E7 */	0,
	/* E8 */	0,
	/* E9 */	0,
	/* EA */	0,
	/* EB */	0,
	/* EC */	0,
	/* ED */	0,
	/* EE */	0,
	/* EF */	0,
	/* F0 */	0,
	/* F1 */	0,
	/* F2 */	0,
	/* F3 */	0,
	/* F4 */	0,
	/* F5 */	0,
	/* F6 */	0,
	/* F7 */	0,
	/* F8 */	0,
	/* F9 */	0,
	/* FA */	0,
	/* FB */	0,
	/* FC */	0,
	/* FD */	0,
	/* FE */	0,
	/* FF */	0
};

const int Ps2Input::_keyCodes[16] = { 
	49,	 // '1' - Select
	0,	 //     - L3
	0,	 //     - R3
	286, // F5  - Start
	0,	 //		- Up
	0,	 //		- Right
	0,	 //		- Down
	0,	 //		- Left
	0,	 //		- L2
	0,	 //		- R2
	0,	 //		- L1
	0,	 //		- R1
	27,	 // Esc - Triangle
	0,	 //		- Circle
	0,	 //		- Cross
	0,	 //		- Square
};

const uint16 Ps2Input::_asciiCodes[16] = { 
	49,	 // '1' - Select
	0,	 //     - L3
	0,	 //     - R3
	319, // F5  - Start
	0,	 //		- Up
	0,	 //		- Right
	0,	 //		- Down
	0,	 //		- Left
	0,	 //		- L2
	0,	 //		- R2
	0,	 //		- L1
	0,	 //		- R1
	27,	 // Esc - Triangle
	0,	 //		- Circle
	0,	 //		- Cross
	0,	 //		- Square
};


--- NEW FILE: ps2input.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2001-2004 The ScummVM project
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/backends/ps2/ps2input.h,v 1.1 2005/03/31 05:35:04 lavosspawn Exp $
 *
 */

#ifndef __PS2INPUT_H__
#define __PS2INPUT_H__

#include "common/system.h"

class OSystem_PS2;
class Ps2Pad;

class Ps2Input {
public:
	Ps2Input(OSystem_PS2 *system, bool mouseLoaded, bool kbdLoaded);
	~Ps2Input(void);
	void newRange(uint16 minx, uint16 miny, uint16 maxx, uint16 maxy);
	bool pollEvent(OSystem::Event *event);
	void warpTo(uint16 x, uint16 y);
private:
	int mapKey(int key, int mod);
	bool getKeyEvent(OSystem::Event *event, uint16 buttonCode, bool down);
	OSystem_PS2 *_system;
	Ps2Pad		*_pad;

	uint16 _minx, _maxx, _miny, _maxy;

	uint16 _posX, _posY;
	uint16 _mButtons;
	uint16 _padLastButtons;
	uint32 _lastPadCheck;
	uint16 _padAccel;

	bool _mouseLoaded, _kbdLoaded;
	int _keyFlags;
	static const int _keyCodes[16];
	static const uint16 _asciiCodes[16];
	static const int _usbToSdlk[0x100];
};

#endif // __PS2INPUT_H__


--- NEW FILE: ps2pad.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2001-2004 The ScummVM project
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/backends/ps2/ps2pad.cpp,v 1.1 2005/03/31 05:35:04 lavosspawn Exp $
 *
 */

#include <kernel.h>
#include <malloc.h>
#include <assert.h>
#include "backends/ps2/systemps2.h"
#include "backends/ps2/ps2pad.h"

Ps2Pad::Ps2Pad(OSystem_PS2 *system) {
	_system = system;
	_padBuf = (uint8*)memalign(64, 256);
	_padStatus = STAT_NONE;
	
	padInit(0); // initialize library
	_port = _slot = 0;	// first controller, no multitap
	initPad();
}

void Ps2Pad::initPad(void) {
	int modes = 0;
	if (_padStatus == STAT_NONE) {
		if (padPortOpen(_port, _slot, _padBuf) == 1) {
			_padStatus = STAT_OPEN;
			_padInitTime = _system->getMillis();
		} else {
			padPortClose(_port, _slot);
			printf("Unable to open port (%d/%d)!\n", _port, _slot);
		}
	} else {
		if (checkPadReady(_port, _slot)) {
			switch (_padStatus) {
				case STAT_OPEN:
					_padStatus = STAT_DETECT;
					break;
				case STAT_DETECT:
					_isDualShock = false;
					modes = padInfoMode(_port, _slot, PAD_MODETABLE, -1);

					// Verify that the controller has a DUAL SHOCK mode
					for (int cnt = 0; cnt < modes; cnt++)
						if (padInfoMode(_port, _slot, PAD_MODETABLE, cnt) == PAD_TYPE_DUALSHOCK)
							_isDualShock = true;

					// If ExId != 0x0 => This controller has actuator engines
					// This check should always pass if the Dual Shock test above passed
					if (_isDualShock)
						if (padInfoMode(_port, _slot, PAD_MODECUREXID, 0) == 0)
							_isDualShock = false;

					if (_isDualShock) {
						// When using MMODE_LOCK, user cant change mode with Select button
						padSetMainMode(_port, _slot, PAD_MMODE_DUALSHOCK, PAD_MMODE_LOCK);
						_padStatus = STAT_INIT_DSHOCK;
					} else
						_padStatus = STAT_WAIT_READY;
					break;
				case STAT_INIT_DSHOCK:
					padEnterPressMode(_port, _slot);
					_padStatus = STAT_CHECK_ACT;
					break;
				case STAT_CHECK_ACT:
					_actuators = padInfoAct(_port, _slot, -1, 0);
					if (_actuators != 0)
						_padStatus = STAT_INIT_ACT;
					else {
						_isDualShock = false;
						_padStatus = STAT_WAIT_READY;
					}
					break;
				case STAT_INIT_ACT:
					char actAlign[6];
					actAlign[0] = 0;
					actAlign[1] = 1;
					actAlign[2] = actAlign[3] = actAlign[4] = actAlign[5] = 0xff;
					padSetActAlign(_port, _slot, actAlign);
					_padStatus = STAT_WAIT_READY;
					break;
				case STAT_WAIT_READY:
					_padStatus = STAT_OKAY;
					break;
			}
		} else {
			// check for timeout...
			if (_system->getMillis() - _padInitTime > 5000) {
				// still no pad, give up.
				if (padPortClose(_port, _slot) != 1)
					printf("WARNING: can't close port: %d/%d\n");
				printf("looking for pad, gave up and closed port\n");
				_padStatus = STAT_NONE;
			}
		}
	}
}

bool Ps2Pad::checkPadReady(int port, int slot, uint32 wait, uint32 *waitRes) {
	int state;
	for (uint32 cnt = 0; cnt < wait; cnt++) {
		state = padGetState(port, slot);
		if ((state == PAD_STATE_STABLE) || (state == PAD_STATE_FINDCTP1)) {
			if (waitRes)
				*waitRes = cnt;
			return true;
		}
	}
	return false;	
}

bool Ps2Pad::padAlive(void) {
	if ((_padStatus == STAT_OKAY) && checkPadReady(_port, _slot))
		return true;
	initPad();
	return false;
}

bool Ps2Pad::isDualShock(void) {
	return _isDualShock;
}

void Ps2Pad::readPad(uint16 *pbuttons, int16 *joyh, int16 *joyv) {
	if (padAlive()) {
		struct padButtonStatus buttons;
		padRead(_port, _slot, &buttons);
		*pbuttons = ~buttons.btns;
		if (_isDualShock) {
			*joyh = (int16)buttons.ljoy_h - 128;
			*joyv = (int16)buttons.ljoy_v - 128;
		} else
			*joyh = *joyv = 0;
	} else {
		*joyh = *joyv = 0;
		*pbuttons = 0;
	}
}




--- NEW FILE: ps2pad.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2001-2004 The ScummVM project
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/backends/ps2/ps2pad.h,v 1.1 2005/03/31 05:35:04 lavosspawn Exp $
 *
 */

#ifndef __PS2PAD_H__
#define __PS2PAD_H__

enum PadStatus {
	STAT_NONE,
	STAT_OPEN,
	STAT_DETECT,
	STAT_INIT_DSHOCK,
	STAT_CHECK_ACT,
	STAT_INIT_ACT,
	STAT_WAIT_READY,
	STAT_OKAY
};

#include "common/system.h"
#include <libpad.h>

#define PAD_DIR_MASK  (PAD_LEFT | PAD_DOWN | PAD_RIGHT | PAD_UP)
#define PAD_BUTTON_MASK (PAD_START | PAD_SELECT | PAD_SQUARE | PAD_CROSS | PAD_CIRCLE | PAD_TRIANGLE)

class OSystem_PS2;

class Ps2Pad {
public:
	Ps2Pad(OSystem_PS2 *system);
	bool padAlive(void);
	bool isDualShock(void);
	void readPad(uint16 *pbuttons, int16 *joyh, int16 *joyv);
private:
	void initPad(void);
	bool checkPadReady(int port, int slot, uint32 wait = 1, uint32 *waitRes = NULL);

	OSystem_PS2 *_system;
	int _port, _slot;

	uint32 _padInitTime;
	PadStatus _padStatus;
	bool _isDualShock;
	uint8 *_padBuf;
	char _actuators;
};

#endif //__PS2PAD_H__


--- NEW FILE: savefile.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2002-2005 The ScummVM project
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/backends/ps2/savefile.cpp,v 1.1 2005/03/31 05:35:04 lavosspawn Exp $
 *
 */

#include "backends/ps2/savefile.h"
#include "backends/ps2/Gs2dScreen.h"

#include <tamtypes.h>
#include <kernel.h>
#include <sifrpc.h>
#include <loadfile.h>
#include <fileio.h>
#include <malloc.h>
#include <ucl/ucl.h>
#include "scummsys.h"

class StdioSaveFile : public SaveFile {
public:
	StdioSaveFile(const char *filename, bool saveOrLoad);
	virtual ~StdioSaveFile();
	virtual bool isOpen() const;
	virtual uint32 read(void *buf, uint32 cnt);
	virtual uint32 write(const void *buf, uint32 cnt);
private:
	FILE *_fh;
	bool _saving;
};

class UclSaveFile : public SaveFile {
public:
	UclSaveFile(const char *filename, bool saveOrLoad, Gs2dScreen *screen);
	virtual ~UclSaveFile();
	virtual bool isOpen() const;
	virtual uint32 read(void *buf, uint32 cnt);
	virtual uint32 write(const void *buf, uint32 cnt);
private:
	Gs2dScreen *_screen;
	FILE *_fh;
	bool _saving;
	uint8 *_buf;
	uint32 _bufSize, _bufPos;
};

#define ARRAY_ENTRIES	16
static mcTable mcDir[ARRAY_ENTRIES] __attribute__((aligned(64)));
static int     mcEntries;
static bool    mcNeedUpdate = true;

Ps2SaveFileManager::Ps2SaveFileManager(const char *path, SaveMode mode, Gs2dScreen *screen) {
	_screen = screen;
	if (mcInit(MC_TYPE_MC) < 0) {
		printf("Can't init libmc!\n");
		SleepThread();
	}
	
	if (path)
		strcpy(_savePath, path);
	else
		_savePath[0] = '\0';

	_mode = mode;
	if (mode == TO_HOST) {
		printf("saving to host:/\n");
	} else if (mode == TO_MC) {
		int mcType, mcFree, mcFormat, res;
		mcGetInfo(0, 0, &mcType, &mcFree, &mcFormat);
		mcSync(0, NULL, &res);
		if ((res == 0) || (res == -1)) // mc okay
			printf("MC okay, result = %d. Type %d, Free %d, Format %d\n", res, mcType, mcFree, mcFormat);
		else
			printf("MC failed, not present or not formatted, code %d\n", res);
	} else {
		printf("HDD not implemented yet\n");
		SleepThread();
	}

	checkMainDirectory();
}

Ps2SaveFileManager::~Ps2SaveFileManager(void) {
}

void Ps2SaveFileManager::checkMainDirectory(void) {
	// verify that the main directory (scummvm config + icon) exists
	int ret;
	mcGetDir(0, 0, "/ScummVM/*", 0, ARRAY_ENTRIES, mcDir);
	mcSync(0, NULL, &ret);
	printf("/ScummVM/* res = %d\n", ret);
	if (ret <= 0) { // assume directory doesn't exist
		printf("Dir doesn't exist\n");
		fioMkdir("mc0:ScummVM");
		FILE *outf = fopen("mc0:ScummVM/scummvm.icn", "wb");
		if (outf) {
			uint16 icoSize;
			uint16 *icoBuf = decompressIconData(&icoSize);
			fwrite(icoBuf, 2, icoSize, outf);
			fclose(outf);
			printf(".icn written\n");
			free(icoBuf);

			setupIcon("mc0:ScummVM/icon.sys", "scummvm.icn", "ScummVM", "Configuration");
		} else
			printf("unable to write icon data\n");
	}
}

SaveFile *Ps2SaveFileManager::openSavefile(const char *filename, bool saveOrLoad) {
	char *defaultExt = "SAVE";
	char nameBase[256];
	strcpy(nameBase, filename);
	char *ext = strchr(nameBase, '.');
	if (ext) {	
		*ext = '\0';
		ext++;
		if (!*ext)
			ext = defaultExt;
	} else
		ext = defaultExt;

	if (_mode == TO_HOST) {
		char hostName[256];
		sprintf(hostName, "%s%s", _savePath, filename);
		SaveFile *res = new StdioSaveFile(hostName, saveOrLoad);
		if (!res->isOpen()) {
			printf("unable to open savefile %s for %s\n", hostName, saveOrLoad ? "saving" : "loading");
			delete res;
			return NULL;
		}
		printf("Savefile %s opened for %s\n", hostName, saveOrLoad ? "saving" : "loading");
		return res;
	} else if (_mode == TO_MC) {
		_screen->wantAnim(true);
		int mcType, mcFree, mcFormat, mcResult;
		mcGetInfo(0, 0, &mcType, &mcFree, &mcFormat);
		mcSync(0, NULL, &mcResult);
		if (mcResult == -1) // memory card was exchanged
			mcNeedUpdate = true;
		else if (mcResult != 0) {
			printf("Memory card is not ready\n");
			return NULL;
		}

		char dirStr[256];
		sprintf(dirStr, "/ScummVM-%s/*", nameBase);
		if (saveOrLoad) { // saving
			mcGetDir(0, 0, dirStr, 0, ARRAY_ENTRIES, mcDir);
			mcSync(0, NULL, &mcEntries);
			mcNeedUpdate = true;
			if (mcEntries <= 0) { // directory is empty or doesn't exist.
				sprintf(dirStr, "mc0:ScummVM-%s", nameBase);
				printf("Creating directory %s\n", dirStr);
				if (mcEntries < 0) { // directory doesn't exist
					if (fioMkdir(dirStr) < 0) {
						printf("unable to create directory %s\n", dirStr);
						_screen->wantAnim(false);
						return NULL; // unable to create directory
					}
				}
				char icoSysDest[256], saveDesc[256];
				sprintf(icoSysDest, "%s/icon.sys", dirStr);
				strcpy(saveDesc, nameBase);
				if ((saveDesc[0] >= 'a') && (saveDesc[0] <= 'z'))
					saveDesc[0] += 'A' - 'a'; 
				setupIcon(icoSysDest, "../ScummVM/scummvm.icn", saveDesc, "Savegames");
			}
		} else {
			// scumm engine tries to open hundreds of files to search for savegames.
			if (mcNeedUpdate) {
				mcGetDir(0, 0, dirStr, 0, ARRAY_ENTRIES, mcDir);
				mcSync(0, NULL, &mcEntries);
				mcNeedUpdate = false;
			}
			bool fileExists = false;
			char searchName[32];
			sprintf(searchName, "%s.bin", ext);
			for (int cnt = 0; (cnt < mcEntries) && !fileExists; cnt++)
				if (strcmp(searchName, (char*)mcDir[cnt].name) == 0)
					fileExists = true;

			if (!fileExists) {
				_screen->wantAnim(false);
				return NULL;
			}
		}
		sprintf(dirStr, "mc0:ScummVM-%s/%s.bin", nameBase, ext);
		SaveFile *file = new UclSaveFile(dirStr, saveOrLoad, _screen);
		if (!file->isOpen()) {
			printf("unable to open savefile %s for %s\n", dirStr, saveOrLoad ? "saving" : "loading");
            delete file;
			_screen->wantAnim(false);
			return NULL;
		}
		return file;
	} else {
		printf("HDD not implemented yet\n");
		return NULL;
	}
}

void Ps2SaveFileManager::listSavefiles(const char * /* prefix */, bool *marks, int num) {
	memset(marks, true, num * sizeof(bool));
}

const char *Ps2SaveFileManager::getSavePath(void) const {
	return _savePath;
}

void Ps2SaveFileManager::setSavePath(const char *path) {
	strcpy(_savePath, path);
}

bool Ps2SaveFileManager::setupIcon(const char *dest, const char *ico, const char *descr1, const char *descr2) {
	mcIcon icon_sys;
	memset(&icon_sys, 0, sizeof(mcIcon));
	memcpy(icon_sys.head, "PS2D", 4);
	char title[256];
	sprintf(title, "%s\n%s", descr1, descr2);
	strcpy_sjis((short*)&(icon_sys.title), title);
	icon_sys.nlOffset = strlen(descr1) + 1;
	icon_sys.trans = 0x10;
	memcpy(icon_sys.bgCol, _bgcolor, sizeof(_bgcolor));
	memcpy(icon_sys.lightDir, _lightdir, sizeof(_lightdir));
	memcpy(icon_sys.lightCol, _lightcol, sizeof(_lightcol));
	memcpy(icon_sys.lightAmbient, _ambient, sizeof(_ambient));
	strcpy((char*)icon_sys.view, ico);
	strcpy((char*)icon_sys.copy, ico);
	strcpy((char*)icon_sys.del, ico);

	FILE *outf = fopen(dest, "wb");
	if (outf) {
		fwrite(&icon_sys, 1, sizeof(icon_sys), outf);
		fclose(outf);
		return true;
	} else
		return false;
}

uint16 *Ps2SaveFileManager::decompressIconData(uint16 *size) {
	uint16 inPos = 1;
	uint16 *rleData = (uint16*)_rleIcoData;
	uint16 resSize = rleData[0];
	uint16 *resData = (uint16*)malloc(resSize * sizeof(uint16*));
	uint16 outPos = 0;
	while (outPos < resSize) {
		uint16 len = rleData[inPos++];
		while (len--)
			resData[outPos++] = 0x7FFF;
		len = rleData[inPos++];
		while (len--)
			resData[outPos++] = rleData[inPos++];
	}
	*size = resSize;
	assert(outPos == resSize);
	return resData;
}


StdioSaveFile::StdioSaveFile(const char *filename, bool saveOrLoad)  { 
	_fh = ::fopen(filename, (saveOrLoad? "wb" : "rb")); 
	_saving = saveOrLoad;
}

StdioSaveFile::~StdioSaveFile(void)  { 
	if (_fh)
		::fclose(_fh);
}

bool StdioSaveFile::isOpen(void) const {
	return _fh != NULL;
}

uint32 StdioSaveFile::read(void *buf, uint32 cnt) {
	assert(!_saving);
	return ::fread(buf, 1, cnt, _fh);
}

uint32 StdioSaveFile::write(const void *buf, uint32 cnt) {
	assert(_saving);
	return ::fwrite(buf, 1, cnt, _fh);
}

UclSaveFile::UclSaveFile(const char *filename, bool saveOrLoad, Gs2dScreen *screen) {
	_fh = ::fopen(filename, (saveOrLoad? "wb" : "rb")); 
	_saving = saveOrLoad;
	_bufPos = 0;
	_screen = screen;
	if (_fh) {
		if (_saving) {
			_buf = (uint8*)malloc(65536);
			_bufSize = 65536;
		} else {
			uint32 srcSize = ::fsize(_fh);
			uint8 *srcBuf = (uint8*)malloc(srcSize);
			int res = ::fread(srcBuf, 1, srcSize, _fh);
			assert(res == srcSize);

			uint32 resLen = _bufSize = *(uint32*)srcBuf;
			_buf = (uint8*)malloc(_bufSize + 2048);
			res = ucl_nrv2e_decompress_8(srcBuf + 4, srcSize - 4, _buf, &resLen, NULL);
			if ((res < 0) || (resLen != _bufSize)) {
				printf("Unable to decompress file %s (%d -> %d) error code %d\n", filename, srcSize, _bufSize, res);
                free(_buf);
				_buf = NULL;
				_bufSize = 0;
			}
			::fclose(_fh);
			_fh = NULL;
			free(srcBuf);
		}
	} else {
		printf("Savefile %s doesn't exist\n", filename);
		_buf = NULL;
	}
}

UclSaveFile::~UclSaveFile(void) {
	if (_saving) {
		uint8 *compBuf = (uint8*)malloc(_bufPos * 2);
		uint32 compSize = _bufPos * 2;
		int res = ucl_nrv2e_99_compress(_buf, _bufPos, compBuf, &compSize, NULL, 10, NULL, NULL);
		if (res >= 0) {
			fwrite(&_bufPos, 1, 4, _fh);
			fwrite(compBuf, 1, compSize, _fh);
		} else {
            printf("unable to compress %d bytes of savedata, errorcode %d\n", _bufPos, res);
		}
        free(compBuf);
	}
	if (_buf)
		free(_buf);
	if (_fh)
		::fclose(_fh);
	_screen->wantAnim(false);
}

bool UclSaveFile::isOpen(void) const {
	return (_buf != NULL);
}

uint32 UclSaveFile::read(void *buf, uint32 cnt) {
	assert(!_saving);
	uint32 numBytes = (cnt > _bufSize - _bufPos) ? (_bufSize - _bufPos) : cnt;
	memcpy(buf, _buf + _bufPos, numBytes);
	_bufPos += numBytes;
	return numBytes;
}

uint32 UclSaveFile::write(const void *buf, uint32 cnt) {
	assert(_saving);
	if (_bufSize - _bufPos < cnt) {
		_bufSize += (cnt > 65536) ? cnt : 65536;
		_buf = (uint8*)realloc(_buf, _bufSize);
	}
	memcpy(_buf + _bufPos, buf, cnt);
	_bufPos += cnt;
	return cnt;
}


--- NEW FILE: savefile.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2002-2005 The ScummVM project
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/backends/ps2/savefile.h,v 1.1 2005/03/31 05:35:04 lavosspawn Exp $
 *
 */

#ifndef __PS2_SAVEFILE__
#define __PS2_SAVEFILE__

#include "common/savefile.h"
#include <libmc.h>

enum SaveMode {
	TO_HOST = 0,
	TO_MC,
	TO_HDD
};

class Gs2dScreen;

class Ps2SaveFileManager : public SaveFileManager {
public:
	Ps2SaveFileManager(const char *path, SaveMode mode, Gs2dScreen *screen);
	virtual ~Ps2SaveFileManager();

	virtual SaveFile *openSavefile(const char *filename, bool saveOrLoad);
	virtual void listSavefiles(const char * /* prefix */, bool *marks, int num);

	/** Get the path to the save game directory. */
	virtual const char *getSavePath() const;

	void setSavePath(const char *path);
	static bool setupIcon(const char *dest, const char *ico, const char *descr1, const char *descr2);

	void checkMainDirectory(void);
private:
	uint16 *decompressIconData(uint16 *size);

	Gs2dScreen *_screen;

	static const uint8 _rleIcoData[14018];
	SaveMode _mode;
	char _savePath[256];

	static const iconIVECTOR _bgcolor[4];
	static const iconFVECTOR _lightdir[3], _lightcol[3], _ambient;
};

#endif // __PS2_SAVEFILE__

--- NEW FILE: sdlkeys.h ---
/* copied from SDK_keysym.h */

#ifndef __SDLKEYS_H__
#define __SDLKEYS_H__

enum SdlKeyCodes {
	SDLK_UNKNOWN		= 0,
	SDLK_FIRST		= 0,
	SDLK_BACKSPACE		= 8,
	SDLK_TAB		= 9,
	SDLK_CLEAR		= 12,
	SDLK_RETURN		= 13,
	SDLK_PAUSE		= 19,
	SDLK_ESCAPE		= 27,
	SDLK_SPACE		= 32,
	SDLK_EXCLAIM		= 33,
	SDLK_QUOTEDBL		= 34,
	SDLK_HASH		= 35,
	SDLK_DOLLAR		= 36,
	SDLK_AMPERSAND		= 38,
	SDLK_QUOTE		= 39,
	SDLK_LEFTPAREN		= 40,
	SDLK_RIGHTPAREN		= 41,
	SDLK_ASTERISK		= 42,
	SDLK_PLUS		= 43,
	SDLK_COMMA		= 44,
	SDLK_MINUS		= 45,
	SDLK_PERIOD		= 46,
	SDLK_SLASH		= 47,
	SDLK_0			= 48,
	SDLK_1			= 49,
	SDLK_2			= 50,
	SDLK_3			= 51,
	SDLK_4			= 52,
	SDLK_5			= 53,
	SDLK_6			= 54,
	SDLK_7			= 55,
	SDLK_8			= 56,
	SDLK_9			= 57,
	SDLK_COLON		= 58,
	SDLK_SEMICOLON		= 59,
	SDLK_LESS		= 60,
	SDLK_EQUALS		= 61,
	SDLK_GREATER		= 62,
	SDLK_QUESTION		= 63,
	SDLK_AT			= 64,
	/* 
	   Skip uppercase letters
	 */
	SDLK_LEFTBRACKET	= 91,
	SDLK_BACKSLASH		= 92,
	SDLK_RIGHTBRACKET	= 93,
	SDLK_CARET		= 94,
	SDLK_UNDERSCORE		= 95,
	SDLK_BACKQUOTE		= 96,
	SDLK_a			= 97,
	SDLK_b			= 98,
	SDLK_c			= 99,
	SDLK_d			= 100,
	SDLK_e			= 101,
	SDLK_f			= 102,
	SDLK_g			= 103,
	SDLK_h			= 104,
	SDLK_i			= 105,
	SDLK_j			= 106,
	SDLK_k			= 107,
	SDLK_l			= 108,
	SDLK_m			= 109,
	SDLK_n			= 110,
	SDLK_o			= 111,
	SDLK_p			= 112,
	SDLK_q			= 113,
	SDLK_r			= 114,
	SDLK_s			= 115,
	SDLK_t			= 116,
	SDLK_u			= 117,
	SDLK_v			= 118,
	SDLK_w			= 119,
	SDLK_x			= 120,
	SDLK_y			= 121,
	SDLK_z			= 122,
	SDLK_DELETE		= 127,
	/* End of ASCII mapped keysyms */

	/* International keyboard syms */
	SDLK_WORLD_0		= 160,		/* 0xA0 */
	SDLK_WORLD_1		= 161,
	SDLK_WORLD_2		= 162,
	SDLK_WORLD_3		= 163,
	SDLK_WORLD_4		= 164,
	SDLK_WORLD_5		= 165,
	SDLK_WORLD_6		= 166,
	SDLK_WORLD_7		= 167,
	SDLK_WORLD_8		= 168,
	SDLK_WORLD_9		= 169,
	SDLK_WORLD_10		= 170,
	SDLK_WORLD_11		= 171,
	SDLK_WORLD_12		= 172,
	SDLK_WORLD_13		= 173,
	SDLK_WORLD_14		= 174,
	SDLK_WORLD_15		= 175,
	SDLK_WORLD_16		= 176,
	SDLK_WORLD_17		= 177,
	SDLK_WORLD_18		= 178,
	SDLK_WORLD_19		= 179,
	SDLK_WORLD_20		= 180,
	SDLK_WORLD_21		= 181,
	SDLK_WORLD_22		= 182,
	SDLK_WORLD_23		= 183,
	SDLK_WORLD_24		= 184,
	SDLK_WORLD_25		= 185,
	SDLK_WORLD_26		= 186,
	SDLK_WORLD_27		= 187,
	SDLK_WORLD_28		= 188,
	SDLK_WORLD_29		= 189,
	SDLK_WORLD_30		= 190,
	SDLK_WORLD_31		= 191,
	SDLK_WORLD_32		= 192,
	SDLK_WORLD_33		= 193,
	SDLK_WORLD_34		= 194,
	SDLK_WORLD_35		= 195,
	SDLK_WORLD_36		= 196,
	SDLK_WORLD_37		= 197,
	SDLK_WORLD_38		= 198,
	SDLK_WORLD_39		= 199,
	SDLK_WORLD_40		= 200,
	SDLK_WORLD_41		= 201,
	SDLK_WORLD_42		= 202,
	SDLK_WORLD_43		= 203,
	SDLK_WORLD_44		= 204,
	SDLK_WORLD_45		= 205,
	SDLK_WORLD_46		= 206,
	SDLK_WORLD_47		= 207,
	SDLK_WORLD_48		= 208,
	SDLK_WORLD_49		= 209,
	SDLK_WORLD_50		= 210,
	SDLK_WORLD_51		= 211,
	SDLK_WORLD_52		= 212,
	SDLK_WORLD_53		= 213,
	SDLK_WORLD_54		= 214,
	SDLK_WORLD_55		= 215,
	SDLK_WORLD_56		= 216,
	SDLK_WORLD_57		= 217,
	SDLK_WORLD_58		= 218,
	SDLK_WORLD_59		= 219,
	SDLK_WORLD_60		= 220,
	SDLK_WORLD_61		= 221,
	SDLK_WORLD_62		= 222,
	SDLK_WORLD_63		= 223,
	SDLK_WORLD_64		= 224,
	SDLK_WORLD_65		= 225,
	SDLK_WORLD_66		= 226,
	SDLK_WORLD_67		= 227,
	SDLK_WORLD_68		= 228,
	SDLK_WORLD_69		= 229,
	SDLK_WORLD_70		= 230,
	SDLK_WORLD_71		= 231,
	SDLK_WORLD_72		= 232,
	SDLK_WORLD_73		= 233,
	SDLK_WORLD_74		= 234,
	SDLK_WORLD_75		= 235,
	SDLK_WORLD_76		= 236,
	SDLK_WORLD_77		= 237,
	SDLK_WORLD_78		= 238,
	SDLK_WORLD_79		= 239,
	SDLK_WORLD_80		= 240,
	SDLK_WORLD_81		= 241,
	SDLK_WORLD_82		= 242,
	SDLK_WORLD_83		= 243,
	SDLK_WORLD_84		= 244,
	SDLK_WORLD_85		= 245,
	SDLK_WORLD_86		= 246,
	SDLK_WORLD_87		= 247,
	SDLK_WORLD_88		= 248,
	SDLK_WORLD_89		= 249,
	SDLK_WORLD_90		= 250,
	SDLK_WORLD_91		= 251,
	SDLK_WORLD_92		= 252,
	SDLK_WORLD_93		= 253,
	SDLK_WORLD_94		= 254,
	SDLK_WORLD_95		= 255,		/* 0xFF */

	/* Numeric keypad */
	SDLK_KP0		= 256,
	SDLK_KP1		= 257,
	SDLK_KP2		= 258,
	SDLK_KP3		= 259,
	SDLK_KP4		= 260,
	SDLK_KP5		= 261,
	SDLK_KP6		= 262,
	SDLK_KP7		= 263,
	SDLK_KP8		= 264,
	SDLK_KP9		= 265,
	SDLK_KP_PERIOD		= 266,
	SDLK_KP_DIVIDE		= 267,
	SDLK_KP_MULTIPLY	= 268,
	SDLK_KP_MINUS		= 269,
	SDLK_KP_PLUS		= 270,
	SDLK_KP_ENTER		= 271,
	SDLK_KP_EQUALS		= 272,

	/* Arrows + Home/End pad */
	SDLK_UP			= 273,
	SDLK_DOWN		= 274,
	SDLK_RIGHT		= 275,
	SDLK_LEFT		= 276,
	SDLK_INSERT		= 277,
	SDLK_HOME		= 278,
	SDLK_END		= 279,
	SDLK_PAGEUP		= 280,
	SDLK_PAGEDOWN		= 281,

	/* Function keys */
	SDLK_F1			= 282,
	SDLK_F2			= 283,
	SDLK_F3			= 284,
	SDLK_F4			= 285,
	SDLK_F5			= 286,
	SDLK_F6			= 287,
	SDLK_F7			= 288,
	SDLK_F8			= 289,
	SDLK_F9			= 290,
	SDLK_F10		= 291,
	SDLK_F11		= 292,
	SDLK_F12		= 293,
	SDLK_F13		= 294,
	SDLK_F14		= 295,
	SDLK_F15		= 296,

	/* Key state modifier keys */
	SDLK_NUMLOCK		= 300,
	SDLK_CAPSLOCK		= 301,
	SDLK_SCROLLOCK		= 302,
	SDLK_RSHIFT		= 303,
	SDLK_LSHIFT		= 304,
	SDLK_RCTRL		= 305,
	SDLK_LCTRL		= 306,
	SDLK_RALT		= 307,
	SDLK_LALT		= 308,
	SDLK_RMETA		= 309,
	SDLK_LMETA		= 310,
	SDLK_LSUPER		= 311,		/* Left "Windows" key */
	SDLK_RSUPER		= 312,		/* Right "Windows" key */
	SDLK_MODE		= 313,		/* "Alt Gr" key */
	SDLK_COMPOSE		= 314,		/* Multi-key compose key */

	/* Miscellaneous function keys */
	SDLK_HELP		= 315,
	SDLK_PRINT		= 316,
	SDLK_SYSREQ		= 317,
	SDLK_BREAK		= 318,
	SDLK_MENU		= 319,
	SDLK_POWER		= 320,		/* Power Macintosh power key */
	SDLK_EURO		= 321,		/* Some european keyboards */
	SDLK_UNDO		= 322,		/* Atari keyboard has Undo */

	/* Add any other keys here */

	SDLK_LAST
};

#endif



--- NEW FILE: sjpcm.h ---
/*
    -----------------------------------------------------------------------
    sjpcm.h - SjPCM EE-side prototypes. (c) Nick Van Veen (aka Sjeep), 2002
	-----------------------------------------------------------------------

    This library is free software; you can redistribute it and/or
	modify it under the terms of the GNU Lesser General Public
	License as published by the Free Software Foundation; either
	version 2.1 of the License, or (at your option) any later version.

	This library is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
	Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public
	License along with this library; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

*/

#ifndef _SJPCM_H
#define _SJPCM_H

#ifdef __cplusplus
extern "C" {
#endif

#define	SJPCM_IRX		0xB0110C5
#define SJPCM_PUTS		0x01
#define	SJPCM_INIT		0x02
#define SJPCM_PLAY		0x03
#define SJPCM_PAUSE		0x04
#define SJPCM_SETVOL	0x05
#define SJPCM_ENQUEUE	0x06
#define SJPCM_CLEARBUFF	0x07
#define SJPCM_QUIT		0x08
#define SJPCM_GETAVAIL  0x09
#define SJPCM_GETBUFFD  0x10

void SjPCM_Puts(char *format, ...);
int SjPCM_Init(int sync);
void SjPCM_Enqueue(short *left, short *right, int size, int wait);
void SjPCM_Play();
void SjPCM_Pause();
void SjPCM_Setvol(unsigned int volume);
void SjPCM_Clearbuff();
int SjPCM_Available();
int SjPCM_Buffered();
void SjPCM_Quit();

#ifdef __cplusplus
}
#endif

#endif // _SJPCM_H

--- NEW FILE: sysdefs.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2001-2004 The ScummVM project
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/backends/ps2/sysdefs.h,v 1.1 2005/03/31 05:35:04 lavosspawn Exp $
 *
 */

#ifndef __SYSDEFS_H__
#define __SYSDEFS_H__

typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
typedef unsigned long uint64;
typedef signed char int8;
typedef signed short int16;
typedef signed int int32;
typedef signed long int64;

enum Interrupts {
	INT_VBLANK_START = 2,
	INT_TIMER0 = 9
};

// dma 2 registers
#define D2_CHCR (*(volatile uint32*)0x1000A000)
#define D2_QWC  (*(volatile uint32*)0x1000A020) // D2_SIZE
#define D2_TADR (*(volatile uint32*)0x1000A030) // D2_TAG
#define D2_MADR (*(volatile uint32*)0x1000A010)
#define D2_ASR1 (*(volatile uint32*)0x1000A050)
#define D2_ASR0 (*(volatile uint32*)0x1000A040)

#define D_CTRL  (*(volatile uint32*)0x1000E000)
#define D_STAT  (*(volatile uint32*)0x1000E010)
#define D_PCR   (*(volatile uint32*)0x1000E020)
#define D_SQWC  (*(volatile uint32*)0x1000E030)
#define D_RBSR  (*(volatile uint32*)0x1000E040)
#define D_RBOR  (*(volatile uint32*)0x1000E050)
#define D_STADR (*(volatile uint32*)0x1000E060)

#define CIM2 (1 << 18)
#define CIS2 (1 << 2)


// timer 0 registers
#define T0_COUNT (*(volatile uint32*)0x10000000)
#define T0_MODE  (*(volatile uint32*)0x10000010)
#define T0_COMP  (*(volatile uint32*)0x10000020)
#define T0_HOLD  (*(volatile uint32*)0x10000030)

#define TIMER_MODE(clks, gate, gates, gatem, zeroret, cue, cmpe, ovfe, equf, ovff) \
	((clks) | ((gate) << 2) | ((gates) << 3) | ((gatem) << 4) | ((zeroret) << 6) | \
	((cue) << 7) | ((cmpe) << 8) | ((ovfe) << 9) | ((equf) << 10) | ((ovff) << 11))

#endif // __SYSDEFS_H__

--- NEW FILE: systemps2.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2001-2004 The ScummVM project
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/backends/ps2/systemps2.cpp,v 1.1 2005/03/31 05:35:04 lavosspawn Exp $
 *
 */

#include "stdafx.h"
#include <kernel.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sifrpc.h>
#include <loadfile.h>
#include <malloc.h>
#include <assert.h>
#include <fileio.h>
#include <iopcontrol.h>
#include <iopheap.h>
#include "scummsys.h"
#include "../intern.h"
#include "base/engine.h"
#include "backends/ps2/systemps2.h"
#include "backends/ps2/Gs2dScreen.h"
#include "backends/ps2/ps2input.h"
#include "sjpcm.h"
#include <cdvd_rpc.h>
#include "backends/ps2/savefile.h"
#include "common/file.h"
#include "backends/ps2/sysdefs.h"
#include <libmc.h>
#include "backends/ps2/cd.h"
#include <sio.h>

#define TIMER_STACK_SIZE (1024 * 32)
#define SOUND_STACK_SIZE (1024 * 32)
#define SMP_PER_BLOCK 800
#define FROM_BCD(a) ((a >> 4) * 10 + (a & 0xF))

#define CHECK_STACK_USAGE

#ifdef USE_PS2LINK
#define IRX_PREFIX "host:"
#define IRX_SUFFIX
#else
#define IRX_PREFIX "cdrom0:\\"
#define IRX_SUFFIX ";1"
#endif

static volatile int32 g_TimerThreadSema = -1;
static volatile int32 g_SoundThreadSema = -1;
static volatile uint64 msecCount = 0;

extern void NORETURN CDECL error(const char *s, ...);

static OSystem_PS2 *g_systemPs2 = NULL;

void readRtcTime(void);

int gBitFormat = 555;

void sioprintf(const char *zFormat, ...) {
	va_list ap;
	char resStr[2048];

	va_start(ap,zFormat);
	int res = vsnprintf(resStr, 2048, zFormat, ap);
	va_end(ap);

	sio_puts(resStr);
}

OSystem *OSystem_PS2_create(void) {
	if (!g_systemPs2)
		g_systemPs2 = new OSystem_PS2();	
	return g_systemPs2;
}

extern "C" int scummvm_main(int argc, char *argv[]);

extern "C" int main(int argc, char *argv[]) {
	SifInitRpc(0);
#ifdef USE_PS2LINK
	fioInit();
#else // reset the IOP if this is a CD build
	cdvdInit(CDVD_EXIT);
	cdvdExit();
	fioExit();
	SifExitIopHeap();
	SifLoadFileExit();
	SifExitRpc();
	sio_puts("Resetting IOP.");
	SifIopReset("rom0:UDNL rom0:EELOADCNF",0);
	while (!SifIopSync())
		;
	sio_puts("IOP synced.");
	SifInitRpc(0);
	fioInit();
	SifLoadFileInit();
    cdvdInit(CDVD_INIT_NOWAIT);
#endif

	ee_thread_t thisThread;
	int tid = GetThreadId();
	ReferThreadStatus(tid, &thisThread);

	sioprintf("Thread Start Priority = %d\n", thisThread.current_priority);
	if ((thisThread.current_priority < 5) || (thisThread.current_priority > 80)) {
		/* Depending on the way ScummVM is run, we may get here with different
		   thread priorities.
		   The PS2 BIOS executes it with priority = 0, ps2link uses priority 64.
		   Don't know about NapLink, etc.
		   The priority doesn't matter too much, but we need to be at least at prio 3,
		   so we can have the timer thread run at prio 2 and the sound thread at prio 1	*/
		sioprintf("Changing thread priority");
		int res = ChangeThreadPriority(tid, 20);
		sioprintf("Result = %d", res);
	}

	sioprintf("Creating system");
	/* The OSystem has to be created before we enter ScummVM's main.
	   It sets up the memory card, etc. */
	OSystem_PS2_create();

	sioprintf("init done. starting ScummVM.");
	return scummvm_main(argc, argv);
}

s32 timerInterruptHandler(s32 cause) {
	msecCount += 10;
	T0_MODE = 0xDC2; // same value as in initialization.

	iSignalSema(g_SoundThreadSema);
	iSignalSema(g_TimerThreadSema);
	return 0;
}

void systemTimerThread(OSystem_PS2 *system) {
	system->timerThread();
}

void systemSoundThread(OSystem_PS2 *system) {
	system->soundThread();
}

OSystem_PS2::OSystem_PS2(void) {
	sioprintf("OSystem_PS2 constructor\n");

	_soundStack = _timerStack = NULL;
	_scummTimerProc = NULL;
	_scummSoundProc = NULL;
	_scummSoundParam = NULL;

	_screen = new Gs2dScreen(320, 200, TV_DONT_CARE);
	_width = 320; 
	_height = 200;

	sioprintf("Initializing timer\n");
	initTimer();

	_screen->wantAnim(true);

	if (!loadModules()) {
		sioprintf("ERROR: Can't load modules");
		printf("ERROR: Can't load modules\n");
		_screen->wantAnim(false);
		SleepThread();
		// Todo: handle this correctly...
	}
	sioprintf("Modules: UsbMouse %sloaded, UsbKbd %sloaded, Hdd %sloaded.", _useMouse ? "" : "not ", _useKbd ? "" : "not ", _useHdd ? "" : "not ");

	sioprintf("Initializing SjPCM");
	if (SjPCM_Init(0) < 0)
		sioprintf("SjPCM Bind failed");
	
	sioprintf("Initializing LibCDVD.");
	int res = CDVD_Init();
	sioprintf("result = %d\n", res);

	_timerTid = _soundTid = -1;
	_mouseVisible = false;

	sioprintf("reading RTC");
	readRtcTime();

	sioprintf("Setting non-blocking fio");
	fioSetBlockMode(FIO_NOWAIT); // asynchronous file i/o
	
	sioprintf("Starting SavefileManager");
	_saveManager = new Ps2SaveFileManager(NULL, TO_MC, _screen);

	_soundBuf = (int16*)malloc(SMP_PER_BLOCK * 2 * sizeof(int16));
	_soundBuf2 = (int16*)malloc(SMP_PER_BLOCK * sizeof(int16));

	sioprintf("Initializing ps2Input");
	_input = new Ps2Input(this, _useMouse, _useKbd);

	sio_puts("OSystem_PS2 constructor done\n");
	_screen->wantAnim(false);
}

OSystem_PS2::~OSystem_PS2(void) {
}

void OSystem_PS2::initTimer(void) {
	// this has to be set before the timer interrupt handler gets called
	g_systemPs2 = this;

	// first setup the two threads that get activated by the timer:
	// the timerthread and the soundthread
	ee_sema_t threadSema;
	threadSema.init_count = 0;
	threadSema.max_count = 255;
	g_TimerThreadSema = CreateSema(&threadSema);
	g_SoundThreadSema = CreateSema(&threadSema);
	assert((g_TimerThreadSema >= 0) && (g_SoundThreadSema >= 0));

	ee_thread_t timerThread, soundThread, thisThread;
	ReferThreadStatus(GetThreadId(), &thisThread);

	_timerStack = (uint8*)malloc(TIMER_STACK_SIZE);
	memset(_timerStack, 0xE7, TIMER_STACK_SIZE);
	_soundStack = (uint8*)malloc(SOUND_STACK_SIZE);
	memset(_soundStack, 0xE7, SOUND_STACK_SIZE);

	// give timer thread a higher priority than main thread
	timerThread.initial_priority = thisThread.current_priority - 1;
	timerThread.stack            = _timerStack;
	timerThread.stack_size       = TIMER_STACK_SIZE;
	timerThread.func             = (void *)systemTimerThread;
	//timerThread.gp_reg         = _gp; // _gp is always NULL.. broken linkfile?
	asm("move %0, $gp\n": "=r"(timerThread.gp_reg));

	// soundthread's priority is higher than main- and timerthread
	soundThread.initial_priority = thisThread.current_priority - 2;
	soundThread.stack            = _soundStack;
	soundThread.stack_size       = SOUND_STACK_SIZE;
	soundThread.func             = (void *)systemSoundThread;
	asm("move %0, $gp\n": "=r"(soundThread.gp_reg));

	_timerTid = CreateThread(&timerThread);
	_soundTid = CreateThread(&soundThread);

	assert((_timerTid >= 0) && (_soundTid >= 0));

	StartThread(_timerTid, this);
	StartThread(_soundTid, this);

	// threads done, start the interrupt handler
	AddIntcHandler( INT_TIMER0, timerInterruptHandler, 0); // 0=first handler, 9 = cause = timer0
	EnableIntc(INT_TIMER0);
	T0_HOLD = 0;
	T0_COUNT = 0;
	T0_COMP = 5859; // (busclock / 256) / 5859 = ~ 100.0064
	T0_MODE = TIMER_MODE( 2, 0, 0, 0, 1, 1, 1, 0, 1, 1);
}

void OSystem_PS2::timerThread(void) {
	while (1) {
		WaitSema(g_TimerThreadSema);
		if (_scummTimerProc)
			_scummTimerProc(0);
		_screen->timerTick();
	}
}

void OSystem_PS2::soundThread(void) {
	ee_sema_t soundSema;
	soundSema.init_count = 1;
	soundSema.max_count = 1;
	_soundSema = CreateSema(&soundSema);
	assert(_soundSema >= 0);
	while (1) {
		WaitSema(g_SoundThreadSema);
		
		WaitSema(_soundSema);
		if (_scummSoundProc) {
			while (SjPCM_Buffered() <= 4 * SMP_PER_BLOCK) {
				// call sound mixer
				_scummSoundProc(_scummSoundParam, (uint8*)_soundBuf, SMP_PER_BLOCK * 2 * sizeof(int16));
				// split data into 2 buffers, L and R
				_soundBuf2[0] = _soundBuf[1];
				for (uint32 cnt = 1; cnt < SMP_PER_BLOCK; cnt++) {
					_soundBuf[cnt]  = _soundBuf[cnt << 1];
					_soundBuf2[cnt] = _soundBuf[(cnt << 1) | 1];
				}
				// and feed it into the SPU
				SjPCM_Enqueue((short int*)_soundBuf, (short int*)_soundBuf2, SMP_PER_BLOCK, 1);
			}
		}
		SignalSema(_soundSema);
	}
}

bool OSystem_PS2::loadModules(void) {

	_useHdd = _useMouse = _useKbd = false;

	int res;
	if ((res = SifLoadModule("rom0:SIO2MAN", 0, NULL)) < 0)
		sioprintf("Cannot load module: SIO2MAN (%d)\n", res);
	else if ((res = SifLoadModule("rom0:MCMAN", 0, NULL)) < 0)
		sioprintf("Cannot load module: MCMAN (%d)\n", res);
	else if ((res = SifLoadModule("rom0:MCSERV", 0, NULL)) < 0)
		sioprintf("Cannot load module: MCSERV (%d)\n", res);
	else if ((res = SifLoadModule("rom0:PADMAN", 0, NULL)) < 0)
		sioprintf("Cannot load module: PADMAN (%d)\n", res);
	else if ((res = SifLoadModule("rom0:LIBSD", 0, NULL)) < 0)
		sioprintf("Cannot load module: LIBSD (%d)\n", res);
	else if ((res = SifLoadModule(IRX_PREFIX "CDVD.IRX" IRX_SUFFIX, 0, NULL)) < 0)
		sioprintf("Cannot load module CDVD.IRX (%d)\n", res);
	else if ((res = SifLoadModule(IRX_PREFIX "SJPCM.IRX" IRX_SUFFIX, 0, NULL)) < 0)
		sioprintf("Cannot load module: SJPCM.IRX (%d)\n", res);
	else {
		sioprintf("modules loaded\n");
		if ((res = SifLoadModule(IRX_PREFIX "USBD.IRX" IRX_SUFFIX, 0, NULL)) < 0)
			sioprintf("Cannot load module: USBD.IRX (%d)\n", res);
#ifndef USE_PS2LINK
		else if ((res = SifLoadModule(IRX_PREFIX "IOMANX.IRX" IRX_SUFFIX, 0, NULL)) < 0)
			sioprintf("Cannot load module: IOMANX.IRX (%d)\n", res);
#endif
		else {
			if ((res = SifLoadModule(IRX_PREFIX "PS2MOUSE.IRX" IRX_SUFFIX, 0, NULL)) < 0)
				sioprintf("Cannot load module: PS2MOUSE.IRX (%d)\n", res);
			else
				_useMouse = true;
			if ((res = SifLoadModule(IRX_PREFIX "PS2KBD.IRX" IRX_SUFFIX, 0, NULL)) < 0)
				sioprintf("Cannot load module: PS2KBD.IRX (%d)\n", res);
			else
				_useKbd = true;
		}
		return true;		
	}
	return false;
}

void OSystem_PS2::initSize(uint width, uint height, int overscale) {
	printf("initializing new size: (%d/%d)...", width, height);
	_screen->newScreenSize(width, height);
	_width = width;
	_height = height;
	_screen->setMouseXy(width / 2, height / 2);
	_input->newRange(0, 0, width - 1, height - 1);
	_input->warpTo(width / 2, height / 2);

	_oldMouseX = width / 2;
	_oldMouseY = height / 2;
	printf("done\n");
}

void OSystem_PS2::setPalette(const byte *colors, uint start, uint num) {
	_screen->setPalette((const uint32*)colors, (uint8)start, (uint16)num);
}

void OSystem_PS2::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) {
	_screen->copyScreenRect((const uint8*)buf, (uint16)pitch, (uint16)x, (uint16)y, (uint16)w, (uint16)h);
}

void OSystem_PS2::updateScreen(void) {
	_screen->updateScreen();	
}

uint32 OSystem_PS2::getMillis(void) {
	return (uint32)msecCount;
}

void OSystem_PS2::delayMillis(uint msecs) {
	uint64 endTime = msecCount + msecs;

	while (endTime > msecCount) {
		// idle        
	}
}

void OSystem_PS2::setTimerCallback(OSystem::TimerProc callback, int interval) {
	if (callback && (interval != 10))
		sioprintf("unhandled timer interval: %d\n", interval);
	_scummTimerProc = callback;
}

int OSystem_PS2::getOutputSampleRate(void) const {
	return 48000;
}

bool OSystem_PS2::setSoundCallback(SoundProc proc, void *param) {
	assert(proc != NULL);

	WaitSema(_soundSema);
    _scummSoundProc = proc;
	_scummSoundParam = param;
	SjPCM_Play();
	SignalSema(_soundSema);
	return true;
}

void OSystem_PS2::clearSoundCallback(void) {
	WaitSema(_soundSema);
	_scummSoundProc = NULL;
	_scummSoundParam = NULL;
	SjPCM_Pause();
	SignalSema(_soundSema);
}

SaveFileManager *OSystem_PS2::getSavefileManager(void) {
	return _saveManager;
}

OSystem::MutexRef OSystem_PS2::createMutex(void) {
	ee_sema_t newSema;
	newSema.init_count = 1;
	newSema.max_count = 1;
	int resSema = CreateSema(&newSema);
	if (resSema < 0)
		printf("createMutex: unable to create Semaphore.\n");
	return (MutexRef)resSema;
}

void OSystem_PS2::lockMutex(MutexRef mutex) {
	WaitSema((int)mutex);
}

void OSystem_PS2::unlockMutex(MutexRef mutex) {
	SignalSema((int)mutex);
}

void OSystem_PS2::deleteMutex(MutexRef mutex) {
	DeleteSema((int)mutex);
}

void OSystem_PS2::setShakePos(int shakeOffset) {
	_screen->setShakePos(shakeOffset);
}

bool OSystem_PS2::showMouse(bool visible) {
	bool retVal = _mouseVisible;
	_screen->showMouse(visible);
	_mouseVisible = visible;
	return retVal;
}

void OSystem_PS2::warpMouse(int x, int y) {
	_input->warpTo((uint16)x, (uint16)y);
	_screen->setMouseXy(x, y);
}

void OSystem_PS2::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, byte keycolor, int cursorTargetScale) {
	_screen->setMouseOverlay(buf, w, h, hotspot_x, hotspot_y, keycolor);
}

bool OSystem_PS2::openCD(int drive) {
	return false;
}

bool OSystem_PS2::pollCD(void) {
	return false;
}

void OSystem_PS2::playCD(int track, int num_loops, int start_frame, int duration) {
}

void OSystem_PS2::stopCD(void) {
}

void OSystem_PS2::updateCD(void) {
}

void OSystem_PS2::showOverlay(void) {
	_screen->showOverlay();
}

void OSystem_PS2::hideOverlay(void) {
	_screen->hideOverlay();
}

void OSystem_PS2::clearOverlay(void) {
	_screen->clearOverlay();
}

void OSystem_PS2::grabOverlay(OverlayColor *buf, int pitch) {
	_screen->grabOverlay((uint16*)buf, (uint16)pitch);
}

void OSystem_PS2::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) {
	_screen->copyOverlayRect((uint16*)buf, (uint16)pitch, (uint16)x, (uint16)y, (uint16)w, (uint16)h);
}

const OSystem::GraphicsMode OSystem_PS2::_graphicsMode = { NULL, NULL, 0 };

const OSystem::GraphicsMode *OSystem_PS2::getSupportedGraphicsModes(void) const {
    return &_graphicsMode;
}

bool OSystem_PS2::setGraphicsMode(int mode) {
	return (mode == 0);
}

int OSystem_PS2::getGraphicsMode(void) const {
	return 0;
}

int OSystem_PS2::getDefaultGraphicsMode(void) const {
	return 0;
}

bool OSystem_PS2::pollEvent(Event &event) {
	bool res = _input->pollEvent(&event);
	if (res && (event.type == EVENT_MOUSEMOVE))
		_screen->setMouseXy(event.mouse.x, event.mouse.y);
	return res;
}

OverlayColor OSystem_PS2::RGBToColor(uint8 r, uint8 g, uint8 b) {
	return (r >> 3) | ((g >> 3) << 5) | ((b >> 3) << 10);
}

void OSystem_PS2::colorToRGB(OverlayColor color, uint8 &r, uint8 &g, uint8 &b) {
	r = (color & 0x1F) << 3;
	g = ((color >> 5) & 0x1F) << 3;
	b = ((color >> 10) & 0x1F) << 3;
}

int16 OSystem_PS2::getHeight(void) {
	return _height;
}

int16 OSystem_PS2::getWidth(void) {
	return _width;
}

void OSystem_PS2::quit(void) {
	printf("OSystem_PS2::quit\n");
	clearSoundCallback();
	setTimerCallback(NULL, 0);
	SleepThread();
}

static uint32 g_timeSecs;
static uint8  g_day, g_month, g_year;
static uint64 g_lastTimeCheck;

void readRtcTime(void) {
	struct CdClock cdClock;
	CDVD_ReadClock(&cdClock);
	g_lastTimeCheck = msecCount;

	if (cdClock.stat)
		printf("Unable to read RTC time.\n");

	g_timeSecs = ((FROM_BCD(cdClock.hour) * 60) + FROM_BCD(cdClock.minute)) * 60 + FROM_BCD(cdClock.second);
	g_day = FROM_BCD(cdClock.day);
	g_month = FROM_BCD(cdClock.month);
	g_year = FROM_BCD(cdClock.year);
	// todo: add something here to convert from JST to the right time zone
	sioprintf("Got RTC time: %d:%02d:%02d  %d.%d.%4d\n",
		FROM_BCD(cdClock.hour), FROM_BCD(cdClock.minute), FROM_BCD(cdClock.second),
		g_day, g_month, g_year + 2000);
}

time_t time(time_t *p) {
	time_t blah;
	memset(&blah, 0, sizeof(time_t));
	return blah;
}

#define SECONDS_PER_DAY (24 * 60 * 60)

struct tm *localtime(const time_t *p) {
	uint32 currentSecs = g_timeSecs + (msecCount - g_lastTimeCheck) / 1000;
	if (currentSecs >= SECONDS_PER_DAY) {
		readRtcTime();
		currentSecs = g_timeSecs + (msecCount - g_lastTimeCheck) / 1000;
	}

	static struct tm retStruct;
	memset(&retStruct, 0, sizeof(retStruct));

	retStruct.tm_hour = currentSecs / (60 * 60);
	retStruct.tm_min  = (currentSecs / 60) % 60;
	retStruct.tm_sec  = currentSecs % 60;
	retStruct.tm_year = g_year + 100;
	retStruct.tm_mday = g_day;
	retStruct.tm_mon  = g_month;
	// tm_wday, tm_yday and tm_isdst are zero for now
    return &retStruct;	
}


--- NEW FILE: systemps2.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2001-2004 The ScummVM project
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/backends/ps2/systemps2.h,v 1.1 2005/03/31 05:35:04 lavosspawn Exp $
 *
 */

#ifndef SYSTEMPS2_H
#define SYSTEMPS2_H

#include "stdafx.h"
#include "system.h"

class Gs2dScreen;
class Ps2Input;
class Ps2SaveFileManager;

class OSystem_PS2 : public OSystem {
public:
	OSystem_PS2(void);
	virtual ~OSystem_PS2(void);
	virtual void initSize(uint width, uint height, int overScale = -1);

	virtual int16 getHeight(void);
	virtual int16 getWidth(void);
	virtual void setPalette(const byte *colors, uint start, uint num);
	virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h);
	
	virtual void updateScreen();
	virtual void setShakePos(int shakeOffset);

	virtual bool showMouse(bool visible);

	virtual void warpMouse(int x, int y);
	virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, byte keycolor, int cursorTargetScale = 1);

	virtual uint32 getMillis();
	virtual void delayMillis(uint msecs);
	virtual void setTimerCallback(TimerProc callback, int interval);
	virtual bool pollEvent(Event &event);

	virtual bool setSoundCallback(SoundProc proc, void *param);
	virtual void clearSoundCallback();
	virtual int  getOutputSampleRate(void) const;

	virtual bool openCD(int drive);
	virtual bool pollCD();
	virtual void playCD(int track, int num_loops, int start_frame, int duration);
	virtual void stopCD();
	virtual void updateCD();

	virtual MutexRef createMutex(void);
	virtual void lockMutex(MutexRef mutex);
	virtual void unlockMutex(MutexRef mutex);
	virtual void deleteMutex(MutexRef mutex);

	virtual void showOverlay();
	virtual void hideOverlay();
	virtual void clearOverlay();
	virtual void grabOverlay(OverlayColor *buf, int pitch);
	virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h);

	virtual const GraphicsMode *getSupportedGraphicsModes() const;
	virtual int getDefaultGraphicsMode() const;
	virtual bool setGraphicsMode(int mode);
	virtual int getGraphicsMode() const;

	virtual void quit();

	virtual OverlayColor RGBToColor(uint8 r, uint8 g, uint8 b);

	virtual void colorToRGB(OverlayColor color, uint8 &r, uint8 &g, uint8 &b);

	virtual SaveFileManager *getSavefileManager();

	void timerThread(void);
	void soundThread(void);
private:
	volatile OSystem::TimerProc _scummTimerProc;
	volatile OSystem::SoundProc _scummSoundProc;
	void *_scummSoundParam;
	int16 *_soundBuf, *_soundBuf2;
	int _soundSema;

	void initTimer(void);

	bool loadModules(void);
	bool _mouseVisible;
	bool _useHdd, _useMouse, _useKbd;

	Ps2SaveFileManager *_saveManager;

	uint16 _width, _height;

	Gs2dScreen	*_screen;
	//PadMouse	*_mouse;
	Ps2Input	*_input;
	uint16		_oldMouseX, _oldMouseY;

	uint8		*_timerStack, *_soundStack;
	int32		_timerTid, _soundTid;
	static const GraphicsMode _graphicsMode;
};

#endif // SYSTEMPS2_H






More information about the Scummvm-git-logs mailing list