From b602b511607ac7bae911a5306bbe8301fdad4708 Mon Sep 17 00:00:00 2001 From: Einar Johan Trøan Sømåen Date: Tue, 6 Mar 2012 03:09:12 +0100 Subject: WINTERMUTE: Add the files for the rest of the B-classes. --- engines/wintermute/BActiveRect.cpp | 107 + engines/wintermute/BActiveRect.h | 59 + engines/wintermute/BDebugger.cpp | 49 +- engines/wintermute/BDebugger.h | 55 +- engines/wintermute/BDiskFile.cpp | 214 ++ engines/wintermute/BDiskFile.h | 59 + engines/wintermute/BDynBuffer.cpp | 192 ++ engines/wintermute/BEvent.cpp | 197 ++ engines/wintermute/BEvent.h | 56 + engines/wintermute/BFader.cpp | 175 ++ engines/wintermute/BFader.h | 62 + engines/wintermute/BFile.cpp | 69 + engines/wintermute/BFile.h | 65 + engines/wintermute/BFileEntry.cpp | 50 + engines/wintermute/BFileEntry.h | 57 + engines/wintermute/BFileManager.cpp | 743 +++++ engines/wintermute/BFileManager.h | 81 + engines/wintermute/BFont.cpp | 206 ++ engines/wintermute/BFont.h | 61 + engines/wintermute/BFontBitmap.cpp | 532 ++++ engines/wintermute/BFontBitmap.h | 72 + engines/wintermute/BFontStorage.cpp | 155 ++ engines/wintermute/BFontStorage.h | 66 + engines/wintermute/BFontTT.cpp | 853 ++++++ engines/wintermute/BFontTT.h | 188 ++ engines/wintermute/BFrame.cpp | 707 +++++ engines/wintermute/BFrame.h | 73 + engines/wintermute/BGame.cpp | 4462 +++++++++++++++++++++++++++++++ engines/wintermute/BGame.h | 20 +- engines/wintermute/BImage.cpp | 117 + engines/wintermute/BImage.h | 62 + engines/wintermute/BKeyboardState.cpp | 243 ++ engines/wintermute/BKeyboardState.h | 71 + engines/wintermute/BPackage.cpp | 102 + engines/wintermute/BPackage.h | 57 + engines/wintermute/BPkgFile.cpp | 228 ++ engines/wintermute/BPkgFile.h | 61 + engines/wintermute/BPoint.cpp | 64 + engines/wintermute/BPoint.h | 50 + engines/wintermute/BQuickMsg.cpp | 54 + engines/wintermute/BQuickMsg.h | 48 + engines/wintermute/BRegion.cpp | 508 ++++ engines/wintermute/BRegion.h | 68 + engines/wintermute/BRegistry.cpp | 227 ++ engines/wintermute/BRegistry.h | 76 + engines/wintermute/BRenderSDL.cpp | 408 +++ engines/wintermute/BRenderSDL.h | 95 + engines/wintermute/BRenderer.cpp | 259 ++ engines/wintermute/BRenderer.h | 124 + engines/wintermute/BResourceFile.cpp | 103 + engines/wintermute/BResourceFile.h | 50 + engines/wintermute/BResources.cpp | 2830 ++++++++++++++++++++ engines/wintermute/BResources.h | 41 + engines/wintermute/BSaveThumbFile.cpp | 146 + engines/wintermute/BSaveThumbFile.h | 51 + engines/wintermute/BSaveThumbHelper.cpp | 79 + engines/wintermute/BSaveThumbHelper.h | 50 + engines/wintermute/BScriptHolder.cpp | 470 ++++ engines/wintermute/BSound.cpp | 266 ++ engines/wintermute/BSound.h | 85 + engines/wintermute/BSoundBuffer.cpp | 384 +++ engines/wintermute/BSoundBuffer.h | 95 + engines/wintermute/BSoundMgr.cpp | 330 +++ engines/wintermute/BSoundMgr.h | 70 + engines/wintermute/BSprite.cpp | 753 ++++++ engines/wintermute/BSprite.h | 90 + engines/wintermute/BStringTable.cpp | 229 ++ engines/wintermute/BStringTable.h | 55 + engines/wintermute/BSubFrame.cpp | 588 ++++ engines/wintermute/BSubFrame.h | 85 + engines/wintermute/BSurface.cpp | 196 ++ engines/wintermute/BSurface.h | 93 + engines/wintermute/BSurfaceSDL.cpp | 402 +++ engines/wintermute/BSurfaceSDL.h | 79 + engines/wintermute/BSurfaceStorage.cpp | 192 ++ engines/wintermute/BSurfaceStorage.h | 58 + engines/wintermute/BTransitionMgr.cpp | 126 + engines/wintermute/BTransitionMgr.h | 54 + engines/wintermute/BViewport.cpp | 98 + engines/wintermute/BViewport.h | 55 + engines/wintermute/PathUtil.cpp | 196 ++ engines/wintermute/PathUtil.h | 56 + engines/wintermute/StringUtil.cpp | 49 +- engines/wintermute/StringUtil.h | 53 +- engines/wintermute/SysClass.h | 49 +- engines/wintermute/module.mk | 1 + engines/wintermute/persistent.h | 1 - engines/wintermute/utils.cpp | 49 +- engines/wintermute/utils.h | 55 +- 89 files changed, 21140 insertions(+), 179 deletions(-) create mode 100644 engines/wintermute/BActiveRect.cpp create mode 100644 engines/wintermute/BActiveRect.h create mode 100644 engines/wintermute/BDiskFile.cpp create mode 100644 engines/wintermute/BDiskFile.h create mode 100644 engines/wintermute/BDynBuffer.cpp create mode 100644 engines/wintermute/BEvent.cpp create mode 100644 engines/wintermute/BEvent.h create mode 100644 engines/wintermute/BFader.cpp create mode 100644 engines/wintermute/BFader.h create mode 100644 engines/wintermute/BFile.cpp create mode 100644 engines/wintermute/BFile.h create mode 100644 engines/wintermute/BFileEntry.cpp create mode 100644 engines/wintermute/BFileEntry.h create mode 100644 engines/wintermute/BFileManager.cpp create mode 100644 engines/wintermute/BFileManager.h create mode 100644 engines/wintermute/BFont.cpp create mode 100644 engines/wintermute/BFont.h create mode 100644 engines/wintermute/BFontBitmap.cpp create mode 100644 engines/wintermute/BFontBitmap.h create mode 100644 engines/wintermute/BFontStorage.cpp create mode 100644 engines/wintermute/BFontStorage.h create mode 100644 engines/wintermute/BFontTT.cpp create mode 100644 engines/wintermute/BFontTT.h create mode 100644 engines/wintermute/BFrame.cpp create mode 100644 engines/wintermute/BFrame.h create mode 100644 engines/wintermute/BGame.cpp create mode 100644 engines/wintermute/BImage.cpp create mode 100644 engines/wintermute/BImage.h create mode 100644 engines/wintermute/BKeyboardState.cpp create mode 100644 engines/wintermute/BKeyboardState.h create mode 100644 engines/wintermute/BPackage.cpp create mode 100644 engines/wintermute/BPackage.h create mode 100644 engines/wintermute/BPkgFile.cpp create mode 100644 engines/wintermute/BPkgFile.h create mode 100644 engines/wintermute/BPoint.cpp create mode 100644 engines/wintermute/BPoint.h create mode 100644 engines/wintermute/BQuickMsg.cpp create mode 100644 engines/wintermute/BQuickMsg.h create mode 100644 engines/wintermute/BRegion.cpp create mode 100644 engines/wintermute/BRegion.h create mode 100644 engines/wintermute/BRegistry.cpp create mode 100644 engines/wintermute/BRegistry.h create mode 100644 engines/wintermute/BRenderSDL.cpp create mode 100644 engines/wintermute/BRenderSDL.h create mode 100644 engines/wintermute/BRenderer.cpp create mode 100644 engines/wintermute/BRenderer.h create mode 100644 engines/wintermute/BResourceFile.cpp create mode 100644 engines/wintermute/BResourceFile.h create mode 100644 engines/wintermute/BResources.cpp create mode 100644 engines/wintermute/BResources.h create mode 100644 engines/wintermute/BSaveThumbFile.cpp create mode 100644 engines/wintermute/BSaveThumbFile.h create mode 100644 engines/wintermute/BSaveThumbHelper.cpp create mode 100644 engines/wintermute/BSaveThumbHelper.h create mode 100644 engines/wintermute/BScriptHolder.cpp create mode 100644 engines/wintermute/BSound.cpp create mode 100644 engines/wintermute/BSound.h create mode 100644 engines/wintermute/BSoundBuffer.cpp create mode 100644 engines/wintermute/BSoundBuffer.h create mode 100644 engines/wintermute/BSoundMgr.cpp create mode 100644 engines/wintermute/BSoundMgr.h create mode 100644 engines/wintermute/BSprite.cpp create mode 100644 engines/wintermute/BSprite.h create mode 100644 engines/wintermute/BStringTable.cpp create mode 100644 engines/wintermute/BStringTable.h create mode 100644 engines/wintermute/BSubFrame.cpp create mode 100644 engines/wintermute/BSubFrame.h create mode 100644 engines/wintermute/BSurface.cpp create mode 100644 engines/wintermute/BSurface.h create mode 100644 engines/wintermute/BSurfaceSDL.cpp create mode 100644 engines/wintermute/BSurfaceSDL.h create mode 100644 engines/wintermute/BSurfaceStorage.cpp create mode 100644 engines/wintermute/BSurfaceStorage.h create mode 100644 engines/wintermute/BTransitionMgr.cpp create mode 100644 engines/wintermute/BTransitionMgr.h create mode 100644 engines/wintermute/BViewport.cpp create mode 100644 engines/wintermute/BViewport.h create mode 100644 engines/wintermute/PathUtil.cpp create mode 100644 engines/wintermute/PathUtil.h (limited to 'engines') diff --git a/engines/wintermute/BActiveRect.cpp b/engines/wintermute/BActiveRect.cpp new file mode 100644 index 0000000000..5827cb8d61 --- /dev/null +++ b/engines/wintermute/BActiveRect.cpp @@ -0,0 +1,107 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BActiveRect.h" +#include "BGame.h" +#include "BRegion.h" +#include "PlatformSDL.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +CBActiveRect::CBActiveRect(CBGame *inGame): CBBase(inGame) { + CBPlatform::SetRectEmpty(&m_Rect); + m_Owner = NULL; + m_Frame = NULL; + m_Region = NULL; + m_ZoomX = 100; + m_ZoomY = 100; + m_OffsetX = m_OffsetY = 0; + ClipRect(); +} + + +////////////////////////////////////////////////////////////////////// +CBActiveRect::CBActiveRect(CBGame *inGame, CBObject *Owner, CBSubFrame *Frame, int X, int Y, int Width, int Height, float ZoomX, float ZoomY, bool Precise): CBBase(inGame) { + m_Owner = Owner; + m_Frame = Frame; + CBPlatform::SetRect(&m_Rect, X, Y, X + Width, Y + Height); + m_ZoomX = ZoomX; + m_ZoomY = ZoomY; + m_Precise = Precise; + m_Region = NULL; + m_OffsetX = m_OffsetY = 0; + ClipRect(); +} + +////////////////////////////////////////////////////////////////////// +CBActiveRect::CBActiveRect(CBGame *inGame, CBObject *Owner, CBRegion *Region, int OffsetX, int OffsetY): CBBase(inGame) { + m_Owner = Owner; + m_Region = Region; + CBPlatform::CopyRect(&m_Rect, &Region->m_Rect); + CBPlatform::OffsetRect(&m_Rect, -OffsetX, -OffsetY); + m_ZoomX = 100; + m_ZoomY = 100; + m_Precise = true; + m_Frame = NULL; + ClipRect(); + m_OffsetX = OffsetX; + m_OffsetY = OffsetY; +} + + +////////////////////////////////////////////////////////////////////// +CBActiveRect::~CBActiveRect() { + m_Owner = NULL; + m_Frame = NULL; + m_Region = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +void CBActiveRect::ClipRect() { + RECT rc; + bool CustomViewport; + Game->GetCurrentViewportRect(&rc, &CustomViewport); + CBRenderer *Rend = Game->m_Renderer; + + if (!CustomViewport) { + rc.left -= Rend->m_DrawOffsetX; + rc.right -= Rend->m_DrawOffsetX; + rc.top -= Rend->m_DrawOffsetY; + rc.bottom -= Rend->m_DrawOffsetY; + } + + if (rc.left > m_Rect.left) m_OffsetX = rc.left - m_Rect.left; + if (rc.top > m_Rect.top) m_OffsetY = rc.top - m_Rect.top; + + CBPlatform::IntersectRect(&m_Rect, &m_Rect, &rc); +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BActiveRect.h b/engines/wintermute/BActiveRect.h new file mode 100644 index 0000000000..ee9bb8aea1 --- /dev/null +++ b/engines/wintermute/BActiveRect.h @@ -0,0 +1,59 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BACTIVERECT_H +#define WINTERMUTE_BACTIVERECT_H + +#include "BBase.h" + +namespace WinterMute { +class CBRegion; +class CBSubFrame; +class CBObject; +class CBActiveRect: CBBase { +public: + void ClipRect(); + bool m_Precise; + float m_ZoomX; + float m_ZoomY; + CBSubFrame *m_Frame; + CBObject *m_Owner; + CBRegion *m_Region; + int m_OffsetX; + int m_OffsetY; + RECT m_Rect; + CBActiveRect(CBGame *inGameOwner = NULL); + CBActiveRect(CBGame *inGameOwner, CBObject *Owner, CBSubFrame *Frame, int X, int Y, int Width, int Height, float ZoomX = 100, float ZoomY = 100, bool Precise = true); + CBActiveRect(CBGame *inGame, CBObject *Owner, CBRegion *Region, int OffsetX, int OffsetY); + virtual ~CBActiveRect(); + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BDebugger.cpp b/engines/wintermute/BDebugger.cpp index 8e5faa8db1..13eae9fd18 100644 --- a/engines/wintermute/BDebugger.cpp +++ b/engines/wintermute/BDebugger.cpp @@ -1,27 +1,30 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + /* -This file is part of WME Lite. -http://dead-code.org/redir.php?target=wmelite - -Copyright (c) 2011 Jan Nedoma - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ #include "BDebugger.h" diff --git a/engines/wintermute/BDebugger.h b/engines/wintermute/BDebugger.h index 28b37cee4f..21a7d308a9 100644 --- a/engines/wintermute/BDebugger.h +++ b/engines/wintermute/BDebugger.h @@ -1,30 +1,33 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + /* -This file is part of WME Lite. -http://dead-code.org/redir.php?target=wmelite - -Copyright (c) 2011 Jan Nedoma - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#ifndef __WmeBDebugger_H__ -#define __WmeBDebugger_H__ + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BDEBUGGER_H +#define WINTERMUTE_BDEBUGGER_H #include "BBase.h" diff --git a/engines/wintermute/BDiskFile.cpp b/engines/wintermute/BDiskFile.cpp new file mode 100644 index 0000000000..ea7a24a0a9 --- /dev/null +++ b/engines/wintermute/BDiskFile.cpp @@ -0,0 +1,214 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BGame.h" +#include "wintypes.h" +#include "BPkgFile.h" +#include "BDiskFile.h" +#include "common/stream.h" +#include "BFileManager.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CBDiskFile::CBDiskFile(CBGame *inGame): CBFile(inGame) { + m_File = NULL; + m_Data = NULL; + m_Compressed = false; + m_PrefixSize = 0; +} + + +////////////////////////////////////////////////////////////////////////// +CBDiskFile::~CBDiskFile() { + Close(); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBDiskFile::Open(Common::String Filename) { + Close(); + + char FullPath[MAX_PATH]; + + for (int i = 0; i < Game->m_FileManager->m_SinglePaths.GetSize(); i++) { + sprintf(FullPath, "%s%s", Game->m_FileManager->m_SinglePaths[i], Filename.c_str()); + CorrectSlashes(FullPath); + + m_File = Common::createFileStream(FullPath); + if (m_File != NULL) + break; + } + + // if we didn't find it in search paths, try to open directly + if (!m_File) { + strcpy(FullPath, Filename.c_str()); + CorrectSlashes(FullPath); + m_File = Common::createFileStream(FullPath); + } + + if (m_File) { + uint32 magic1, magic2; + magic1 = m_File->readUint32LE(); + magic2 = m_File->readUint32LE(); + + if (magic1 == DCGF_MAGIC && magic2 == COMPRESSED_FILE_MAGIC) m_Compressed = true; + + if (m_Compressed) { + uint32 DataOffset, CompSize, UncompSize; + DataOffset = m_File->readUint32LE(); + CompSize = m_File->readUint32LE(); + UncompSize = m_File->readUint32LE(); + + byte *CompBuffer = new byte[CompSize]; + if (!CompBuffer) { + Game->LOG(0, "Error allocating memory for compressed file '%s'", Filename.c_str()); + Close(); + return E_FAIL; + } + + m_Data = new byte[UncompSize]; + if (!m_Data) { + Game->LOG(0, "Error allocating buffer for file '%s'", Filename.c_str()); + delete [] CompBuffer; + Close(); + return E_FAIL; + } + m_File->seek(DataOffset + m_PrefixSize, SEEK_SET); + m_File->read(CompBuffer, CompSize); + + if (uncompress(m_Data, (uLongf *)&UncompSize, CompBuffer, CompSize) != Z_OK) { + Game->LOG(0, "Error uncompressing file '%s'", Filename.c_str()); + delete [] CompBuffer; + Close(); + return E_FAIL; + } + + delete [] CompBuffer; + m_Size = UncompSize; + m_Pos = 0; + delete m_File; + m_File = NULL; + } else { + m_Pos = 0; + m_File->seek(0, SEEK_END); + m_Size = m_File->pos() - m_PrefixSize; + m_File->seek(m_PrefixSize,SEEK_SET); + } + + return S_OK; + } else return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBDiskFile::Close() { + if (m_File) { + delete m_File; + } + m_File = NULL; + m_Pos = 0; + m_Size = 0; + + delete[] m_Data; + m_Data = NULL; + + m_Compressed = false; + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBDiskFile::Read(void *Buffer, uint32 Size) { + if (m_Compressed) { + memcpy(Buffer, m_Data + m_Pos, Size); + m_Pos += Size; + return S_OK; + } else { + + if (m_File) { + size_t count = m_File->read(Buffer, Size); + m_Pos += count; + return S_OK; + } else return E_FAIL; + } +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBDiskFile::Seek(uint32 Pos, TSeek Origin) { + if (m_Compressed) { + uint32 NewPos = 0; + + switch (Origin) { + case SEEK_TO_BEGIN: + NewPos = Pos; + break; + case SEEK_TO_END: + NewPos = m_Size + Pos; + break; + case SEEK_TO_CURRENT: + NewPos = m_Pos + Pos; + break; + } + + if (NewPos < 0 || NewPos > m_Size) return E_FAIL; + else m_Pos = NewPos; + return S_OK; + } else { + if (!m_File) return E_FAIL; + int ret = 1; + + switch (Origin) { + case SEEK_TO_BEGIN: + ret = m_File->seek(m_PrefixSize + Pos, SEEK_SET); + break; + case SEEK_TO_END: + ret = m_File->seek(Pos, SEEK_END); + break; + case SEEK_TO_CURRENT: + ret = m_File->seek(Pos, SEEK_CUR); + break; + } + if (ret == 0) { + m_Pos = m_File->pos() - m_PrefixSize; + return S_OK; + } else return E_FAIL; + } +} + +////////////////////////////////////////////////////////////////////////// +void CBDiskFile::CorrectSlashes(char *fileName) { + for (size_t i = 0; i < strlen(fileName); i++) { + if (fileName[i] == '\\') fileName[i] = '/'; + } +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BDiskFile.h b/engines/wintermute/BDiskFile.h new file mode 100644 index 0000000000..7cb4a889aa --- /dev/null +++ b/engines/wintermute/BDiskFile.h @@ -0,0 +1,59 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BDISKFILE_H +#define WINTERMUTE_BDISKFILE_H + + +#include "BFile.h" + +namespace Common { + class SeekableReadStream; +} + +namespace WinterMute { + +class CBDiskFile : public CBFile { +public: + CBDiskFile(CBGame *inGame); + virtual ~CBDiskFile(); + virtual HRESULT Seek(uint32 Pos, TSeek Origin = SEEK_TO_BEGIN); + virtual HRESULT Read(void *Buffer, uint32 Size); + virtual HRESULT Close(); + virtual HRESULT Open(Common::String Filename); +private: + void CorrectSlashes(char *fileName); + Common::SeekableReadStream *m_File; + byte *m_Data; + bool m_Compressed; + uint32 m_PrefixSize; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BDynBuffer.cpp b/engines/wintermute/BDynBuffer.cpp new file mode 100644 index 0000000000..3fe99faeb1 --- /dev/null +++ b/engines/wintermute/BDynBuffer.cpp @@ -0,0 +1,192 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "BGame.h" +#include "BDynBuffer.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CBDynBuffer::CBDynBuffer(CBGame *inGame, uint32 InitSize, uint32 GrowBy): CBBase(inGame) { + m_Buffer = NULL; + m_Size = 0; + m_RealSize = 0; + + m_Offset = 0; + m_InitSize = InitSize; + m_GrowBy = GrowBy; + + m_Initialized = false; +} + + +////////////////////////////////////////////////////////////////////////// +CBDynBuffer::~CBDynBuffer() { + Cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +void CBDynBuffer::Cleanup() { + if (m_Buffer) free(m_Buffer); + m_Buffer = NULL; + m_Size = 0; + m_RealSize = 0; + m_Offset = 0; + m_Initialized = false; +} + + +////////////////////////////////////////////////////////////////////////// +uint32 CBDynBuffer::GetSize() { + return m_Size; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBDynBuffer::Init(uint32 InitSize) { + Cleanup(); + + if (InitSize == 0) InitSize = m_InitSize; + + m_Buffer = (byte *)malloc(InitSize); + if (!m_Buffer) { + Game->LOG(0, "CBDynBuffer::Init - Error allocating %d bytes", InitSize); + return E_FAIL; + } + + m_RealSize = InitSize; + m_Initialized = true; + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBDynBuffer::PutBytes(byte *Buffer, uint32 Size) { + if (!m_Initialized) Init(); + + while (m_Offset + Size > m_RealSize) { + m_RealSize += m_GrowBy; + m_Buffer = (byte *)realloc(m_Buffer, m_RealSize); + if (!m_Buffer) { + Game->LOG(0, "CBDynBuffer::PutBytes - Error reallocating buffer to %d bytes", m_RealSize); + return E_FAIL; + } + } + + memcpy(m_Buffer + m_Offset, Buffer, Size); + m_Offset += Size; + m_Size += Size; + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBDynBuffer::GetBytes(byte *Buffer, uint32 Size) { + if (!m_Initialized) Init(); + + if (m_Offset + Size > m_Size) { + Game->LOG(0, "CBDynBuffer::GetBytes - Buffer underflow"); + return E_FAIL; + } + + memcpy(Buffer, m_Buffer + m_Offset, Size); + m_Offset += Size; + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void CBDynBuffer::PutDWORD(uint32 Val) { + PutBytes((byte *)&Val, sizeof(uint32)); +} + + +////////////////////////////////////////////////////////////////////////// +uint32 CBDynBuffer::GetDWORD() { + uint32 ret; + GetBytes((byte *)&ret, sizeof(uint32)); + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +void CBDynBuffer::PutString(const char *Val) { + if (!Val) PutString("(null)"); + else { + PutDWORD(strlen(Val) + 1); + PutBytes((byte *)Val, strlen(Val) + 1); + } +} + + +////////////////////////////////////////////////////////////////////////// +char *CBDynBuffer::GetString() { + uint32 len = GetDWORD(); + char *ret = (char *)(m_Buffer + m_Offset); + m_Offset += len; + + if (!strcmp(ret, "(null)")) return NULL; + else return ret; +} + + +////////////////////////////////////////////////////////////////////////// +void CBDynBuffer::PutText(LPCSTR fmt, ...) { + va_list va; + + va_start(va, fmt); + PutTextForm(fmt, va); + va_end(va); + +} + + +////////////////////////////////////////////////////////////////////////// +void CBDynBuffer::PutTextIndent(int Indent, LPCSTR fmt, ...) { + va_list va; + + PutText("%*s", Indent, ""); + + va_start(va, fmt); + PutTextForm(fmt, va); + va_end(va); +} + + +////////////////////////////////////////////////////////////////////////// +void CBDynBuffer::PutTextForm(const char *format, va_list argptr) { + char buff[32768]; + vsprintf(buff, format, argptr); + PutBytes((byte *)buff, strlen(buff)); +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BEvent.cpp b/engines/wintermute/BEvent.cpp new file mode 100644 index 0000000000..fbeddacb39 --- /dev/null +++ b/engines/wintermute/BEvent.cpp @@ -0,0 +1,197 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "BGame.h" +#include "BFileManager.h" +#include "BEvent.h" +#include "BParser.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +IMPLEMENT_PERSISTENT(CBEvent, false) + +////////////////////////////////////////////////////////////////////////// +CBEvent::CBEvent(CBGame *inGame): CBBase(inGame) { + m_Type = EVENT_NONE; + m_Script = NULL; + m_Name = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +CBEvent::CBEvent(CBGame *inGame, TEventType Type, char *Script): CBBase(inGame) { + m_Type = Type; + m_Script = new char [strlen(Script) + 1]; + if (m_Script) strcpy(m_Script, Script); + m_Name = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +CBEvent::~CBEvent() { + delete[] m_Script; + m_Script = NULL; + delete[] m_Name; + m_Name = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +const char *CBEvent::GetEventName(TEventType Type) { + switch (Type) { + case EVENT_INIT: + return "INIT"; + case EVENT_SHUTDOWN: + return "SHUTDOWN"; + case EVENT_LEFT_CLICK: + return "LEFT_CLICK"; + case EVENT_RIGHT_CLICK: + return "RIGHT_CLICK"; + case EVENT_MIDDLE_CLICK: + return "MIDDLE_CLICK"; + case EVENT_LEFT_DBLCLICK: + return "LEFT_DBLCLICK"; + case EVENT_PRESS: + return "PRESS"; + case EVENT_IDLE: + return "IDLE"; + case EVENT_MOUSE_OVER: + return "MOUSE_OVER"; + case EVENT_LEFT_RELEASE: + return "LEFT_RELEASE"; + case EVENT_RIGHT_RELEASE: + return "RIGHT_RELEASE"; + case EVENT_MIDDLE_RELEASE: + return "MIDDLE_RELEASE"; + + default: + return "NONE"; + } +} + + +////////////////////////////////////////////////////////////////////////// +void CBEvent::SetScript(char *Script) { + if (m_Script) delete [] m_Script; + + m_Script = new char [strlen(Script) + 1]; + if (m_Script) strcpy(m_Script, Script); +} + + +////////////////////////////////////////////////////////////////////////// +void CBEvent::SetName(char *Name) { + if (m_Name) delete [] m_Name; + + m_Name = new char [strlen(Name) + 1]; + if (m_Name) strcpy(m_Name, Name); +} + + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBEvent::LoadFile(char *Filename) { + byte *Buffer = Game->m_FileManager->ReadWholeFile(Filename); + if (Buffer == NULL) { + Game->LOG(0, "CBEvent::LoadFile failed for file '%s'", Filename); + return E_FAIL; + } + + HRESULT ret; + + if (FAILED(ret = LoadBuffer(Buffer, true))) Game->LOG(0, "Error parsing EVENT file '%s'", Filename); + + delete [] Buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(EVENT) +TOKEN_DEF(NAME) +TOKEN_DEF(SCRIPT) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +HRESULT CBEvent::LoadBuffer(byte *Buffer, bool Complete) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(EVENT) + TOKEN_TABLE(NAME) + TOKEN_TABLE(SCRIPT) + TOKEN_TABLE_END + + byte *params; + int cmd; + CBParser parser(Game); + + if (Complete) { + if (parser.GetCommand((char **)&Buffer, commands, (char **)¶ms) != TOKEN_EVENT) { + Game->LOG(0, "'EVENT' keyword expected."); + return E_FAIL; + } + Buffer = params; + } + + while ((cmd = parser.GetCommand((char **)&Buffer, commands, (char **)¶ms)) > 0) { + switch (cmd) { + case TOKEN_NAME: + SetName((char *)params); + break; + + case TOKEN_SCRIPT: + SetScript((char *)params); + break; + } + + } + if (cmd == PARSERR_TOKENNOTFOUND) { + Game->LOG(0, "Syntax error in EVENT definition"); + return E_FAIL; + } + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBEvent::Persist(CBPersistMgr *PersistMgr) { + + PersistMgr->Transfer(TMEMBER(Game)); + + PersistMgr->Transfer(TMEMBER(m_Script)); + PersistMgr->Transfer(TMEMBER(m_Name)); + PersistMgr->Transfer(TMEMBER_INT(m_Type)); + + return S_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BEvent.h b/engines/wintermute/BEvent.h new file mode 100644 index 0000000000..006e10706e --- /dev/null +++ b/engines/wintermute/BEvent.h @@ -0,0 +1,56 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BEVENT_H +#define WINTERMUTE_BEVENT_H + + +#include "BBase.h" +#include "dctypes.h" // Added by ClassView + +namespace WinterMute { + +class CBEvent : public CBBase { +public: + DECLARE_PERSISTENT(CBEvent, CBBase) + void SetScript(char *Script); + void SetName(char *Name); + static const char *GetEventName(TEventType Type); + char *m_Script; + char *m_Name; + TEventType m_Type; + CBEvent(CBGame *inGame); + CBEvent(CBGame *inGame, TEventType Type, char *Script); + virtual ~CBEvent(); + HRESULT LoadFile(char *Filename); + HRESULT LoadBuffer(byte *Buffer, bool Complete = true); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BFader.cpp b/engines/wintermute/BFader.cpp new file mode 100644 index 0000000000..f64023a08d --- /dev/null +++ b/engines/wintermute/BFader.cpp @@ -0,0 +1,175 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BFader.h" +#include "BGame.h" +#include "PlatformSDL.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +IMPLEMENT_PERSISTENT(CBFader, false) + +////////////////////////////////////////////////////////////////////////// +CBFader::CBFader(CBGame *inGame): CBObject(inGame) { + m_Active = false; + m_Red = m_Green = m_Blue = 0; + m_CurrentAlpha = 0x00; + m_SourceAlpha = 0; + m_TargetAlpha = 0; + m_Duration = 1000; + m_StartTime = 0; + m_System = false; +} + + +////////////////////////////////////////////////////////////////////////// +CBFader::~CBFader() { + +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFader::Update() { + if (!m_Active) return S_OK; + + int AlphaDelta = m_TargetAlpha - m_SourceAlpha; + + uint32 time; + + if (m_System) time = CBPlatform::GetTime() - m_StartTime; + else time = Game->m_Timer - m_StartTime; + + if (time >= m_Duration) m_CurrentAlpha = m_TargetAlpha; + else { + m_CurrentAlpha = m_SourceAlpha + (float)time / (float)m_Duration * AlphaDelta; + } + m_CurrentAlpha = MIN(255, std::max(m_CurrentAlpha, (byte )0)); + + m_Ready = time >= m_Duration; + if (m_Ready && m_CurrentAlpha == 0x00) m_Active = false; + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFader::Display() { + if (!m_Active) return S_OK; + + if (m_CurrentAlpha > 0x00) return Game->m_Renderer->FadeToColor(DRGBA(m_Red, m_Green, m_Blue, m_CurrentAlpha)); + else return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFader::Deactivate() { + m_Active = false; + m_Ready = true; + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFader::FadeIn(uint32 SourceColor, uint32 Duration, bool System) { + m_Ready = false; + m_Active = true; + + m_Red = D3DCOLGetR(SourceColor); + m_Green = D3DCOLGetG(SourceColor); + m_Blue = D3DCOLGetB(SourceColor); + + m_SourceAlpha = D3DCOLGetA(SourceColor); + m_TargetAlpha = 0; + + m_Duration = Duration; + m_System = System; + + if (m_System) m_StartTime = CBPlatform::GetTime(); + else m_StartTime = Game->m_Timer; + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFader::FadeOut(uint32 TargetColor, uint32 Duration, bool System) { + m_Ready = false; + m_Active = true; + + m_Red = D3DCOLGetR(TargetColor); + m_Green = D3DCOLGetG(TargetColor); + m_Blue = D3DCOLGetB(TargetColor); + + //m_SourceAlpha = 0; + m_SourceAlpha = m_CurrentAlpha; + m_TargetAlpha = D3DCOLGetA(TargetColor); + + m_Duration = Duration; + m_System = System; + + if (m_System) m_StartTime = CBPlatform::GetTime(); + else m_StartTime = Game->m_Timer; + + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +uint32 CBFader::GetCurrentColor() { + return DRGBA(m_Red, m_Green, m_Blue, m_CurrentAlpha); +} + + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFader::Persist(CBPersistMgr *PersistMgr) { + CBObject::Persist(PersistMgr); + + PersistMgr->Transfer(TMEMBER(m_Active)); + PersistMgr->Transfer(TMEMBER(m_Blue)); + PersistMgr->Transfer(TMEMBER(m_CurrentAlpha)); + PersistMgr->Transfer(TMEMBER(m_Duration)); + PersistMgr->Transfer(TMEMBER(m_Green)); + PersistMgr->Transfer(TMEMBER(m_Red)); + PersistMgr->Transfer(TMEMBER(m_SourceAlpha)); + PersistMgr->Transfer(TMEMBER(m_StartTime)); + PersistMgr->Transfer(TMEMBER(m_TargetAlpha)); + PersistMgr->Transfer(TMEMBER(m_System)); + + if (m_System && !PersistMgr->m_Saving) m_StartTime = 0; + + return S_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BFader.h b/engines/wintermute/BFader.h new file mode 100644 index 0000000000..44ce256826 --- /dev/null +++ b/engines/wintermute/BFader.h @@ -0,0 +1,62 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BFADER_H +#define WINTERMUTE_BFADER_H + + +#include "BObject.h" + +namespace WinterMute { + +class CBFader : public CBObject { +public: + bool m_System; + uint32 GetCurrentColor(); + HRESULT FadeOut(uint32 TargetColor, uint32 Duration, bool System = false); + HRESULT FadeIn(uint32 SourceColor, uint32 Duration, bool System = false); + HRESULT Deactivate(); + HRESULT Display(); + HRESULT Update(); + DECLARE_PERSISTENT(CBFader, CBObject) + CBFader(CBGame *inGame); + virtual ~CBFader(); + bool m_Active; + byte m_Red; + byte m_Green; + byte m_Blue; + byte m_CurrentAlpha; + byte m_TargetAlpha; + byte m_SourceAlpha; + uint32 m_Duration; + uint32 m_StartTime; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BFile.cpp b/engines/wintermute/BFile.cpp new file mode 100644 index 0000000000..f4d7da2c70 --- /dev/null +++ b/engines/wintermute/BFile.cpp @@ -0,0 +1,69 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BFile.h" +#include "common/memstream.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////// +CBFile::CBFile(CBGame *inGame): CBBase(inGame) { + m_Pos = 0; + m_Size = 0; +} + + +////////////////////////////////////////////////////////////////////////// +CBFile::~CBFile() { + +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFile::IsEOF() { + return m_Pos == m_Size; +} + +Common::SeekableReadStream *CBFile::getMemStream() { + uint32 oldPos = GetPos(); + Seek(0); + byte *data = new byte[GetSize()]; + Read(data, GetSize()); + Seek(oldPos); + Common::MemoryReadStream *memStream = new Common::MemoryReadStream(data, GetSize(), DisposeAfterUse::YES); + return memStream; +} + + +} // end of namespace WinterMute diff --git a/engines/wintermute/BFile.h b/engines/wintermute/BFile.h new file mode 100644 index 0000000000..db6a29d903 --- /dev/null +++ b/engines/wintermute/BFile.h @@ -0,0 +1,65 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BFILE_H +#define WINTERMUTE_BFILE_H + + +#include "BBase.h" +#include "common/str.h" + +namespace Common { + class SeekableReadStream; +} + +namespace WinterMute { + +class CBFile : public CBBase { +public: + uint32 m_Pos; + uint32 m_Size; + virtual uint32 GetSize() { + return m_Size; + }; + virtual uint32 GetPos() { + return m_Pos; + }; + virtual HRESULT Seek(uint32 Pos, TSeek Origin = SEEK_TO_BEGIN) = 0; + virtual HRESULT Read(void *Buffer, uint32 Size) = 0; + virtual HRESULT Close() = 0; + virtual HRESULT Open(Common::String Filename) = 0; + virtual bool IsEOF(); + CBFile(CBGame *inGame); + virtual ~CBFile(); + // Temporary solution to allow usage in ScummVM-code: + virtual Common::SeekableReadStream *getMemStream(); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BFileEntry.cpp b/engines/wintermute/BFileEntry.cpp new file mode 100644 index 0000000000..18a15e37f9 --- /dev/null +++ b/engines/wintermute/BFileEntry.cpp @@ -0,0 +1,50 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ +#include "dcgf.h" +#include "BFileEntry.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CBFileEntry::CBFileEntry(CBGame *inGame): CBBase(inGame) { + m_Package = NULL; + m_Length = m_CompressedLength = m_Offset = m_Flags = 0; + m_Filename = ""; + + m_TimeDate1 = m_TimeDate2 = 0; + + m_JournalTime = 0; +} + + +////////////////////////////////////////////////////////////////////////// +CBFileEntry::~CBFileEntry() { + m_Package = NULL; // ref only +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BFileEntry.h b/engines/wintermute/BFileEntry.h new file mode 100644 index 0000000000..cfad80926c --- /dev/null +++ b/engines/wintermute/BFileEntry.h @@ -0,0 +1,57 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BFILEENTRY_H +#define WINTERMUTE_BFILEENTRY_H + + +#include "BBase.h" + +namespace WinterMute { + +class CBPackage; + +class CBFileEntry : public CBBase { +public: + uint32 m_TimeDate2; + uint32 m_TimeDate1; + uint32 m_Flags; + uint32 m_JournalTime; + std::string m_Filename; + uint32 m_CompressedLength; + uint32 m_Length; + uint32 m_Offset; + CBPackage *m_Package; + CBFileEntry(CBGame *inGame); + virtual ~CBFileEntry(); + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BFileManager.cpp b/engines/wintermute/BFileManager.cpp new file mode 100644 index 0000000000..d679321598 --- /dev/null +++ b/engines/wintermute/BFileManager.cpp @@ -0,0 +1,743 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BFileManager.h" +#include "StringUtil.h" +#include "PathUtil.h" +#include "BDiskFile.h" +#include "BResourceFile.h" +#include "BSaveThumbFile.h" +#include "BFileEntry.h" +#include "BPkgFile.h" +#include "BPackage.h" +#include "BRegistry.h" +#include "BGame.h" +#include "dcpackage.h" +#include "utils.h" +#include "PlatformSDL.h" +#include "common/str.h" +#include "common/textconsole.h" +#include + +#ifdef __WIN32__ +# include +#else +# include +#endif + +#ifdef __APPLE__ +# include +#endif + + +#if _DEBUG +#pragma comment(lib, "zlib_d.lib") +#else +#pragma comment(lib, "zlib.lib") +#endif + + +extern "C" +{ +#include "zlib.h" +} + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////// +CBFileManager::CBFileManager(CBGame *inGame): CBBase(inGame) { + m_BasePath = NULL; + + InitPaths(); + RegisterPackages(); +} + + +////////////////////////////////////////////////////////////////////// +CBFileManager::~CBFileManager() { + Cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFileManager::Cleanup() { + int i; + + // delete registered paths + for (i = 0; i < m_SinglePaths.GetSize(); i++) + delete [] m_SinglePaths[i]; + m_SinglePaths.RemoveAll(); + + for (i = 0; i < m_PackagePaths.GetSize(); i++) + delete [] m_PackagePaths[i]; + m_PackagePaths.RemoveAll(); + + + // delete file entries + m_FilesIter = m_Files.begin(); + while (m_FilesIter != m_Files.end()) { + delete m_FilesIter->second; + m_FilesIter++; + } + m_Files.clear(); + + // close open files + for (i = 0; i < m_OpenFiles.GetSize(); i++) { + m_OpenFiles[i]->Close(); + delete m_OpenFiles[i]; + } + m_OpenFiles.RemoveAll(); + + + // delete packages + for (i = 0; i < m_Packages.GetSize(); i++) + delete m_Packages[i]; + m_Packages.RemoveAll(); + + delete[] m_BasePath; + m_BasePath = NULL; + + return S_OK; +} + + + +#define MAX_FILE_SIZE 10000000 +////////////////////////////////////////////////////////////////////// +byte *CBFileManager::ReadWholeFile(const char *Filename, uint32 *Size, bool MustExist) { + + byte *buffer = NULL; + + CBFile *File = OpenFile(Filename); + if (!File) { + if (MustExist) Game->LOG(0, "Error opening file '%s'", Filename); + return NULL; + } + + /* + if(File->GetSize()>MAX_FILE_SIZE){ + Game->LOG(0, "File '%s' exceeds the maximum size limit (%d bytes)", Filename, MAX_FILE_SIZE); + CloseFile(File); + return NULL; + } + */ + + + buffer = new byte[File->GetSize() + 1]; + if (buffer == NULL) { + Game->LOG(0, "Error allocating buffer for file '%s' (%d bytes)", Filename, File->GetSize() + 1); + CloseFile(File); + return NULL; + } + + if (FAILED(File->Read(buffer, File->GetSize()))) { + Game->LOG(0, "Error reading file '%s'", Filename); + CloseFile(File); + delete [] buffer; + return NULL; + }; + + buffer[File->GetSize()] = '\0'; + if (Size != NULL) *Size = File->GetSize(); + CloseFile(File); + + return buffer; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFileManager::SaveFile(char *Filename, byte *Buffer, uint32 BufferSize, bool Compressed, byte *PrefixBuffer, uint32 PrefixSize) { + RestoreCurrentDir(); + + CBUtils::CreatePath(Filename, false); + + FILE *f = fopen(Filename, "wb"); + if (!f) { + Game->LOG(0, "Error opening file '%s' for writing.", Filename); + return E_FAIL; + } + + if (PrefixBuffer && PrefixSize) { + fwrite(PrefixBuffer, PrefixSize, 1, f); + } + + if (Compressed) { + uint32 CompSize = BufferSize + (BufferSize / 100) + 12; // 1% extra space + byte *CompBuffer = new byte[CompSize]; + if (!CompBuffer) { + Game->LOG(0, "Error allocating compression buffer while saving '%s'", Filename); + Compressed = false; + } else { + if (compress(CompBuffer, (uLongf *)&CompSize, Buffer, BufferSize) == Z_OK) { + uint32 magic = DCGF_MAGIC; + fwrite(&magic, sizeof(uint32), 1, f); + magic = COMPRESSED_FILE_MAGIC; + fwrite(&magic, sizeof(uint32), 1, f); + + uint32 DataOffset = 5 * sizeof(uint32); + fwrite(&DataOffset, sizeof(uint32), 1, f); + + fwrite(&CompSize, sizeof(uint32), 1, f); + fwrite(&BufferSize, sizeof(uint32), 1, f); + + fwrite(CompBuffer, CompSize, 1, f); + } else { + Game->LOG(0, "Error compressing data while saving '%s'", Filename); + Compressed = false; + } + + delete [] CompBuffer; + } + } + + if (!Compressed) fwrite(Buffer, BufferSize, 1, f); + + fclose(f); + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFileManager::RequestCD(int CD, char *PackageFile, char *Filename) { + // unmount all non-local packages + for (int i = 0; i < m_Packages.GetSize(); i++) { + if (m_Packages[i]->m_CD > 0) m_Packages[i]->Close(); + } + + + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFileManager::AddPath(TPathType Type, const char *Path) { + if (Path == NULL || strlen(Path) < 1) return E_FAIL; + + bool slashed = (Path[strlen(Path) - 1] == '\\' || Path[strlen(Path) - 1] == '/'); + + char *buffer = new char [strlen(Path) + 1 + (slashed ? 0 : 1)]; + if (buffer == NULL) return E_FAIL; + + strcpy(buffer, Path); + if (!slashed) strcat(buffer, "\\"); + //CBPlatform::strlwr(buffer); + + switch (Type) { + case PATH_SINGLE: + m_SinglePaths.Add(buffer); + break; + case PATH_PACKAGE: + m_PackagePaths.Add(buffer); + break; + } + + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFileManager::ReloadPaths() { + // delete registered paths + for (int i = 0; i < m_SinglePaths.GetSize(); i++) + delete [] m_SinglePaths[i]; + m_SinglePaths.RemoveAll(); + + for (int i = 0; i < m_PackagePaths.GetSize(); i++) + delete [] m_PackagePaths[i]; + m_PackagePaths.RemoveAll(); + + return InitPaths(); +} + + +#define TEMP_BUFFER_SIZE 32768 +////////////////////////////////////////////////////////////////////////// +HRESULT CBFileManager::InitPaths() { + RestoreCurrentDir(); + + AnsiString pathList; + int numPaths; + + // single files paths + pathList = Game->m_Registry->ReadString("Resource", "CustomPaths", ""); + numPaths = CBUtils::StrNumEntries(pathList.c_str(), ';'); + + for (int i = 0; i < numPaths; i++) { + char *path = CBUtils::StrEntry(i, pathList.c_str(), ';'); + if (path && strlen(path) > 0) { + AddPath(PATH_SINGLE, path); + } + delete[] path; + path = NULL; + } + AddPath(PATH_SINGLE, ".\\"); + + + // package files paths + AddPath(PATH_PACKAGE, "./"); + +#ifdef __APPLE__ + // search .app path and Resources dir in the bundle + CFURLRef appUrlRef = CFBundleCopyBundleURL(CFBundleGetMainBundle()); + CFStringRef macPath = CFURLCopyFileSystemPath(appUrlRef, kCFURLPOSIXPathStyle); + const char *pathPtr = CFStringGetCStringPtr(macPath, CFStringGetSystemEncoding()); + +#ifdef __IPHONE__ + AddPath(PATH_PACKAGE, pathPtr); + AddPath(PATH_SINGLE, pathPtr); +#else + char bundlePath[MAX_PATH]; + + sprintf(bundlePath, "%s/../", pathPtr); + AddPath(PATH_PACKAGE, bundlePath); + AddPath(PATH_SINGLE, bundlePath); + + sprintf(bundlePath, "%s/Contents/Resources/", pathPtr); + AddPath(PATH_PACKAGE, bundlePath); + AddPath(PATH_SINGLE, bundlePath); + + + CFRelease(appUrlRef); + CFRelease(macPath); +#endif +#endif + + + pathList = Game->m_Registry->ReadString("Resource", "PackagePaths", ""); + numPaths = CBUtils::StrNumEntries(pathList.c_str(), ';'); + + for (int i = 0; i < numPaths; i++) { + char *path = CBUtils::StrEntry(i, pathList.c_str(), ';'); + if (path && strlen(path) > 0) { + AddPath(PATH_PACKAGE, path); + } + delete[] path; + path = NULL; + } + AddPath(PATH_PACKAGE, "data"); + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFileManager::RegisterPackages() { + RestoreCurrentDir(); + + Game->LOG(0, "Scanning packages..."); + warning("Scanning packages"); + + AnsiString extension = AnsiString(".") + AnsiString(PACKAGE_EXTENSION); + + for (int i = 0; i < m_PackagePaths.GetSize(); i++) { + boost::filesystem::path absPath = boost::filesystem::system_complete(m_PackagePaths[i]); + + //Game->LOG(0, "Scanning: %s", absPath.string().c_str()); + //printf("Scanning: %s\n", absPath.string().c_str()); + + if (!exists(absPath)) continue; + + // scan files + boost::filesystem::directory_iterator endIter; + for (boost::filesystem::directory_iterator dit(absPath); dit != endIter; ++dit) { + if (!is_directory((*dit).status())) { + AnsiString fileName = (*dit).path().string(); + + if (!IsValidPackage(fileName)) continue; + + warning("%s", fileName.c_str()); + //printf("%s\n", fileName.c_str()); + if (!StringUtil::CompareNoCase(extension, PathUtil::GetExtension(fileName))) continue; + warning("Registered"); + RegisterPackage(absPath.string().c_str(), dit->path().filename().string().c_str()); + } + } + } + + + Game->LOG(0, " Registered %d files in %d package(s)", m_Files.size(), m_Packages.GetSize()); + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFileManager::RegisterPackage(const char *Path, const char *Name, bool SearchSignature) { + char Filename[MAX_PATH]; + sprintf(Filename, "%s%s", Path, Name); + + FILE *f = fopen(Filename, "rb"); + if (!f) { + Game->LOG(0, " Error opening package file '%s'. Ignoring.", Filename); + return S_OK; + } + + uint32 AbosulteOffset = 0; + bool BoundToExe = false; + + if (SearchSignature) { + uint32 Offset; + if (!FindPackageSignature(f, &Offset)) { + fclose(f); + return S_OK; + } else { + fseek(f, Offset, SEEK_SET); + AbosulteOffset = Offset; + BoundToExe = true; + } + } + + TPackageHeader hdr; + fread(&hdr, sizeof(TPackageHeader), 1, f); + if (hdr.Magic1 != PACKAGE_MAGIC_1 || hdr.Magic2 != PACKAGE_MAGIC_2 || hdr.PackageVersion > PACKAGE_VERSION) { + Game->LOG(0, " Invalid header in package file '%s'. Ignoring.", Filename); + fclose(f); + return S_OK; + } + + if (hdr.PackageVersion != PACKAGE_VERSION) { + Game->LOG(0, " Warning: package file '%s' is outdated.", Filename); + } + + // new in v2 + if (hdr.PackageVersion == PACKAGE_VERSION) { + uint32 DirOffset; + fread(&DirOffset, sizeof(uint32), 1, f); + DirOffset += AbosulteOffset; + fseek(f, DirOffset, SEEK_SET); + } + + for (int i = 0; i < hdr.NumDirs; i++) { + CBPackage *pkg = new CBPackage(Game); + if (!pkg) return E_FAIL; + + pkg->m_BoundToExe = BoundToExe; + + // read package info + byte NameLength; + fread(&NameLength, sizeof(byte ), 1, f); + pkg->m_Name = new char[NameLength]; + fread(pkg->m_Name, NameLength, 1, f); + fread(&pkg->m_CD, sizeof(byte ), 1, f); + pkg->m_Priority = hdr.Priority; + + if (!hdr.MasterIndex) pkg->m_CD = 0; // override CD to fixed disk + m_Packages.Add(pkg); + + + // read file entries + uint32 NumFiles; + fread(&NumFiles, sizeof(uint32), 1, f); + + for (int j = 0; j < NumFiles; j++) { + char *Name; + uint32 Offset, Length, CompLength, Flags, TimeDate1, TimeDate2; + + fread(&NameLength, sizeof(byte ), 1, f); + Name = new char[NameLength]; + fread(Name, NameLength, 1, f); + + // v2 - xor name + if (hdr.PackageVersion == PACKAGE_VERSION) { + for (int k = 0; k < NameLength; k++) { + ((byte *)Name)[k] ^= 'D'; + } + } + + // some old version of ProjectMan writes invalid directory entries + // so at least prevent strupr from corrupting memory + Name[NameLength - 1] = '\0'; + + + CBPlatform::strupr(Name); + + fread(&Offset, sizeof(uint32), 1, f); + Offset += AbosulteOffset; + fread(&Length, sizeof(uint32), 1, f); + fread(&CompLength, sizeof(uint32), 1, f); + fread(&Flags, sizeof(uint32), 1, f); + + if (hdr.PackageVersion == PACKAGE_VERSION) { + fread(&TimeDate1, sizeof(uint32), 1, f); + fread(&TimeDate2, sizeof(uint32), 1, f); + } + + m_FilesIter = m_Files.find(Name); + if (m_FilesIter == m_Files.end()) { + CBFileEntry *file = new CBFileEntry(Game); + file->m_Package = pkg; + file->m_Offset = Offset; + file->m_Length = Length; + file->m_CompressedLength = CompLength; + file->m_Flags = Flags; + + m_Files[Name] = file; + } else { + // current package has lower CD number or higher priority, than the registered + if (pkg->m_CD < m_FilesIter->second->m_Package->m_CD || pkg->m_Priority > m_FilesIter->second->m_Package->m_Priority) { + m_FilesIter->second->m_Package = pkg; + m_FilesIter->second->m_Offset = Offset; + m_FilesIter->second->m_Length = Length; + m_FilesIter->second->m_CompressedLength = CompLength; + m_FilesIter->second->m_Flags = Flags; + } + } + delete [] Name; + } + } + + + fclose(f); + + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBFileManager::IsValidPackage(const AnsiString &fileName) const { + AnsiString plainName = PathUtil::GetFileNameWithoutExtension(fileName); + + // check for device-type specific packages + if (StringUtil::StartsWith(plainName, "xdevice_", true)) { + return StringUtil::CompareNoCase(plainName, "xdevice_" + Game->GetDeviceType()); + } + return true; +} + +////////////////////////////////////////////////////////////////////////// +FILE *CBFileManager::OpenPackage(char *Name) { + RestoreCurrentDir(); + + FILE *ret = NULL; + char Filename[MAX_PATH]; + + for (int i = 0; i < m_PackagePaths.GetSize(); i++) { + sprintf(Filename, "%s%s.%s", m_PackagePaths[i], Name, PACKAGE_EXTENSION); + ret = fopen(Filename, "rb"); + if (ret != NULL) return ret; + } + return NULL; +} + + +////////////////////////////////////////////////////////////////////////// +FILE *CBFileManager::OpenSingleFile(char *Name) { + RestoreCurrentDir(); + + FILE *ret = NULL; + char Filename[MAX_PATH]; + + for (int i = 0; i < m_SinglePaths.GetSize(); i++) { + sprintf(Filename, "%s%s", m_SinglePaths[i], Name); + ret = fopen(Filename, "rb"); + if (ret != NULL) return ret; + } + + // didn't find in search paths, try to open directly + return fopen(Name, "rb"); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFileManager::GetFullPath(char *Filename, char *Fullname) { + RestoreCurrentDir(); + + FILE *f = NULL; + bool found = false; + + for (int i = 0; i < m_SinglePaths.GetSize(); i++) { + sprintf(Fullname, "%s%s", m_SinglePaths[i], Filename); + f = fopen(Fullname, "rb"); + if (f) { + fclose(f); + found = true; + break; + } + } + + if (!found) { + f = fopen(Filename, "rb"); + if (f) { + fclose(f); + found = true; + strcpy(Fullname, Filename); + } + } + + return found; +} + + +////////////////////////////////////////////////////////////////////////// +CBFileEntry *CBFileManager::GetPackageEntry(const char *Filename) { + char *upc_name = new char[strlen(Filename) + 1]; + strcpy(upc_name, Filename); + CBPlatform::strupr(upc_name); + + CBFileEntry *ret = NULL; + m_FilesIter = m_Files.find(upc_name); + if (m_FilesIter != m_Files.end()) ret = m_FilesIter->second; + + delete [] upc_name; + + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +CBFile *CBFileManager::OpenFile(const char *Filename, bool AbsPathWarning) { + if (strcmp(Filename, "") == 0) return NULL; + //Game->LOG(0, "open file: %s", Filename); +#ifdef __WIN32__ + if (Game->m_DEBUG_DebugMode && Game->m_DEBUG_AbsolutePathWarning && AbsPathWarning) { + char Drive[_MAX_DRIVE]; + _splitpath(Filename, Drive, NULL, NULL, NULL); + if (Drive[0] != '\0') { + Game->LOG(0, "WARNING: Referencing absolute path '%s'. The game will NOT work on another computer.", Filename); + } + } +#endif + + CBFile *File = OpenFileRaw(Filename); + if (File) m_OpenFiles.Add(File); + return File; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFileManager::CloseFile(CBFile *File) { + for (int i = 0; i < m_OpenFiles.GetSize(); i++) { + if (m_OpenFiles[i] == File) { + m_OpenFiles[i]->Close(); + delete m_OpenFiles[i]; + m_OpenFiles.RemoveAt(i); + return S_OK; + } + } + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +CBFile *CBFileManager::OpenFileRaw(const char *Filename) { + RestoreCurrentDir(); + + if (scumm_strnicmp(Filename, "savegame:", 9) == 0) { + CBSaveThumbFile *SaveThumbFile = new CBSaveThumbFile(Game); + if (SUCCEEDED(SaveThumbFile->Open(Filename))) return SaveThumbFile; + else { + delete SaveThumbFile; + return NULL; + } + } + + CBDiskFile *DiskFile = new CBDiskFile(Game); + if (SUCCEEDED(DiskFile->Open(Filename))) return DiskFile; + + delete DiskFile; + + CBPkgFile *PkgFile = new CBPkgFile(Game); + if (SUCCEEDED(PkgFile->Open(Filename))) return PkgFile; + + delete PkgFile; + + CBResourceFile *ResFile = new CBResourceFile(Game); + if (SUCCEEDED(ResFile->Open(Filename))) return ResFile; + + delete ResFile; + + return NULL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFileManager::RestoreCurrentDir() { + if (!m_BasePath) return S_OK; + else { + if (!chdir(m_BasePath)) return S_OK; + else return E_FAIL; + } +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFileManager::SetBasePath(char *Path) { + Cleanup(); + + if (Path) { + m_BasePath = new char[strlen(Path) + 1]; + strcpy(m_BasePath, Path); + } + + InitPaths(); + RegisterPackages(); + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFileManager::FindPackageSignature(FILE *f, uint32 *Offset) { + byte buf[32768]; + + byte Signature[8]; + ((uint32 *)Signature)[0] = PACKAGE_MAGIC_1; + ((uint32 *)Signature)[1] = PACKAGE_MAGIC_2; + + fseek(f, 0, SEEK_END); + uint32 FileSize = ftell(f); + + int StartPos = 1024 * 1024; + + int BytesRead = StartPos; + + while (BytesRead < FileSize - 16) { + int ToRead = MIN(32768, FileSize - BytesRead); + fseek(f, StartPos, SEEK_SET); + int ActuallyRead = fread(buf, 1, ToRead, f); + if (ActuallyRead != ToRead) return false; + + for (int i = 0; i < ToRead - 8; i++) + if (!memcmp(buf + i, Signature, 8)) { + *Offset = StartPos + i; + return true; + } + + BytesRead = BytesRead + ToRead - 16; + StartPos = StartPos + ToRead - 16; + + } + return false; + +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BFileManager.h b/engines/wintermute/BFileManager.h new file mode 100644 index 0000000000..e585841a4a --- /dev/null +++ b/engines/wintermute/BFileManager.h @@ -0,0 +1,81 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BFILEMANAGER_H +#define WINTERMUTE_BFILEMANAGER_H + + +#include +#include "coll_templ.h" +#include "BFileEntry.h" +#include "common/archive.h" + +namespace WinterMute { +class CBFile; +class CBFileManager: CBBase { +public: + bool FindPackageSignature(FILE *f, uint32 *Offset); + HRESULT Cleanup(); + HRESULT SetBasePath(char *Path); + HRESULT RestoreCurrentDir(); + char *m_BasePath; + bool GetFullPath(char *Filename, char *Fullname); + CBFile *OpenFileRaw(const char *Filename); + HRESULT CloseFile(CBFile *File); + CBFile *OpenFile(const char *Filename, bool AbsPathWarning = true); + CBFileEntry *GetPackageEntry(const char *Filename); + FILE *OpenSingleFile(char *Name); + FILE *OpenPackage(char *Name); + HRESULT RegisterPackages(); + HRESULT InitPaths(); + HRESULT ReloadPaths(); + typedef enum { + PATH_PACKAGE, PATH_SINGLE + } TPathType; + HRESULT AddPath(TPathType Type, const char *Path); + HRESULT RequestCD(int CD, char *PackageFile, char *Filename); + HRESULT SaveFile(char *Filename, byte *Buffer, uint32 BufferSize, bool Compressed = false, byte *PrefixBuffer = NULL, uint32 PrefixSize = 0); + byte *ReadWholeFile(const char *Filename, uint32 *Size = NULL, bool MustExist = true); + CBFileManager(CBGame *inGame = NULL); + virtual ~CBFileManager(); + CBArray m_SinglePaths; + CBArray m_PackagePaths; + CBArray m_Packages; + CBArray m_OpenFiles; + + std::map m_Files; +private: + HRESULT RegisterPackage(const char *Path, const char *Name, bool SearchSignature = false); + std::map::iterator m_FilesIter; + bool IsValidPackage(const AnsiString &fileName) const; + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BFont.cpp b/engines/wintermute/BFont.cpp new file mode 100644 index 0000000000..93d870875d --- /dev/null +++ b/engines/wintermute/BFont.cpp @@ -0,0 +1,206 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BFont.h" +#include "BFontBitmap.h" +#include "BParser.h" +#include "BFileManager.h" +#include "BFontTT.h" +#include "BGame.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +IMPLEMENT_PERSISTENT(CBFont, false) + +////////////////////////////////////////////////////////////////////// +CBFont::CBFont(CBGame *inGame): CBObject(inGame) { + +} + + +////////////////////////////////////////////////////////////////////// +CBFont::~CBFont() { +} + + +////////////////////////////////////////////////////////////////////// +void CBFont::DrawText(byte *text, int x, int y, int width, TTextAlign align, int max_height, int MaxLenght) { +} + + +////////////////////////////////////////////////////////////////////// +int CBFont::GetTextHeight(byte *text, int width) { + return 0; +} + + +////////////////////////////////////////////////////////////////////// +int CBFont::GetTextWidth(byte *text, int MaxLenght) { + return 0; +} + +/* +////////////////////////////////////////////////////////////////////// +HRESULT CBFont::LoadFile(char * Filename) +{ + BYTE* Buffer = Game->m_FileManager->ReadWholeFile(Filename); + if(Buffer==NULL){ + Game->LOG(0, "CBFont::LoadFile failed for file '%s'", Filename); + return E_FAIL; + } + + HRESULT ret; + + m_Filename = new char [strlen(Filename)+1]; + strcpy(m_Filename, Filename); + + if(FAILED(ret = LoadBuffer(Buffer))) Game->LOG(0, "Error parsing FONT file '%s'", Filename); + + delete [] Buffer; + + return ret; +} + + +TOKEN_DEF_START + TOKEN_DEF (FONT) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////// +HRESULT CBFont::LoadBuffer(byte * Buffer) +{ + TOKEN_TABLE_START(commands) + TOKEN_TABLE (FONT) + TOKEN_TABLE_END + + char* params; + int cmd; + CBParser parser(Game); + + if(parser.GetCommand ((char**)&Buffer, commands, (char**)¶ms)!=TOKEN_FONT){ + Game->LOG(0, "'FONT' keyword expected."); + return E_FAIL; + } + Buffer = (byte *)params; + + while ((cmd = parser.GetCommand ((char**)&Buffer, commands, (char**)¶ms)) > 0) + { + switch (cmd) + { + case TOKEN_IMAGE: + surface_file = (char*)params; + break; + + case TOKEN_TRANSPARENT: + parser.ScanStr(params, "%d,%d,%d", &r, &g, &b); + custom_trans = true; + break; + } + + + } + if (cmd == PARSERR_TOKENNOTFOUND){ + Game->LOG(0, "Syntax error in FONT definition"); + return E_FAIL; + } + + return S_OK; +} +*/ + +////////////////////////////////////////////////////////////////////////// +int CBFont::GetLetterHeight() { + return 0; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFont::Persist(CBPersistMgr *PersistMgr) { + + CBObject::Persist(PersistMgr); + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +CBFont *CBFont::CreateFromFile(CBGame *Game, char *Filename) { + if (IsTrueType(Game, Filename)) { + CBFontTT *Font = new CBFontTT(Game); + if (Font) { + if (FAILED(Font->LoadFile(Filename))) { + delete Font; + return NULL; + } + } + return Font; + } else { + CBFontBitmap *Font = new CBFontBitmap(Game); + if (Font) { + if (FAILED(Font->LoadFile(Filename))) { + delete Font; + return NULL; + } + } + return Font; + } +} + + +TOKEN_DEF_START +TOKEN_DEF(FONT) +TOKEN_DEF(TTFONT) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +bool CBFont::IsTrueType(CBGame *Game, char *Filename) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(FONT) + TOKEN_TABLE(TTFONT) + TOKEN_TABLE_END + + + byte *Buffer = Game->m_FileManager->ReadWholeFile(Filename); + if (Buffer == NULL) return false; + + byte *WorkBuffer = Buffer; + + char *params; + CBParser parser(Game); + + bool Ret = false; + if (parser.GetCommand((char **)&WorkBuffer, commands, (char **)¶ms) == TOKEN_TTFONT) + Ret = true; + + delete [] Buffer; + return Ret; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BFont.h b/engines/wintermute/BFont.h new file mode 100644 index 0000000000..5ffba7ace4 --- /dev/null +++ b/engines/wintermute/BFont.h @@ -0,0 +1,61 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BFONT_H +#define WINTERMUTE_BFONT_H + +#include "BObject.h" + +#define NUM_CHARACTERS 256 + +namespace WinterMute { + +class CBFont: public CBObject { +public: + DECLARE_PERSISTENT(CBFont, CBObject) + virtual int GetTextWidth(byte *text, int MaxLenght = -1); + virtual int GetTextHeight(byte *text, int width); + virtual void DrawText(byte *text, int x, int y, int width, TTextAlign align = TAL_LEFT, int max_height = -1, int MaxLenght = -1); + virtual int GetLetterHeight(); + + virtual void InitLoop() {}; + + CBFont(CBGame *inGame); + virtual ~CBFont(); + + static CBFont *CreateFromFile(CBGame *Game, char *Filename); + +private: + //HRESULT LoadBuffer(byte * Buffer); + //HRESULT LoadFile(char* Filename); + static bool IsTrueType(CBGame *Game, char *Filename); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BFontBitmap.cpp b/engines/wintermute/BFontBitmap.cpp new file mode 100644 index 0000000000..e7a1466ed0 --- /dev/null +++ b/engines/wintermute/BFontBitmap.cpp @@ -0,0 +1,532 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BFontBitmap.h" +#include "StringUtil.h" +#include "BParser.h" +#include "BFrame.h" +#include "BSurface.h" +#include "BGame.h" +#include "BSubFrame.h" +#include "BFrame.h" +#include "BSprite.h" +#include "BFileManager.h" +#include "PlatformSDL.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +IMPLEMENT_PERSISTENT(CBFontBitmap, false) + +////////////////////////////////////////////////////////////////////// +CBFontBitmap::CBFontBitmap(CBGame *inGame): CBFont(inGame) { + m_Subframe = NULL; + m_Sprite = NULL; + m_WidthsFrame = 0; + memset(m_Widths, 0, NUM_CHARACTERS); + m_TileWidth = m_TileHeight = m_NumColumns = 0; + m_FontextFix = false; + m_Freezable = false; + m_WholeCell = false; +} + + +////////////////////////////////////////////////////////////////////// +CBFontBitmap::~CBFontBitmap() { + SAFE_DELETE(m_Subframe); + SAFE_DELETE(m_Sprite); +} + + +////////////////////////////////////////////////////////////////////// +void CBFontBitmap::DrawText(byte *text, int x, int y, int width, TTextAlign align, int max_height, int MaxLenght) { + TextHeightDraw(text, x, y, width, align, true, max_height, MaxLenght); +} + + +////////////////////////////////////////////////////////////////////// +int CBFontBitmap::GetTextHeight(byte *text, int width) { + return TextHeightDraw(text, 0, 0, width, TAL_LEFT, false); +} + + +////////////////////////////////////////////////////////////////////// +int CBFontBitmap::GetTextWidth(byte *text, int MaxLength) { + AnsiString str; + + if (Game->m_TextEncoding == TEXT_UTF8) { + WideString wstr = StringUtil::Utf8ToWide(Utf8String((char *)text)); + str = StringUtil::WideToAnsi(wstr); + } else { + str = AnsiString((char *)text); + } + + if (MaxLength >= 0 && str.length() > MaxLength) str = str.substr(0, MaxLength); + + int TextWidth = 0; + for (size_t i = 0; i < str.length(); i++) { + TextWidth += GetCharWidth(str[i]); + } + + return TextWidth; +} + + +////////////////////////////////////////////////////////////////////// +int CBFontBitmap::TextHeightDraw(byte *text, int x, int y, int width, TTextAlign align, bool draw, int max_height, int MaxLenght) { + if (MaxLenght == 0) return 0; + + if (text == NULL || text[0] == '\0') return m_TileHeight; + + + + AnsiString str; + + if (Game->m_TextEncoding == TEXT_UTF8) { + WideString wstr = StringUtil::Utf8ToWide(Utf8String((char *)text)); + str = StringUtil::WideToAnsi(wstr); + } else { + str = AnsiString((char *)text); + } + if (str.empty()) return 0; + + int LineLength = 0; + int RealLength = 0; + int NumLines = 0; + + int i; + + int index = -1; + int start = 0; + int end = 0; + int last_end = 0; + + bool done = false; + bool new_line = false; + bool long_line = false; + + if (draw) Game->m_Renderer->StartSpriteBatch(); + + while (!done) { + if (max_height > 0 && (NumLines + 1)*m_TileHeight > max_height) { + if (draw) Game->m_Renderer->EndSpriteBatch(); + return NumLines * m_TileHeight; + } + + index++; + + if (str[index] == ' ' && (max_height < 0 || max_height / m_TileHeight > 1)) { + end = index - 1; + RealLength = LineLength; + } + + if (str[index] == '\n') { + end = index - 1; + RealLength = LineLength; + new_line = true; + } + + if (LineLength + GetCharWidth(str[index]) > width && last_end == end) { + end = index - 1; + RealLength = LineLength; + new_line = true; + long_line = true; + } + + if (str[index + 1] == '\0' || (MaxLenght >= 0 && index == MaxLenght - 1)) { + done = true; + if (!new_line) { + end = index; + LineLength += GetCharWidth(str[index]); + RealLength = LineLength; + } + } else LineLength += GetCharWidth(str[index]); + + if ((LineLength > width) || done || new_line) { + if (end < 0) done = true; + int StartX; + switch (align) { + case TAL_CENTER: + StartX = x + (width - RealLength) / 2; + break; + case TAL_RIGHT: + StartX = x + width - RealLength; + break; + case TAL_LEFT: + StartX = x; + break; + } + for (i = start; i < end + 1; i++) { + if (draw) DrawChar(str[i], StartX, y); + StartX += GetCharWidth(str[i]); + } + y += m_TileHeight; + last_end = end; + if (long_line) end--; + start = end + 2; + index = end + 1; + LineLength = 0; + new_line = false; + long_line = false; + NumLines++; + } + } + + if (draw) Game->m_Renderer->EndSpriteBatch(); + + return NumLines * m_TileHeight; +} + + +////////////////////////////////////////////////////////////////////// +void CBFontBitmap::DrawChar(byte c, int x, int y) { + if (m_FontextFix) c--; + + int row, col; + + row = c / m_NumColumns; + col = c % m_NumColumns; + + RECT rect; + /* l t r b */ + int TileWidth; + if (m_WholeCell) TileWidth = m_TileWidth; + else TileWidth = m_Widths[c]; + + CBPlatform::SetRect(&rect, col * m_TileWidth, row * m_TileHeight, col * m_TileWidth + TileWidth, (row + 1)*m_TileHeight); + bool Handled = false; + if (m_Sprite) { + m_Sprite->GetCurrentFrame(); + if (m_Sprite->m_CurrentFrame >= 0 && m_Sprite->m_CurrentFrame < m_Sprite->m_Frames.GetSize() && m_Sprite->m_Frames[m_Sprite->m_CurrentFrame]) { + if (m_Sprite->m_Frames[m_Sprite->m_CurrentFrame]->m_Subframes.GetSize() > 0) { + m_Sprite->m_Frames[m_Sprite->m_CurrentFrame]->m_Subframes[0]->m_Surface->DisplayTrans(x, y, rect); + } + Handled = true; + } + } + if (!Handled && m_Subframe) m_Subframe->m_Surface->DisplayTrans(x, y, rect); +} + + +////////////////////////////////////////////////////////////////////// +HRESULT CBFontBitmap::LoadFile(char *Filename) { + byte *Buffer = Game->m_FileManager->ReadWholeFile(Filename); + if (Buffer == NULL) { + Game->LOG(0, "CBFontBitmap::LoadFile failed for file '%s'", Filename); + return E_FAIL; + } + + HRESULT ret; + + m_Filename = new char [strlen(Filename) + 1]; + strcpy(m_Filename, Filename); + + if (FAILED(ret = LoadBuffer(Buffer))) Game->LOG(0, "Error parsing FONT file '%s'", Filename); + + delete [] Buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(FONTEXT_FIX) +TOKEN_DEF(FONT) +TOKEN_DEF(IMAGE) +TOKEN_DEF(TRANSPARENT) +TOKEN_DEF(COLUMNS) +TOKEN_DEF(TILE_WIDTH) +TOKEN_DEF(TILE_HEIGHT) +TOKEN_DEF(DEFAULT_WIDTH) +TOKEN_DEF(WIDTHS) +TOKEN_DEF(AUTO_WIDTH) +TOKEN_DEF(SPACE_WIDTH) +TOKEN_DEF(EXPAND_WIDTH) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF(SPRITE) +TOKEN_DEF(WIDTHS_FRAME) +TOKEN_DEF(PAINT_WHOLE_CELL) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////// +HRESULT CBFontBitmap::LoadBuffer(byte *Buffer) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(FONTEXT_FIX) + TOKEN_TABLE(FONT) + TOKEN_TABLE(IMAGE) + TOKEN_TABLE(TRANSPARENT) + TOKEN_TABLE(COLUMNS) + TOKEN_TABLE(TILE_WIDTH) + TOKEN_TABLE(TILE_HEIGHT) + TOKEN_TABLE(DEFAULT_WIDTH) + TOKEN_TABLE(WIDTHS) + TOKEN_TABLE(AUTO_WIDTH) + TOKEN_TABLE(SPACE_WIDTH) + TOKEN_TABLE(EXPAND_WIDTH) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE(SPRITE) + TOKEN_TABLE(WIDTHS_FRAME) + TOKEN_TABLE(PAINT_WHOLE_CELL) + TOKEN_TABLE_END + + char *params; + int cmd; + CBParser parser(Game); + + if (parser.GetCommand((char **)&Buffer, commands, (char **)¶ms) != TOKEN_FONT) { + Game->LOG(0, "'FONT' keyword expected."); + return E_FAIL; + } + Buffer = (byte *)params; + + int widths[300]; + int num = 0, default_width = 8; + int last_width = 0; + int i; + int r = 255, g = 255, b = 255; + bool custom_trans = false; + char *surface_file = NULL; + char *sprite_file = NULL; + + bool AutoWidth = false; + int SpaceWidth = 0; + int ExpandWidth = 0; + + while ((cmd = parser.GetCommand((char **)&Buffer, commands, (char **)¶ms)) > 0) { + + switch (cmd) { + case TOKEN_IMAGE: + surface_file = (char *)params; + break; + + case TOKEN_SPRITE: + sprite_file = (char *)params; + break; + + case TOKEN_TRANSPARENT: + parser.ScanStr(params, "%d,%d,%d", &r, &g, &b); + custom_trans = true; + break; + + case TOKEN_WIDTHS: + parser.ScanStr(params, "%D", widths, &num); + for (i = 0; last_width < NUM_CHARACTERS, num > 0; last_width++, num--, i++) { + m_Widths[last_width] = (byte )widths[i]; + } + break; + + case TOKEN_DEFAULT_WIDTH: + parser.ScanStr(params, "%d", &default_width); + break; + + case TOKEN_WIDTHS_FRAME: + parser.ScanStr(params, "%d", &m_WidthsFrame); + break; + + case TOKEN_COLUMNS: + parser.ScanStr(params, "%d", &m_NumColumns); + break; + + case TOKEN_TILE_WIDTH: + parser.ScanStr(params, "%d", &m_TileWidth); + break; + + case TOKEN_TILE_HEIGHT: + parser.ScanStr(params, "%d", &m_TileHeight); + break; + + case TOKEN_AUTO_WIDTH: + parser.ScanStr(params, "%b", &AutoWidth); + break; + + case TOKEN_FONTEXT_FIX: + parser.ScanStr(params, "%b", &m_FontextFix); + break; + + case TOKEN_PAINT_WHOLE_CELL: + parser.ScanStr(params, "%b", &m_WholeCell); + break; + + case TOKEN_SPACE_WIDTH: + parser.ScanStr(params, "%d", &SpaceWidth); + break; + + case TOKEN_EXPAND_WIDTH: + parser.ScanStr(params, "%d", &ExpandWidth); + break; + + case TOKEN_EDITOR_PROPERTY: + ParseEditorProperty((byte *)params, false); + break; + } + + } + if (cmd == PARSERR_TOKENNOTFOUND) { + Game->LOG(0, "Syntax error in FONT definition"); + return E_FAIL; + } + + if (sprite_file != NULL) { + SAFE_DELETE(m_Sprite); + m_Sprite = new CBSprite(Game, this); + if (!m_Sprite || FAILED(m_Sprite->LoadFile(sprite_file))) SAFE_DELETE(m_Sprite); + } + + if (surface_file != NULL && !m_Sprite) { + m_Subframe = new CBSubFrame(Game); + if (custom_trans) m_Subframe->SetSurface(surface_file, false, r, g, b); + else m_Subframe->SetSurface(surface_file); + } + + + if (((m_Subframe == NULL || m_Subframe->m_Surface == NULL) && m_Sprite == NULL) || m_NumColumns == 0 || m_TileWidth == 0 || m_TileHeight == 0) { + Game->LOG(0, "Incomplete font definition"); + return E_FAIL; + } + + if (AutoWidth) { + // calculate characters width + GetWidths(); + + // do we need to modify widths? + if (ExpandWidth != 0) { + for (i = 0; i < NUM_CHARACTERS; i++) { + int NewWidth = (int)m_Widths[i] + ExpandWidth; + if (NewWidth < 0) NewWidth = 0; + + m_Widths[i] = (byte )NewWidth; + } + } + + // handle space character + char SpaceChar = ' '; + if (m_FontextFix) SpaceChar--; + + if (SpaceWidth != 0) m_Widths[SpaceChar] = SpaceWidth; + else { + if (m_Widths[SpaceChar] == ExpandWidth || m_Widths[SpaceChar] == 0) { + m_Widths[SpaceChar] = (m_Widths['m'] + m_Widths['i']) / 2; + } + } + } else { + for (i = last_width; i < NUM_CHARACTERS; i++) m_Widths[i] = default_width; + } + + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFontBitmap::Persist(CBPersistMgr *PersistMgr) { + + CBFont::Persist(PersistMgr); + PersistMgr->Transfer(TMEMBER(m_NumColumns)); + + PersistMgr->Transfer(TMEMBER(m_Subframe)); + PersistMgr->Transfer(TMEMBER(m_TileHeight)); + PersistMgr->Transfer(TMEMBER(m_TileWidth)); + PersistMgr->Transfer(TMEMBER(m_Sprite)); + PersistMgr->Transfer(TMEMBER(m_WidthsFrame)); + + if (PersistMgr->m_Saving) + PersistMgr->PutBytes(m_Widths, sizeof(m_Widths)); + else + PersistMgr->GetBytes(m_Widths, sizeof(m_Widths)); + + + PersistMgr->Transfer(TMEMBER(m_FontextFix)); + PersistMgr->Transfer(TMEMBER(m_WholeCell)); + + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +int CBFontBitmap::GetCharWidth(byte Index) { + if (m_FontextFix) Index--; + return m_Widths[Index]; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFontBitmap::GetWidths() { + CBSurface *surf = NULL; + + if (m_Sprite) { + if (m_WidthsFrame >= 0 && m_WidthsFrame < m_Sprite->m_Frames.GetSize()) { + if (m_Sprite->m_Frames[m_WidthsFrame] && m_Sprite->m_Frames[m_WidthsFrame]->m_Subframes.GetSize() > 0) { + surf = m_Sprite->m_Frames[m_WidthsFrame]->m_Subframes[0]->m_Surface; + } + } + } + if (surf == NULL && m_Subframe) surf = m_Subframe->m_Surface; + if (!surf || FAILED(surf->StartPixelOp())) return E_FAIL; + + + for (int i = 0; i < NUM_CHARACTERS; i++) { + int xxx = (i % m_NumColumns) * m_TileWidth; + int yyy = (i / m_NumColumns) * m_TileHeight; + + + int min_col = -1; + for (int row = 0; row < m_TileHeight; row++) { + for (int col = m_TileWidth - 1; col >= min_col + 1; col--) { + if (xxx + col < 0 || xxx + col >= surf->GetWidth() || yyy + row < 0 || yyy + row >= surf->GetHeight()) continue; + if (!surf->IsTransparentAtLite(xxx + col, yyy + row)) { + //min_col = col; + min_col = std::max(col, min_col); + break; + } + } + if (min_col == m_TileWidth - 1) break; + } + + m_Widths[i] = min_col + 1; + } + surf->EndPixelOp(); + /* + Game->LOG(0, "----- %s ------", m_Filename); + for(int j=0; j<16; j++) + { + Game->LOG(0, "%02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d", m_Widths[j*16+0], m_Widths[j*16+1], m_Widths[j*16+2], m_Widths[j*16+3], m_Widths[j*16+4], m_Widths[j*16+5], m_Widths[j*16+6], m_Widths[j*16+7], m_Widths[j*16+8], m_Widths[j*16+9], m_Widths[j*16+10], m_Widths[j*16+11], m_Widths[j*16+12], m_Widths[j*16+13], m_Widths[j*16+14], m_Widths[j*16+15]); + } + */ + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +int CBFontBitmap::GetLetterHeight() { + return m_TileHeight; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BFontBitmap.h b/engines/wintermute/BFontBitmap.h new file mode 100644 index 0000000000..c56c192e63 --- /dev/null +++ b/engines/wintermute/BFontBitmap.h @@ -0,0 +1,72 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BFONTBITMAP_H +#define WINTERMUTE_BFONTBITMAP_H + + +#include "BFont.h" + +namespace WinterMute { +class CBSubFrame; +class CBFontBitmap : public CBFont { +public: + DECLARE_PERSISTENT(CBFontBitmap, CBFont) + HRESULT LoadBuffer(byte *Buffer); + HRESULT LoadFile(char *Filename); + virtual int GetTextWidth(byte *text, int MaxLength = -1); + virtual int GetTextHeight(byte *text, int width); + virtual void DrawText(byte *text, int x, int y, int width, TTextAlign align = TAL_LEFT, int max_height = -1, int MaxLenght = -1); + virtual int GetLetterHeight(); + + CBFontBitmap(CBGame *inGame); + virtual ~CBFontBitmap(); + + + HRESULT GetWidths(); + CBSprite *m_Sprite; + int m_WidthsFrame; + bool m_FontextFix; + int m_NumColumns; + int m_TileHeight; + int m_TileWidth; + byte m_Widths[NUM_CHARACTERS]; + CBSubFrame *m_Subframe; + bool m_WholeCell; + +private: + int GetCharWidth(byte Index); + void DrawChar(byte c, int x, int y); + + int TextHeightDraw(byte *text, int x, int y, int width, TTextAlign align, bool draw, int max_height = -1, int MaxLenght = -1); + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BFontStorage.cpp b/engines/wintermute/BFontStorage.cpp new file mode 100644 index 0000000000..cb14714550 --- /dev/null +++ b/engines/wintermute/BFontStorage.cpp @@ -0,0 +1,155 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BFontStorage.h" +#include "BGame.h" +#include "BFont.h" +#include "PlatformSDL.h" +#include "common/str.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +IMPLEMENT_PERSISTENT(CBFontStorage, true) + +////////////////////////////////////////////////////////////////////////// +CBFontStorage::CBFontStorage(CBGame *inGame): CBBase(inGame) { + m_FTLibrary = NULL; + InitFreeType(); +} + + +////////////////////////////////////////////////////////////////////////// +CBFontStorage::~CBFontStorage() { + Cleanup(true); +} + + +////////////////////////////////////////////////////////////////////////// +void CBFontStorage::InitFreeType() { + FT_Error error = FT_Init_FreeType(&m_FTLibrary); + if (error) { + Game->LOG(0, "Error initializing FreeType library."); + } +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFontStorage::Cleanup(bool Warn) { + int i; + + for (i = 0; i < m_Fonts.GetSize(); i++) { + if (Warn) Game->LOG(0, "Removing orphan font '%s'", m_Fonts[i]->m_Filename); + delete m_Fonts[i]; + } + m_Fonts.RemoveAll(); + + + if (m_FTLibrary) FT_Done_FreeType(m_FTLibrary); + + + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFontStorage::InitLoop() { + for (int i = 0; i < m_Fonts.GetSize(); i++) { + m_Fonts[i]->InitLoop(); + } + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +CBFont *CBFontStorage::AddFont(char *Filename) { + if (!Filename) return NULL; + + for (int i = 0; i < m_Fonts.GetSize(); i++) { + if (scumm_stricmp(m_Fonts[i]->m_Filename, Filename) == 0) { + m_Fonts[i]->m_RefCount++; + return m_Fonts[i]; + } + } + + /* + CBFont* font = new CBFont(Game); + if(!font) return NULL; + + if(FAILED(font->LoadFile(Filename))){ + delete font; + return NULL; + } + else { + font->m_RefCount = 1; + m_Fonts.Add(font); + return font; + } + */ + CBFont *font = CBFont::CreateFromFile(Game, Filename); + if (font) { + font->m_RefCount = 1; + m_Fonts.Add(font); + } + return font; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFontStorage::RemoveFont(CBFont *Font) { + if (!Font) return E_FAIL; + + for (int i = 0; i < m_Fonts.GetSize(); i++) { + if (m_Fonts[i] == Font) { + m_Fonts[i]->m_RefCount--; + if (m_Fonts[i]->m_RefCount <= 0) { + delete m_Fonts[i]; + m_Fonts.RemoveAt(i); + } + break; + } + } + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFontStorage::Persist(CBPersistMgr *PersistMgr) { + + if (!PersistMgr->m_Saving) Cleanup(false); + + PersistMgr->Transfer(TMEMBER(Game)); + m_Fonts.Persist(PersistMgr); + + if (!PersistMgr->m_Saving) InitFreeType(); + + return S_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BFontStorage.h b/engines/wintermute/BFontStorage.h new file mode 100644 index 0000000000..6dc2273022 --- /dev/null +++ b/engines/wintermute/BFontStorage.h @@ -0,0 +1,66 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BFONTSTORAGE_H +#define WINTERMUTE_BFONTSTORAGE_H + + +#include "BBase.h" +#include "persistent.h" +#include "coll_templ.h" + +#include +#include FT_FREETYPE_H + +namespace WinterMute { + +class CBFont; + +class CBFontStorage : public CBBase { +public: + DECLARE_PERSISTENT(CBFontStorage, CBBase) + HRESULT Cleanup(bool Warn = false); + HRESULT RemoveFont(CBFont *Font); + CBFont *AddFont(char *Filename); + CBFontStorage(CBGame *inGame); + virtual ~CBFontStorage(); + CBArray m_Fonts; + HRESULT InitLoop(); + + FT_Library GetFTLibrary() const { + return m_FTLibrary; + } + +private: + void InitFreeType(); + FT_Library m_FTLibrary; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BFontTT.cpp b/engines/wintermute/BFontTT.cpp new file mode 100644 index 0000000000..a1ca6577fa --- /dev/null +++ b/engines/wintermute/BFontTT.cpp @@ -0,0 +1,853 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include +#include FT_FREETYPE_H +#include "dcgf.h" +#include "BFile.h" +#include "BFontTT.h" +#include "FontGlyphCache.h" +#include "PathUtil.h" +#include "StringUtil.h" +#include "MathUtil.h" +#include "BRenderSDL.h" +#include "BSurfaceSDL.h" +#include "BParser.h" +#include "BGame.h" +#include "BFileManager.h" +#include "utils.h" +#include "PlatformSDL.h" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CBFontTT, false) + +////////////////////////////////////////////////////////////////////////// +CBFontTT::CBFontTT(CBGame *inGame): CBFont(inGame) { + m_FontHeight = 12; + m_IsBold = m_IsItalic = m_IsUnderline = m_IsStriked = false; + + m_FontFile = NULL; + + for (int i = 0; i < NUM_CACHED_TEXTS; i++) m_CachedTexts[i] = NULL; + + + m_FTFace = NULL; + m_FTStream = NULL; + + m_GlyphCache = NULL; + + m_Ascender = m_Descender = m_LineHeight = m_PointSize = m_UnderlinePos = 0; + m_HorDpi = m_VertDpi = 0; + m_MaxCharWidth = m_MaxCharHeight = 0; +} + +////////////////////////////////////////////////////////////////////////// +CBFontTT::~CBFontTT(void) { + ClearCache(); + + for (int i = 0; i < m_Layers.GetSize(); i++) { + delete m_Layers[i]; + } + m_Layers.RemoveAll(); + + delete[] m_FontFile; + m_FontFile = NULL; + + delete m_GlyphCache; + m_GlyphCache = NULL; + + if (m_FTFace) { + FT_Done_Face(m_FTFace); + m_FTFace = NULL; + } + delete[] m_FTStream; + m_FTStream = NULL; + +} + + +////////////////////////////////////////////////////////////////////////// +void CBFontTT::ClearCache() { + for (int i = 0; i < NUM_CACHED_TEXTS; i++) { + if (m_CachedTexts[i]) delete m_CachedTexts[i]; + m_CachedTexts[i] = NULL; + } + +} + +////////////////////////////////////////////////////////////////////////// +void CBFontTT::InitLoop() { + // we need more aggressive cache management on iOS not to waste too much memory on fonts + if (Game->m_ConstrainedMemory) { + // purge all cached images not used in the last frame + for (int i = 0; i < NUM_CACHED_TEXTS; i++) { + if (m_CachedTexts[i] == NULL) continue; + + if (!m_CachedTexts[i]->m_Marked) { + delete m_CachedTexts[i]; + m_CachedTexts[i] = NULL; + } else m_CachedTexts[i]->m_Marked = false; + } + } +} + +////////////////////////////////////////////////////////////////////////// +int CBFontTT::GetTextWidth(byte *Text, int MaxLength) { + WideString text; + + if (Game->m_TextEncoding == TEXT_UTF8) text = StringUtil::Utf8ToWide((char *)Text); + else text = StringUtil::AnsiToWide((char *)Text); + + if (MaxLength >= 0 && text.length() > MaxLength) text = text.substr(0, MaxLength); + + int textWidth, textHeight; + MeasureText(text, -1, -1, textWidth, textHeight); + + return textWidth; +} + +////////////////////////////////////////////////////////////////////////// +int CBFontTT::GetTextHeight(byte *Text, int Width) { + WideString text; + + if (Game->m_TextEncoding == TEXT_UTF8) text = StringUtil::Utf8ToWide((char *)Text); + else text = StringUtil::AnsiToWide((char *)Text); + + + int textWidth, textHeight; + MeasureText(text, Width, -1, textWidth, textHeight); + + return textHeight; +} + + +////////////////////////////////////////////////////////////////////////// +void CBFontTT::DrawText(byte *Text, int X, int Y, int Width, TTextAlign Align, int MaxHeight, int MaxLength) { + if (Text == NULL || strcmp((char *)Text, "") == 0) return; + + WideString text; + + if (Game->m_TextEncoding == TEXT_UTF8) text = StringUtil::Utf8ToWide((char *)Text); + else text = StringUtil::AnsiToWide((char *)Text); + + if (MaxLength >= 0 && text.length() > MaxLength) text = text.substr(0, MaxLength); + + CBRenderSDL *m_Renderer = (CBRenderSDL *)Game->m_Renderer; + + // find cached surface, if exists + int MinPriority = INT_MAX; + int MinIndex = -1; + CBSurface *Surface = NULL; + int textOffset = 0; + + for (int i = 0; i < NUM_CACHED_TEXTS; i++) { + if (m_CachedTexts[i] == NULL) { + MinPriority = 0; + MinIndex = i; + } else { + if (m_CachedTexts[i]->m_Text == text && m_CachedTexts[i]->m_Align == Align && m_CachedTexts[i]->m_Width == Width && m_CachedTexts[i]->m_MaxHeight == MaxHeight && m_CachedTexts[i]->m_MaxLength == MaxLength) { + Surface = m_CachedTexts[i]->m_Surface; + textOffset = m_CachedTexts[i]->m_TextOffset; + m_CachedTexts[i]->m_Priority++; + m_CachedTexts[i]->m_Marked = true; + break; + } else { + if (m_CachedTexts[i]->m_Priority < MinPriority) { + MinPriority = m_CachedTexts[i]->m_Priority; + MinIndex = i; + } + } + } + } + + // not found, create one + if (!Surface) { + Surface = RenderTextToTexture(text, Width, Align, MaxHeight, textOffset); + if (Surface) { + // write surface to cache + if (m_CachedTexts[MinIndex] != NULL) delete m_CachedTexts[MinIndex]; + m_CachedTexts[MinIndex] = new CBCachedTTFontText; + + m_CachedTexts[MinIndex]->m_Surface = Surface; + m_CachedTexts[MinIndex]->m_Align = Align; + m_CachedTexts[MinIndex]->m_Width = Width; + m_CachedTexts[MinIndex]->m_MaxHeight = MaxHeight; + m_CachedTexts[MinIndex]->m_MaxLength = MaxLength; + m_CachedTexts[MinIndex]->m_Priority = 1; + m_CachedTexts[MinIndex]->m_Text = text; + m_CachedTexts[MinIndex]->m_TextOffset = textOffset; + m_CachedTexts[MinIndex]->m_Marked = true; + } + } + + + // and paint it + if (Surface) { + RECT rc; + CBPlatform::SetRect(&rc, 0, 0, Surface->GetWidth(), Surface->GetHeight()); + for (int i = 0; i < m_Layers.GetSize(); i++) { + uint32 Color = m_Layers[i]->m_Color; + uint32 OrigForceAlpha = m_Renderer->m_ForceAlphaColor; + if (m_Renderer->m_ForceAlphaColor != 0) { + Color = DRGBA(D3DCOLGetR(Color), D3DCOLGetG(Color), D3DCOLGetB(Color), D3DCOLGetA(m_Renderer->m_ForceAlphaColor)); + m_Renderer->m_ForceAlphaColor = 0; + } + Surface->DisplayTransOffset(X, Y - textOffset, rc, Color, BLEND_NORMAL, false, false, m_Layers[i]->m_OffsetX, m_Layers[i]->m_OffsetY); + + m_Renderer->m_ForceAlphaColor = OrigForceAlpha; + } + } + + +} + +////////////////////////////////////////////////////////////////////////// +CBSurface *CBFontTT::RenderTextToTexture(const WideString &text, int width, TTextAlign align, int maxHeight, int &textOffset) { + TextLineList lines; + WrapText(text, width, maxHeight, lines); + + + TextLineList::iterator it; + + int textHeight = lines.size() * (m_MaxCharHeight + m_Ascender); + SDL_Surface *surface = SDL_CreateRGBSurface(0, width, textHeight, 32, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000); + + SDL_LockSurface(surface); + + int posY = (int)GetLineHeight() - (int)m_Descender; + + for (it = lines.begin(); it != lines.end(); ++it) { + TextLine *line = (*it); + int posX = 0; + + switch (align) { + case TAL_CENTER: + posX += (width - line->GetWidth()) / 2; + break; + + case TAL_RIGHT: + posX += width - line->GetWidth(); + break; + } + + + textOffset = 0; + for (size_t i = 0; i < line->GetText().length(); i++) { + wchar_t ch = line->GetText()[i]; + + GlyphInfo *glyph = m_GlyphCache->GetGlyph(ch); + if (!glyph) continue; + + textOffset = std::max(textOffset, glyph->GetBearingY()); + } + + + int origPosX = posX; + + wchar_t prevChar = L'\0'; + for (size_t i = 0; i < line->GetText().length(); i++) { + wchar_t ch = line->GetText()[i]; + + GlyphInfo *glyph = m_GlyphCache->GetGlyph(ch); + if (!glyph) continue; + + float kerning = 0; + if (prevChar != L'\0') kerning = GetKerning(prevChar, ch); + posX += (int)kerning; + + + if (glyph->GetBearingY() > 0) { + int i = 10; + } + + SDL_Rect rect; + rect.x = posX + glyph->GetBearingX(); + rect.y = posY - glyph->GetBearingY() + textOffset; + rect.w = glyph->GetImage()->w; + rect.h = glyph->GetImage()->h; + + BlitSurface(glyph->GetImage(), surface, &rect); + + prevChar = ch; + posX += (int)(glyph->GetAdvanceX()); + posY += (int)(glyph->GetAdvanceY()); + } + + if (m_IsUnderline) { + for (int i = origPosX; i < origPosX + line->GetWidth(); i++) { + Uint8 *buf = (Uint8 *)surface->pixels + (int)(m_UnderlinePos + m_Ascender) * surface->pitch; + Uint32 *buf32 = (Uint32 *)buf; + + buf32[i] = SDL_MapRGBA(surface->format, 255, 255, 255, 255); + } + } + + SDL_UnlockSurface(surface); + + delete line; + line = NULL; + posY += GetLineHeight(); + } + + CBSurfaceSDL *wmeSurface = new CBSurfaceSDL(Game); + if (SUCCEEDED(wmeSurface->CreateFromSDLSurface(surface))) { + SDL_FreeSurface(surface); + return wmeSurface; + } else { + SDL_FreeSurface(surface); + delete wmeSurface; + return NULL; + } +} + +////////////////////////////////////////////////////////////////////////// +void CBFontTT::BlitSurface(SDL_Surface *src, SDL_Surface *target, SDL_Rect *targetRect) { + //SDL_BlitSurface(src, NULL, target, targetRect); + + for (int y = 0; y < src->h; y++) { + if (targetRect->y + y < 0 || targetRect->y + y >= target->h) continue; + + + Uint8 *srcBuf = (Uint8 *)src->pixels + y * src->pitch; + Uint8 *tgtBuf = (Uint8 *)target->pixels + (y + targetRect->y) * target->pitch; + + Uint32 *srcBuf32 = (Uint32 *)srcBuf; + Uint32 *tgtBuf32 = (Uint32 *)tgtBuf; + + for (int x = 0; x < src->w; x++) { + if (targetRect->x + x < 0 || targetRect->x + x >= target->w) continue; + + tgtBuf32[x + targetRect->x] = srcBuf32[x]; + } + } + +} + +////////////////////////////////////////////////////////////////////////// +int CBFontTT::GetLetterHeight() { + return GetLineHeight(); +} + + +////////////////////////////////////////////////////////////////////// +HRESULT CBFontTT::LoadFile(char *Filename) { + byte *Buffer = Game->m_FileManager->ReadWholeFile(Filename); + if (Buffer == NULL) { + Game->LOG(0, "CBFontTT::LoadFile failed for file '%s'", Filename); + return E_FAIL; + } + + HRESULT ret; + + m_Filename = new char [strlen(Filename) + 1]; + strcpy(m_Filename, Filename); + + if (FAILED(ret = LoadBuffer(Buffer))) Game->LOG(0, "Error parsing TTFONT file '%s'", Filename); + + delete [] Buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(TTFONT) +TOKEN_DEF(SIZE) +TOKEN_DEF(FACE) +TOKEN_DEF(FILENAME) +TOKEN_DEF(BOLD) +TOKEN_DEF(ITALIC) +TOKEN_DEF(UNDERLINE) +TOKEN_DEF(STRIKE) +TOKEN_DEF(CHARSET) +TOKEN_DEF(COLOR) +TOKEN_DEF(ALPHA) +TOKEN_DEF(LAYER) +TOKEN_DEF(OFFSET_X) +TOKEN_DEF(OFFSET_Y) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////// +HRESULT CBFontTT::LoadBuffer(byte *Buffer) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(TTFONT) + TOKEN_TABLE(SIZE) + TOKEN_TABLE(FACE) + TOKEN_TABLE(FILENAME) + TOKEN_TABLE(BOLD) + TOKEN_TABLE(ITALIC) + TOKEN_TABLE(UNDERLINE) + TOKEN_TABLE(STRIKE) + TOKEN_TABLE(CHARSET) + TOKEN_TABLE(COLOR) + TOKEN_TABLE(ALPHA) + TOKEN_TABLE(LAYER) + TOKEN_TABLE_END + + char *params; + int cmd; + CBParser parser(Game); + + if (parser.GetCommand((char **)&Buffer, commands, (char **)¶ms) != TOKEN_TTFONT) { + Game->LOG(0, "'TTFONT' keyword expected."); + return E_FAIL; + } + Buffer = (byte *)params; + + uint32 BaseColor = 0x00000000; + + while ((cmd = parser.GetCommand((char **)&Buffer, commands, (char **)¶ms)) > 0) { + switch (cmd) { + case TOKEN_SIZE: + parser.ScanStr(params, "%d", &m_FontHeight); + break; + + case TOKEN_FACE: + // we don't need this anymore + break; + + case TOKEN_FILENAME: + CBUtils::SetString(&m_FontFile, params); + break; + + case TOKEN_BOLD: + parser.ScanStr(params, "%b", &m_IsBold); + break; + + case TOKEN_ITALIC: + parser.ScanStr(params, "%b", &m_IsItalic); + break; + + case TOKEN_UNDERLINE: + parser.ScanStr(params, "%b", &m_IsUnderline); + break; + + case TOKEN_STRIKE: + parser.ScanStr(params, "%b", &m_IsStriked); + break; + + case TOKEN_CHARSET: + // we don't need this anymore + break; + + case TOKEN_COLOR: { + int r, g, b; + parser.ScanStr(params, "%d,%d,%d", &r, &g, &b); + BaseColor = DRGBA(r, g, b, D3DCOLGetA(BaseColor)); + } + break; + + case TOKEN_ALPHA: { + int a; + parser.ScanStr(params, "%d", &a); + BaseColor = DRGBA(D3DCOLGetR(BaseColor), D3DCOLGetG(BaseColor), D3DCOLGetB(BaseColor), a); + } + break; + + case TOKEN_LAYER: { + CBTTFontLayer *Layer = new CBTTFontLayer; + if (Layer && SUCCEEDED(ParseLayer(Layer, (byte *)params))) m_Layers.Add(Layer); + else { + delete Layer; + Layer = NULL; + cmd = PARSERR_TOKENNOTFOUND; + } + } + break; + + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + Game->LOG(0, "Syntax error in TTFONT definition"); + return E_FAIL; + } + + // create at least one layer + if (m_Layers.GetSize() == 0) { + CBTTFontLayer *Layer = new CBTTFontLayer; + Layer->m_Color = BaseColor; + m_Layers.Add(Layer); + } + + if (!m_FontFile) CBUtils::SetString(&m_FontFile, "arial.ttf"); + + return InitFont(); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFontTT::ParseLayer(CBTTFontLayer *Layer, byte *Buffer) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(OFFSET_X) + TOKEN_TABLE(OFFSET_Y) + TOKEN_TABLE(COLOR) + TOKEN_TABLE(ALPHA) + TOKEN_TABLE_END + + char *params; + int cmd; + CBParser parser(Game); + + while ((cmd = parser.GetCommand((char **)&Buffer, commands, (char **)¶ms)) > 0) { + switch (cmd) { + case TOKEN_OFFSET_X: + parser.ScanStr(params, "%d", &Layer->m_OffsetX); + break; + + case TOKEN_OFFSET_Y: + parser.ScanStr(params, "%d", &Layer->m_OffsetY); + break; + + case TOKEN_COLOR: { + int r, g, b; + parser.ScanStr(params, "%d,%d,%d", &r, &g, &b); + Layer->m_Color = DRGBA(r, g, b, D3DCOLGetA(Layer->m_Color)); + } + break; + + case TOKEN_ALPHA: { + int a; + parser.ScanStr(params, "%d", &a); + Layer->m_Color = DRGBA(D3DCOLGetR(Layer->m_Color), D3DCOLGetG(Layer->m_Color), D3DCOLGetB(Layer->m_Color), a); + } + break; + } + } + if (cmd != PARSERR_EOF) return E_FAIL; + else return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFontTT::Persist(CBPersistMgr *PersistMgr) { + CBFont::Persist(PersistMgr); + + PersistMgr->Transfer(TMEMBER(m_IsBold)); + PersistMgr->Transfer(TMEMBER(m_IsItalic)); + PersistMgr->Transfer(TMEMBER(m_IsUnderline)); + PersistMgr->Transfer(TMEMBER(m_IsStriked)); + PersistMgr->Transfer(TMEMBER(m_FontHeight)); + PersistMgr->Transfer(TMEMBER(m_FontFile)); + + + // persist layers + int NumLayers; + if (PersistMgr->m_Saving) { + NumLayers = m_Layers.GetSize(); + PersistMgr->Transfer(TMEMBER(NumLayers)); + for (int i = 0; i < NumLayers; i++) m_Layers[i]->Persist(PersistMgr); + } else { + NumLayers = m_Layers.GetSize(); + PersistMgr->Transfer(TMEMBER(NumLayers)); + for (int i = 0; i < NumLayers; i++) { + CBTTFontLayer *Layer = new CBTTFontLayer; + Layer->Persist(PersistMgr); + m_Layers.Add(Layer); + } + } + + if (!PersistMgr->m_Saving) { + for (int i = 0; i < NUM_CACHED_TEXTS; i++) m_CachedTexts[i] = NULL; + m_GlyphCache = NULL; + } + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void CBFontTT::AfterLoad() { + InitFont(); +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFontTT::InitFont() { + if (!m_FontFile) return E_FAIL; + + CBFile *file = Game->m_FileManager->OpenFile(m_FontFile); + if (!file) { + // the requested font file is not in wme file space; try loading a system font + AnsiString fontFileName = PathUtil::Combine(CBPlatform::GetSystemFontPath(), PathUtil::GetFileName(m_FontFile)); + file = Game->m_FileManager->OpenFile((char *)fontFileName.c_str(), false); + + if (!file) { + Game->LOG(0, "Error loading TrueType font '%s'", m_FontFile); + return E_FAIL; + } + } + + FT_Error error; + + float vertDpi = 96.0; + float horDpi = 96.0; + + + m_FTStream = (FT_Stream)new byte[sizeof(*m_FTStream)]; + memset(m_FTStream, 0, sizeof(*m_FTStream)); + + m_FTStream->read = CBFontTT::FTReadSeekProc; + m_FTStream->close = CBFontTT::FTCloseProc; + m_FTStream->descriptor.pointer = file; + m_FTStream->size = file->GetSize(); + + FT_Open_Args args; + args.flags = FT_OPEN_STREAM; + args.stream = m_FTStream; + + error = FT_Open_Face(Game->m_FontStorage->GetFTLibrary(), &args, 0, &m_FTFace); + if (error) { + SAFE_DELETE_ARRAY(m_FTStream); + Game->m_FileManager->CloseFile(file); + return E_FAIL; + } + + error = FT_Set_Char_Size(m_FTFace, 0, (FT_F26Dot6)(m_FontHeight * 64), (FT_UInt)horDpi, (FT_UInt)vertDpi); + if (error) { + FT_Done_Face(m_FTFace); + m_FTFace = NULL; + return E_FAIL; + } + + // http://en.wikipedia.org/wiki/Em_(typography) + float pixelsPerEm = (m_FontHeight / 72.f) * vertDpi; // Size in inches * dpi + float EmsPerUnit = 1.0f / m_FTFace->units_per_EM; + float pixelsPerUnit = pixelsPerEm * EmsPerUnit; + + // bounding box in pixels + float xMin = m_FTFace->bbox.xMin * pixelsPerUnit; + float xMax = m_FTFace->bbox.xMax * pixelsPerUnit; + float yMin = m_FTFace->bbox.yMin * pixelsPerUnit; + float yMax = m_FTFace->bbox.yMax * pixelsPerUnit; + + // metrics in pixels + m_Ascender = m_FTFace->ascender * pixelsPerUnit; + m_Descender = - m_FTFace->descender * pixelsPerUnit; + m_LineHeight = MathUtil::RoundUp(m_FTFace->height * pixelsPerUnit) + 2; + m_UnderlinePos = - m_FTFace->underline_position * pixelsPerUnit; + + // max character size (used for texture grid) + m_MaxCharWidth = (size_t)MathUtil::RoundUp(xMax - xMin); + m_MaxCharHeight = (size_t)MathUtil::RoundUp(yMax - yMin); + + m_GlyphCache = new FontGlyphCache(); + m_GlyphCache->Initialize(); + + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +// I/O bridge between FreeType and WME file system +////////////////////////////////////////////////////////////////////////// +unsigned long CBFontTT::FTReadSeekProc(FT_Stream stream, unsigned long offset, unsigned char *buffer, unsigned long count) { + CBFile *f = static_cast(stream->descriptor.pointer); + if (!f) return 0; + + f->Seek(offset, SEEK_TO_BEGIN); + if (count) { + uint32 oldPos = f->GetPos(); + f->Read(buffer, count); + return f->GetPos() - oldPos; + } else return 0; +} + +////////////////////////////////////////////////////////////////////////// +void CBFontTT::FTCloseProc(FT_Stream stream) { + CBFile *f = static_cast(stream->descriptor.pointer); + if (!f) return; + + CBGame *Game = f->Game; + + Game->m_FileManager->CloseFile(f); + stream->descriptor.pointer = NULL; +} + + + +////////////////////////////////////////////////////////////////////////// +void CBFontTT::WrapText(const WideString &text, int maxWidth, int maxHeight, TextLineList &lines) { + int currWidth = 0; + wchar_t prevChar = L'\0'; + int prevSpaceIndex = -1; + int prevSpaceWidth = 0; + int lineStartIndex = 0; + + PrepareGlyphs(text); + + for (size_t i = 0; i < text.length(); i++) { + wchar_t ch = text[i]; + + if (ch == L' ') { + prevSpaceIndex = i; + prevSpaceWidth = currWidth; + } + + int charWidth = 0; + + if (ch != L'\n') { + GlyphInfo *glyphInfo = GetGlyphCache()->GetGlyph(ch); + if (!glyphInfo) continue; + + float kerning = 0; + if (prevChar != L'\0') kerning = GetKerning(prevChar, ch); + prevChar = ch; + + charWidth = (int)(glyphInfo->GetAdvanceX() + kerning); + } + + bool lineTooLong = maxWidth >= 0 && currWidth + charWidth > maxWidth; + bool breakOnSpace = false; + + // we can't fit even a single character + if (lineTooLong && currWidth == 0) break; + + + if (ch == L'\n' || i == text.length() - 1 || lineTooLong) { + int breakPoint, breakWidth; + + if (prevSpaceIndex >= 0 && lineTooLong) { + breakPoint = prevSpaceIndex; + breakWidth = prevSpaceWidth; + breakOnSpace = true; + } else { + breakPoint = i; + breakWidth = currWidth; + + breakOnSpace = (ch == L'\n'); + + // we're at the end + if (i == text.length() - 1) { + breakPoint++; + breakWidth += charWidth; + } + } + + if (maxHeight >= 0 && (lines.size() + 1) * GetLineHeight() > maxHeight) break; + + WideString line = text.substr(lineStartIndex, breakPoint - lineStartIndex); + lines.push_back(new TextLine(line, breakWidth)); + + currWidth = 0; + prevChar = L'\0'; + prevSpaceIndex = -1; + + if (breakOnSpace) breakPoint++; + + lineStartIndex = breakPoint; + i = breakPoint - 1; + + continue; + } + + //if (ch == L' ' && currLine.empty()) continue; + currWidth += charWidth; + } +} + +////////////////////////////////////////////////////////////////////////// +void CBFontTT::MeasureText(const WideString &text, int maxWidth, int maxHeight, int &textWidth, int &textHeight) { + TextLineList lines; + WrapText(text, maxWidth, maxHeight, lines); + + textHeight = (int)(lines.size() * GetLineHeight()); + textWidth = 0; + + TextLineList::iterator it; + for (it = lines.begin(); it != lines.end(); ++it) { + TextLine *line = (*it); + textWidth = std::max(textWidth, line->GetWidth()); + SAFE_DELETE(line); + } +} + + +////////////////////////////////////////////////////////////////////////// +float CBFontTT::GetKerning(wchar_t leftChar, wchar_t rightChar) { + GlyphInfo *infoLeft = m_GlyphCache->GetGlyph(leftChar); + GlyphInfo *infoRight = m_GlyphCache->GetGlyph(rightChar); + + if (!infoLeft || !infoRight) return 0; + + FT_Vector delta; + FT_Error error = FT_Get_Kerning(m_FTFace, infoLeft->GetGlyphIndex(), infoRight->GetGlyphIndex(), ft_kerning_unfitted, &delta); + if (error) return 0; + + return delta.x * (1.0f / 64.0f); +} + + +////////////////////////////////////////////////////////////////////////// +void CBFontTT::PrepareGlyphs(const WideString &text) { + // make sure we have all the glyphs we need + for (size_t i = 0; i < text.length(); i++) { + wchar_t ch = text[i]; + if (!m_GlyphCache->HasGlyph(ch)) CacheGlyph(ch); + } +} + +////////////////////////////////////////////////////////////////////////// +void CBFontTT::CacheGlyph(wchar_t ch) { + FT_UInt glyphIndex = FT_Get_Char_Index(m_FTFace, ch); + if (!glyphIndex) return; + + FT_Error error = FT_Load_Glyph(m_FTFace, glyphIndex, FT_LOAD_DEFAULT); + if (error) return; + + error = FT_Render_Glyph(m_FTFace->glyph, FT_RENDER_MODE_NORMAL); + if (error) return; + + byte *pixels = m_FTFace->glyph->bitmap.buffer; + size_t stride = m_FTFace->glyph->bitmap.pitch; + + + // convert from monochrome to grayscale if needed + byte *tempBuffer = NULL; + if (pixels != NULL && m_FTFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) { + tempBuffer = new byte[m_FTFace->glyph->bitmap.width * m_FTFace->glyph->bitmap.rows]; + for (int j = 0; j < m_FTFace->glyph->bitmap.rows; j++) { + int rowOffset = stride * j; + for (int i = 0; i < m_FTFace->glyph->bitmap.width; i++) { + int byteOffset = i / 8; + int bitOffset = 7 - (i % 8); + byte bit = (pixels[rowOffset + byteOffset] & (1 << bitOffset)) >> bitOffset; + tempBuffer[m_FTFace->glyph->bitmap.width * j + i] = 255 * bit; + } + } + + pixels = tempBuffer; + stride = m_FTFace->glyph->bitmap.width; + } + + // add glyph to cache + m_GlyphCache->AddGlyph(ch, glyphIndex, m_FTFace->glyph, m_FTFace->glyph->bitmap.width, m_FTFace->glyph->bitmap.rows, pixels, stride); + + if (tempBuffer) delete [] tempBuffer; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BFontTT.h b/engines/wintermute/BFontTT.h new file mode 100644 index 0000000000..6fbb019a27 --- /dev/null +++ b/engines/wintermute/BFontTT.h @@ -0,0 +1,188 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BFONTTT_H +#define WINTERMUTE_BFONTTT_H + +#include "BFontStorage.h" +#include "BFont.h" +#include "BSurface.h" + +#define NUM_CACHED_TEXTS 30 +class SDL_Surface; +namespace WinterMute { + +class FontGlyphCache; + +class CBFontTT : public CBFont { +private: + ////////////////////////////////////////////////////////////////////////// + class CBCachedTTFontText { + public: + WideString m_Text; + int m_Width; + TTextAlign m_Align; + int m_MaxHeight; + int m_MaxLength; + CBSurface *m_Surface; + int m_Priority; + int m_TextOffset; + bool m_Marked; + + CBCachedTTFontText() { + m_Text = L""; + m_Width = m_MaxHeight = m_MaxLength = -1; + m_Align = TAL_LEFT; + m_Surface = NULL; + m_Priority = -1; + m_TextOffset = 0; + m_Marked = false; + } + + virtual ~CBCachedTTFontText() { + if (m_Surface) delete m_Surface; + } + }; + +public: + ////////////////////////////////////////////////////////////////////////// + class CBTTFontLayer { + public: + CBTTFontLayer() { + m_OffsetX = m_OffsetY = 0; + m_Color = 0x00000000; + } + + HRESULT Persist(CBPersistMgr *PersistMgr) { + PersistMgr->Transfer(TMEMBER(m_OffsetX)); + PersistMgr->Transfer(TMEMBER(m_OffsetY)); + PersistMgr->Transfer(TMEMBER(m_Color)); + return S_OK; + } + + int m_OffsetX; + int m_OffsetY; + uint32 m_Color; + }; + + ////////////////////////////////////////////////////////////////////////// + class TextLine { + public: + TextLine(const WideString &text, int width) { + m_Text = text; + m_Width = width; + } + + const WideString &GetText() const { + return m_Text; + } + int GetWidth() const { + return m_Width; + } + private: + WideString m_Text; + int m_Width; + }; + typedef std::list TextLineList; + + +public: + DECLARE_PERSISTENT(CBFontTT, CBFont) + CBFontTT(CBGame *inGame); + virtual ~CBFontTT(void); + + virtual int GetTextWidth(byte *text, int MaxLenght = -1); + virtual int GetTextHeight(byte *text, int width); + virtual void DrawText(byte *text, int x, int y, int width, TTextAlign align = TAL_LEFT, int max_height = -1, int MaxLenght = -1); + virtual int GetLetterHeight(); + + HRESULT LoadBuffer(byte *Buffer); + HRESULT LoadFile(char *Filename); + + static unsigned long FTReadSeekProc(FT_Stream stream, unsigned long offset, unsigned char *buffer, unsigned long count); + static void FTCloseProc(FT_Stream stream); + + FontGlyphCache *GetGlyphCache() { + return m_GlyphCache; + } + + float GetLineHeight() const { + return m_LineHeight; + } + + void AfterLoad(); + void InitLoop(); + +private: + HRESULT ParseLayer(CBTTFontLayer *Layer, byte *Buffer); + + void WrapText(const WideString &text, int maxWidth, int maxHeight, TextLineList &lines); + void MeasureText(const WideString &text, int maxWidth, int maxHeight, int &textWidth, int &textHeight); + float GetKerning(wchar_t leftChar, wchar_t rightChar); + void PrepareGlyphs(const WideString &text); + void CacheGlyph(wchar_t ch); + + CBSurface *RenderTextToTexture(const WideString &text, int width, TTextAlign align, int maxHeight, int &textOffset); + void BlitSurface(SDL_Surface *src, SDL_Surface *target, SDL_Rect *targetRect); + + + CBCachedTTFontText *m_CachedTexts[NUM_CACHED_TEXTS]; + + HRESULT InitFont(); + FT_Stream m_FTStream; + FT_Face m_FTFace; + + FontGlyphCache *m_GlyphCache; + + float m_Ascender; + float m_Descender; + float m_LineHeight; + float m_UnderlinePos; + float m_PointSize; + float m_VertDpi; + float m_HorDpi; + + size_t m_MaxCharWidth; + size_t m_MaxCharHeight; + +public: + bool m_IsBold; + bool m_IsItalic; + bool m_IsUnderline; + bool m_IsStriked; + int m_FontHeight; + char *m_FontFile; + + CBArray m_Layers; + void ClearCache(); + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BFrame.cpp b/engines/wintermute/BFrame.cpp new file mode 100644 index 0000000000..4d8d557a2a --- /dev/null +++ b/engines/wintermute/BFrame.cpp @@ -0,0 +1,707 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BParser.h" +#include "BFrame.h" +#include "BGame.h" +#include "BDynBuffer.h" +#include "ScValue.h" +#include "BSoundMgr.h" +#include "BSound.h" +#include "BSubFrame.h" +#include "ScScript.h" +#include "ScStack.h" +#include "PlatformSDL.h" +#include "common/str.h" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CBFrame, false) + +////////////////////////////////////////////////////////////////////// +CBFrame::CBFrame(CBGame *inGame): CBScriptable(inGame, true) { + m_Delay = 0; + m_MoveX = m_MoveY = 0; + + m_Sound = NULL; + m_KillSound = false; + + m_EditorExpanded = false; + m_Keyframe = false; +} + + +////////////////////////////////////////////////////////////////////// +CBFrame::~CBFrame() { + delete m_Sound; + m_Sound = NULL; + + int i; + + for (i = 0; i < m_Subframes.GetSize(); i++) delete m_Subframes[i]; + m_Subframes.RemoveAll(); + + for (i = 0; i < m_ApplyEvent.GetSize(); i++) { + SAFE_DELETE_ARRAY(m_ApplyEvent[i]); + } + m_ApplyEvent.RemoveAll(); +} + + +////////////////////////////////////////////////////////////////////// +HRESULT CBFrame::Draw(int X, int Y, CBObject *Register, float ZoomX, float ZoomY, bool Precise, uint32 Alpha, bool AllFrames, float Rotate, TSpriteBlendMode BlendMode) { + HRESULT res; + + for (int i = 0; i < m_Subframes.GetSize(); i++) { + res = m_Subframes[i]->Draw(X, Y, Register, ZoomX, ZoomY, Precise, Alpha, Rotate, BlendMode); + if (FAILED(res)) return res; + } + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFrame::OneTimeDisplay(CBObject *Owner, bool Muted) { + if (m_Sound && !Muted) { + if (Owner) Owner->UpdateOneSound(m_Sound); + m_Sound->Play(); + /* + if(Game->m_State==GAME_FROZEN) + { + m_Sound->Pause(true); + } + */ + } + if (Owner) { + for (int i = 0; i < m_ApplyEvent.GetSize(); i++) { + Owner->ApplyEvent(m_ApplyEvent[i]); + } + } + return S_OK; +} + + + +TOKEN_DEF_START +TOKEN_DEF(DELAY) +TOKEN_DEF(IMAGE) +TOKEN_DEF(TRANSPARENT) +TOKEN_DEF(RECT) +TOKEN_DEF(HOTSPOT) +TOKEN_DEF(2D_ONLY) +TOKEN_DEF(3D_ONLY) +TOKEN_DEF(MIRROR_X) +TOKEN_DEF(MIRROR_Y) +TOKEN_DEF(MOVE) +TOKEN_DEF(ALPHA_COLOR) +TOKEN_DEF(ALPHA) +TOKEN_DEF(SUBFRAME) +TOKEN_DEF(SOUND) +TOKEN_DEF(KEYFRAME) +TOKEN_DEF(DECORATION) +TOKEN_DEF(APPLY_EVENT) +TOKEN_DEF(EDITOR_SELECTED) +TOKEN_DEF(EDITOR_EXPANDED) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF(KILL_SOUND) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////// +HRESULT CBFrame::LoadBuffer(byte *Buffer, int LifeTime, bool KeepLoaded) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(DELAY) + TOKEN_TABLE(IMAGE) + TOKEN_TABLE(TRANSPARENT) + TOKEN_TABLE(RECT) + TOKEN_TABLE(HOTSPOT) + TOKEN_TABLE(2D_ONLY) + TOKEN_TABLE(3D_ONLY) + TOKEN_TABLE(MIRROR_X) + TOKEN_TABLE(MIRROR_Y) + TOKEN_TABLE(MOVE) + TOKEN_TABLE(ALPHA_COLOR) + TOKEN_TABLE(ALPHA) + TOKEN_TABLE(SUBFRAME) + TOKEN_TABLE(SOUND) + TOKEN_TABLE(KEYFRAME) + TOKEN_TABLE(DECORATION) + TOKEN_TABLE(APPLY_EVENT) + TOKEN_TABLE(EDITOR_SELECTED) + TOKEN_TABLE(EDITOR_EXPANDED) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE(KILL_SOUND) + TOKEN_TABLE_END + + char *params; + int cmd; + CBParser parser(Game); + RECT rect; + int r = 255, g = 255, b = 255; + int ar = 255, ag = 255, ab = 255, alpha = 255; + int HotspotX = 0, HotspotY = 0; + bool custom_trans = false; + bool editor_selected = false; + bool Is2DOnly = false; + bool Is3DOnly = false; + bool Decoration = false; + bool MirrorX = false; + bool MirrorY = false; + CBPlatform::SetRectEmpty(&rect); + char *surface_file = NULL; + + while ((cmd = parser.GetCommand((char **)&Buffer, commands, ¶ms)) > 0) { + switch (cmd) { + case TOKEN_DELAY: + parser.ScanStr(params, "%d", &m_Delay); + break; + + case TOKEN_IMAGE: + surface_file = params; + break; + + case TOKEN_TRANSPARENT: + parser.ScanStr(params, "%d,%d,%d", &r, &g, &b); + custom_trans = true; + break; + + case TOKEN_RECT: + parser.ScanStr(params, "%d,%d,%d,%d", &rect.left, &rect.top, &rect.right, &rect.bottom); + break; + + case TOKEN_HOTSPOT: + parser.ScanStr(params, "%d,%d", &HotspotX, &HotspotY); + break; + + case TOKEN_MOVE: + parser.ScanStr(params, "%d,%d", &m_MoveX, &m_MoveY); + break; + + case TOKEN_2D_ONLY: + parser.ScanStr(params, "%b", &Is2DOnly); + break; + + case TOKEN_3D_ONLY: + parser.ScanStr(params, "%b", &Is3DOnly); + break; + + case TOKEN_MIRROR_X: + parser.ScanStr(params, "%b", &MirrorX); + break; + + case TOKEN_MIRROR_Y: + parser.ScanStr(params, "%b", &MirrorY); + break; + + case TOKEN_ALPHA_COLOR: + parser.ScanStr(params, "%d,%d,%d", &ar, &ag, &ab); + break; + + case TOKEN_ALPHA: + parser.ScanStr(params, "%d", &alpha); + break; + + case TOKEN_EDITOR_SELECTED: + parser.ScanStr(params, "%b", &editor_selected); + break; + + case TOKEN_EDITOR_EXPANDED: + parser.ScanStr(params, "%b", &m_EditorExpanded); + break; + + case TOKEN_KILL_SOUND: + parser.ScanStr(params, "%b", &m_KillSound); + break; + + case TOKEN_SUBFRAME: { + CBSubFrame *subframe = new CBSubFrame(Game); + if (!subframe || FAILED(subframe->LoadBuffer((byte *)params, LifeTime, KeepLoaded))) { + delete subframe; + cmd = PARSERR_GENERIC; + } else m_Subframes.Add(subframe); + } + break; + + case TOKEN_SOUND: { + if (m_Sound) { + delete m_Sound; + m_Sound = NULL; + } + m_Sound = new CBSound(Game); + if (!m_Sound || FAILED(m_Sound->SetSound(params, SOUND_SFX, false))) { + if (Game->m_SoundMgr->m_SoundAvailable) Game->LOG(0, "Error loading sound '%s'.", params); + delete m_Sound; + m_Sound = NULL; + } + } + break; + + case TOKEN_APPLY_EVENT: { + char *Event = new char[strlen(params) + 1]; + strcpy(Event, params); + m_ApplyEvent.Add(Event); + } + break; + + case TOKEN_KEYFRAME: + parser.ScanStr(params, "%b", &m_Keyframe); + break; + + case TOKEN_DECORATION: + parser.ScanStr(params, "%b", &Decoration); + break; + + case TOKEN_EDITOR_PROPERTY: + ParseEditorProperty((byte *)params, false); + break; + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + Game->LOG(0, "Syntax error in FRAME definition"); + return E_FAIL; + } + + if (cmd == PARSERR_GENERIC) { + Game->LOG(0, "Error loading FRAME definition"); + return E_FAIL; + } + + + CBSubFrame *sub = new CBSubFrame(Game); + if (surface_file != NULL) { + if (custom_trans) sub->SetSurface(surface_file, false, r, g, b, LifeTime, KeepLoaded); + else sub->SetSurface(surface_file, true, 0, 0, 0, LifeTime, KeepLoaded); + + if (!sub->m_Surface) { + delete sub; + Game->LOG(0, "Error loading SUBFRAME"); + return E_FAIL; + } + + sub->m_Alpha = DRGBA(ar, ag, ab, alpha); + if (custom_trans) sub->m_Transparent = DRGBA(r, g, b, 0xFF); + } + + if (CBPlatform::IsRectEmpty(&rect)) sub->SetDefaultRect(); + else sub->m_Rect = rect; + + sub->m_HotspotX = HotspotX; + sub->m_HotspotY = HotspotY; + sub->m_2DOnly = Is2DOnly; + sub->m_3DOnly = Is3DOnly; + sub->m_Decoration = Decoration; + sub->m_MirrorX = MirrorX; + sub->m_MirrorY = MirrorY; + + + sub->m_EditorSelected = editor_selected; + m_Subframes.InsertAt(0, sub); + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBFrame::GetBoundingRect(LPRECT Rect, int X, int Y, float ScaleX, float ScaleY) { + if (!Rect) return false; + CBPlatform::SetRectEmpty(Rect); + + RECT SubRect; + + for (int i = 0; i < m_Subframes.GetSize(); i++) { + m_Subframes[i]->GetBoundingRect(&SubRect, X, Y, ScaleX, ScaleY); + CBPlatform::UnionRect(Rect, Rect, &SubRect); + } + return true; +} + + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFrame::SaveAsText(CBDynBuffer *Buffer, int Indent) { + Buffer->PutTextIndent(Indent, "FRAME {\n"); + Buffer->PutTextIndent(Indent + 2, "DELAY = %d\n", m_Delay); + + if (m_MoveX != 0 || m_MoveY != 0) + Buffer->PutTextIndent(Indent + 2, "MOVE {%d, %d}\n", m_MoveX, m_MoveY); + + if (m_Sound && m_Sound->m_SoundFilename) + Buffer->PutTextIndent(Indent + 2, "SOUND=\"%s\"\n", m_Sound->m_SoundFilename); + + Buffer->PutTextIndent(Indent + 2, "KEYFRAME=%s\n", m_Keyframe ? "TRUE" : "FALSE"); + + if (m_KillSound) + Buffer->PutTextIndent(Indent + 2, "KILL_SOUND=%s\n", m_KillSound ? "TRUE" : "FALSE"); + + if (m_EditorExpanded) + Buffer->PutTextIndent(Indent + 2, "EDITOR_EXPANDED=%s\n", m_EditorExpanded ? "TRUE" : "FALSE"); + + if (m_Subframes.GetSize() > 0) m_Subframes[0]->SaveAsText(Buffer, Indent, false); + + int i; + for (i = 1; i < m_Subframes.GetSize(); i++) { + m_Subframes[i]->SaveAsText(Buffer, Indent + 2); + } + + for (i = 0; i < m_ApplyEvent.GetSize(); i++) { + Buffer->PutTextIndent(Indent + 2, "APPLY_EVENT=\"%s\"\n", m_ApplyEvent[i]); + } + + CBBase::SaveAsText(Buffer, Indent + 2); + + + Buffer->PutTextIndent(Indent, "}\n\n"); + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFrame::Persist(CBPersistMgr *PersistMgr) { + CBScriptable::Persist(PersistMgr); + + m_ApplyEvent.Persist(PersistMgr); + PersistMgr->Transfer(TMEMBER(m_Delay)); + PersistMgr->Transfer(TMEMBER(m_EditorExpanded)); + PersistMgr->Transfer(TMEMBER(m_Keyframe)); + PersistMgr->Transfer(TMEMBER(m_KillSound)); + PersistMgr->Transfer(TMEMBER(m_MoveX)); + PersistMgr->Transfer(TMEMBER(m_MoveY)); + PersistMgr->Transfer(TMEMBER(m_Sound)); + m_Subframes.Persist(PersistMgr); + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +HRESULT CBFrame::ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name) { + + ////////////////////////////////////////////////////////////////////////// + // GetSound + ////////////////////////////////////////////////////////////////////////// + if (strcmp(Name, "GetSound") == 0) { + Stack->CorrectParams(0); + + if (m_Sound && m_Sound->m_SoundFilename) Stack->PushString(m_Sound->m_SoundFilename); + else Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetSound + ////////////////////////////////////////////////////////////////////////// + if (strcmp(Name, "SetSound") == 0) { + Stack->CorrectParams(1); + CScValue *Val = Stack->Pop(); + delete m_Sound; + m_Sound = NULL; + + if (!Val->IsNULL()) { + m_Sound = new CBSound(Game); + if (!m_Sound || FAILED(m_Sound->SetSound(Val->GetString(), SOUND_SFX, false))) { + Stack->PushBool(false); + delete m_Sound; + m_Sound = NULL; + } else Stack->PushBool(true); + } else Stack->PushBool(true); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetSubframe + ////////////////////////////////////////////////////////////////////////// + if (strcmp(Name, "GetSubframe") == 0) { + Stack->CorrectParams(1); + int Index = Stack->Pop()->GetInt(-1); + if (Index < 0 || Index >= m_Subframes.GetSize()) { + Script->RuntimeError("Frame.GetSubframe: Subframe index %d is out of range.", Index); + Stack->PushNULL(); + } else Stack->PushNative(m_Subframes[Index], true); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // DeleteSubframe + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "DeleteSubframe") == 0) { + Stack->CorrectParams(1); + CScValue *Val = Stack->Pop(); + if (Val->IsInt()) { + int Index = Val->GetInt(-1); + if (Index < 0 || Index >= m_Subframes.GetSize()) { + Script->RuntimeError("Frame.DeleteSubframe: Subframe index %d is out of range.", Index); + } + } else { + CBSubFrame *Sub = (CBSubFrame *)Val->GetNative(); + for (int i = 0; i < m_Subframes.GetSize(); i++) { + if (m_Subframes[i] == Sub) { + delete m_Subframes[i]; + m_Subframes.RemoveAt(i); + break; + } + } + } + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // AddSubframe + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "AddSubframe") == 0) { + Stack->CorrectParams(1); + CScValue *Val = Stack->Pop(); + char *Filename = NULL; + if (!Val->IsNULL()) Filename = Val->GetString(); + + CBSubFrame *Sub = new CBSubFrame(Game); + if (Filename != NULL) { + Sub->SetSurface(Filename); + Sub->SetDefaultRect(); + } + m_Subframes.Add(Sub); + + Stack->PushNative(Sub, true); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // InsertSubframe + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "InsertSubframe") == 0) { + Stack->CorrectParams(2); + int Index = Stack->Pop()->GetInt(); + if (Index < 0) Index = 0; + + CScValue *Val = Stack->Pop(); + char *Filename = NULL; + if (!Val->IsNULL()) Filename = Val->GetString(); + + CBSubFrame *Sub = new CBSubFrame(Game); + if (Filename != NULL) { + Sub->SetSurface(Filename); + } + + if (Index >= m_Subframes.GetSize()) m_Subframes.Add(Sub); + else m_Subframes.InsertAt(Index, Sub); + + Stack->PushNative(Sub, true); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetEvent + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "GetSubframe") == 0) { + Stack->CorrectParams(1); + int Index = Stack->Pop()->GetInt(-1); + if (Index < 0 || Index >= m_ApplyEvent.GetSize()) { + Script->RuntimeError("Frame.GetEvent: Event index %d is out of range.", Index); + Stack->PushNULL(); + } else Stack->PushString(m_ApplyEvent[Index]); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // AddEvent + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "AddEvent") == 0) { + Stack->CorrectParams(1); + char *Event = Stack->Pop()->GetString(); + for (int i = 0; i < m_ApplyEvent.GetSize(); i++) { + if (scumm_stricmp(m_ApplyEvent[i], Event) == 0) { + Stack->PushNULL(); + return S_OK; + } + } + m_ApplyEvent.Add(Event); + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // DeleteEvent + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "DeleteEvent") == 0) { + Stack->CorrectParams(1); + char *Event = Stack->Pop()->GetString(); + for (int i = 0; i < m_ApplyEvent.GetSize(); i++) { + if (scumm_stricmp(m_ApplyEvent[i], Event) == 0) { + delete [] m_ApplyEvent[i]; + m_ApplyEvent.RemoveAt(i); + break; + } + } + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + else { + if (m_Subframes.GetSize() == 1) return m_Subframes[0]->ScCallMethod(Script, Stack, ThisStack, Name); + else return CBScriptable::ScCallMethod(Script, Stack, ThisStack, Name); + } +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CBFrame::ScGetProperty(char *Name) { + if (!m_ScValue) m_ScValue = new CScValue(Game); + m_ScValue->SetNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type (RO) + ////////////////////////////////////////////////////////////////////////// + if (strcmp(Name, "Type") == 0) { + m_ScValue->SetString("frame"); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Delay + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Delay") == 0) { + m_ScValue->SetInt(m_Delay); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Keyframe + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Keyframe") == 0) { + m_ScValue->SetBool(m_Keyframe); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // KillSounds + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "KillSounds") == 0) { + m_ScValue->SetBool(m_KillSound); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // MoveX + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "MoveX") == 0) { + m_ScValue->SetInt(m_MoveX); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // MoveY + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "MoveY") == 0) { + m_ScValue->SetInt(m_MoveY); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // NumSubframes (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "NumSubframes") == 0) { + m_ScValue->SetInt(m_Subframes.GetSize()); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // NumEvents (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "NumEvents") == 0) { + m_ScValue->SetInt(m_ApplyEvent.GetSize()); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + else { + if (m_Subframes.GetSize() == 1) return m_Subframes[0]->ScGetProperty(Name); + else return CBScriptable::ScGetProperty(Name); + } +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBFrame::ScSetProperty(char *Name, CScValue *Value) { + ////////////////////////////////////////////////////////////////////////// + // Delay + ////////////////////////////////////////////////////////////////////////// + if (strcmp(Name, "Delay") == 0) { + m_Delay = std::max(0, Value->GetInt()); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Keyframe + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Keyframe") == 0) { + m_Keyframe = Value->GetBool(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // KillSounds + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "KillSounds") == 0) { + m_KillSound = Value->GetBool(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // MoveX + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "MoveX") == 0) { + m_MoveX = Value->GetInt(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // MoveY + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "MoveY") == 0) { + m_MoveY = Value->GetInt(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + else { + if (m_Subframes.GetSize() == 1) return m_Subframes[0]->ScSetProperty(Name, Value); + else return CBScriptable::ScSetProperty(Name, Value); + } +} + + +////////////////////////////////////////////////////////////////////////// +char *CBFrame::ScToString() { + return "[frame]"; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BFrame.h b/engines/wintermute/BFrame.h new file mode 100644 index 0000000000..9538305dd6 --- /dev/null +++ b/engines/wintermute/BFrame.h @@ -0,0 +1,73 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BFRAME_H +#define WINTERMUTE_BFRAME_H + +#include "BScriptable.h" +#include "coll_templ.h" + +namespace WinterMute { +class CBSound; +class CBSubFrame; +class CBObject; +class CScScript; +class CScStack; +class CBFrame: public CBScriptable { +public: + bool m_KillSound; + bool m_Keyframe; + HRESULT OneTimeDisplay(CBObject *Owner, bool Muted = false); + DECLARE_PERSISTENT(CBFrame, CBScriptable) + CBSound *m_Sound; + bool m_EditorExpanded; + bool GetBoundingRect(LPRECT Rect, int X, int Y, float ScaleX = 100, float ScaleY = 100); + HRESULT SaveAsText(CBDynBuffer *Buffer, int Indent); + int m_MoveY; + int m_MoveX; + uint32 m_Delay; + CBArray m_Subframes; + HRESULT Draw(int X, int Y, CBObject *Register = NULL, float ZoomX = 100, float ZoomY = 100, bool Precise = true, uint32 Alpha = 0xFFFFFFFF, bool AllFrames = false, float Rotate = 0.0f, TSpriteBlendMode BlendMode = BLEND_NORMAL); + HRESULT LoadBuffer(byte *Buffer, int LifeTime, bool KeepLoaded); + + CBFrame(CBGame *inGame); + virtual ~CBFrame(); + + CBArray m_ApplyEvent; + + // scripting interface + virtual CScValue *ScGetProperty(char *Name); + virtual HRESULT ScSetProperty(char *Name, CScValue *Value); + virtual HRESULT ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name); + virtual char *ScToString(); + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BGame.cpp b/engines/wintermute/BGame.cpp new file mode 100644 index 0000000000..2c58641c33 --- /dev/null +++ b/engines/wintermute/BGame.cpp @@ -0,0 +1,4462 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BGame.h" +#include "BFile.h" +#include "BRegistry.h" +#include "BRenderSDL.h" +#include "BSurfaceSDL.h" +#include "BQuickMsg.h" +#include "scriptables/SXString.h" +#include "scriptables/SXDate.h" +#include "scriptables/SXArray.h" +#include "SxObject.h" +#include "scriptables/SXMemBuffer.h" +#include "SXFile.h" +#include "SXMath.h" +#include "SXStore.h" +#include "PathUtil.h" +#include +#include "crc.h" +#include "StringUtil.h" +#include "BParser.h" +#include "BImage.h" +#include "BTransitionMgr.h" +#include "BKeyboardState.h" +#include "UIWindow.h" +#include "ScValue.h" +#include "BSoundMgr.h" +#include "BSound.h" +#include "BSubFrame.h" +#include "BViewport.h" +#include "BFontStorage.h" +#include "BFontTT.h" +#include "ScEngine.h" +#include "BStringTable.h" +#include "ScScript.h" +#include "BRegion.h" +#include "BSprite.h" +#include "BFileManager.h" +#include "ScStack.h" +#include "common/textconsole.h" + +#ifdef __IPHONEOS__ +# include "ios_utils.h" +#endif + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +IMPLEMENT_PERSISTENT(CBGame, true) + + +////////////////////////////////////////////////////////////////////// +CBGame::CBGame(): CBObject(this) { + m_ShuttingDown = false; + + m_State = GAME_RUNNING; + m_OrigState = GAME_RUNNING; + m_FreezeLevel = 0; + + m_Interactive = true; + m_OrigInteractive = false; + + m_SurfaceStorage = NULL; + m_FontStorage = NULL; + m_Renderer = NULL; + m_SoundMgr = NULL; + m_FileManager = NULL; + m_TransMgr = NULL; + m_DebugMgr = NULL; + m_ScEngine = NULL; + m_KeyboardState = NULL; + + m_MathClass = NULL; + + m_DEBUG_LogFile = NULL; + m_DEBUG_DebugMode = false; + m_DEBUG_AbsolutePathWarning = true; + m_DEBUG_ShowFPS = false; + + m_SystemFont = NULL; + m_VideoFont = NULL; + + m_MainObject = NULL; + m_ActiveObject = NULL; + + m_Fader = NULL; + + m_OffsetX = m_OffsetY = 0; + m_OffsetPercentX = m_OffsetPercentY = 0.0f; + + m_Subtitles = true; + m_VideoSubtitles = true; + + m_Timer = 0; + m_TimerDelta = 0; + m_TimerLast = 0; + + m_LiveTimer = 0; + m_LiveTimerDelta = 0; + m_LiveTimerLast = 0; + + m_Sequence = 0; + + m_MousePos.x = m_MousePos.y = 0; + m_MouseLeftDown = m_MouseRightDown = m_MouseMidlleDown = false; + m_CapturedObject = NULL; + + // FPS counters + m_LastTime = m_FpsTime = m_DeltaTime = m_FramesRendered = m_Fps = 0; + + m_CursorNoninteractive = NULL; + + m_UseD3D = false; + + srand((unsigned)time(NULL)); + + m_Registry = new CBRegistry(this); + m_StringTable = new CBStringTable(this); + + for (int i = 0; i < NUM_MUSIC_CHANNELS; i++) { + m_Music[i] = NULL; + m_MusicStartTime[i] = 0; + } + + m_SettingsResWidth = 800; + m_SettingsResHeight = 600; + m_SettingsRequireAcceleration = false; + m_SettingsRequireSound = false; + m_SettingsTLMode = 0; + m_SettingsAllowWindowed = true; + m_SettingsGameFile = NULL; + m_SettingsAllowAdvanced = false; + m_SettingsAllowAccessTab = true; + m_SettingsAllowAboutTab = true; + m_SettingsAllowDesktopRes = false; + + m_EditorForceScripts = false; + m_EditorAlwaysRegister = false; + + m_FocusedWindow = NULL; + + m_LoadInProgress = false; + + m_Quitting = false; + m_Loading = false; + m_ScheduledLoadSlot = -1; + + m_PersonalizedSave = false; + m_CompressedSavegames = true; + + m_EditorMode = false; + m_DoNotExpandStrings = false; + + m_EngineLogCallback = NULL; + m_EngineLogCallbackData = NULL; + + m_SmartCache = false; + m_SurfaceGCCycleTime = 10000; + + m_ReportTextureFormat = false; + + m_ViewportSP = -1; + + m_SubtitlesSpeed = 70; + + m_ResourceModule = NULL; + + m_ForceNonStreamedSounds = false; + + m_ThumbnailWidth = m_ThumbnailHeight = 0; + + m_IndicatorDisplay = false; + m_IndicatorColor = DRGBA(255, 0, 0, 128); + m_IndicatorProgress = 0; + m_IndicatorX = -1; + m_IndicatorY = -1; + m_IndicatorWidth = -1; + m_IndicatorHeight = 8; + m_RichSavedGames = false; + m_SavedGameExt = NULL; + CBUtils::SetString(&m_SavedGameExt, "dsv"); + + m_MusicCrossfadeRunning = false; + m_MusicCrossfadeStartTime = 0; + m_MusicCrossfadeLength = 0; + m_MusicCrossfadeChannel1 = -1; + m_MusicCrossfadeChannel2 = -1; + m_MusicCrossfadeSwap = false; + + m_LoadImageName = NULL; + m_SaveImageName = NULL; + m_SaveLoadImage = NULL; + + m_SaveImageX = m_SaveImageY = 0; + m_LoadImageX = m_LoadImageY = 0; + + m_LocalSaveDir = NULL; + CBUtils::SetString(&m_LocalSaveDir, "saves"); + m_SaveDirChecked = false; + + m_LoadingIcon = NULL; + m_LoadingIconX = m_LoadingIconY = 0; + m_LoadingIconPersistent = false; + + m_TextEncoding = TEXT_ANSI; + m_TextRTL = false; + + m_SoundBufferSizeSec = 3; + m_SuspendedRendering = false; + + m_LastCursor = NULL; + + + CBPlatform::SetRectEmpty(&m_MouseLockRect); + + m_SuppressScriptErrors = false; + m_LastMiniUpdate = 0; + m_MiniUpdateEnabled = false; + + m_CachedThumbnail = NULL; + + m_AutorunDisabled = false; + + // compatibility bits + m_CompatKillMethodThreads = false; + + m_UsedMem = 0; + + + m_AutoSaveOnExit = true; + m_AutoSaveSlot = 999; + m_CursorHidden = false; + +#ifdef __IPHONEOS__ + m_TouchInterface = true; + m_ConstrainedMemory = true; // TODO differentiate old and new iOS devices +#else + m_TouchInterface = false; + m_ConstrainedMemory = false; +#endif + + m_Store = NULL; +} + + +////////////////////////////////////////////////////////////////////// +CBGame::~CBGame() { + m_ShuttingDown = true; + + LOG(0, ""); + LOG(0, "Shutting down..."); + + GetDebugMgr()->OnGameShutdown(); + + m_Registry->WriteBool("System", "LastRun", true); + + Cleanup(); + + delete[] m_LocalSaveDir; + delete[] m_SettingsGameFile; + delete[] m_SavedGameExt; + + delete m_CachedThumbnail; + + delete m_SaveLoadImage; + delete m_MathClass; + + delete m_TransMgr; + delete m_ScEngine; + delete m_FontStorage; + delete m_SurfaceStorage; + delete m_SoundMgr; + delete m_DebugMgr; + //SAFE_DELETE(m_KeyboardState); + + delete m_Renderer; + delete m_FileManager; + delete m_Registry; + delete m_StringTable; + + m_LocalSaveDir = NULL; + m_SettingsGameFile = NULL; + m_SavedGameExt = NULL; + + m_CachedThumbnail = NULL; + + m_SaveLoadImage = NULL; + m_MathClass = NULL; + + m_TransMgr = NULL; + m_ScEngine = NULL; + m_FontStorage = NULL; + m_SurfaceStorage = NULL; + m_SoundMgr = NULL; + m_DebugMgr = NULL; + + m_Renderer = NULL; + m_FileManager = NULL; + m_Registry = NULL; + m_StringTable = NULL; + + DEBUG_DebugDisable(); + CBPlatform::OutputDebugString("--- shutting down normally ---\n"); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::Cleanup() { + int i; + + delete m_LoadingIcon; + m_LoadingIcon = NULL; + + m_EngineLogCallback = NULL; + m_EngineLogCallbackData = NULL; + + for (i = 0; i < NUM_MUSIC_CHANNELS; i++) { + delete m_Music[i]; + m_Music[i] = NULL; + m_MusicStartTime[i] = 0; + } + + UnregisterObject(m_Store); + m_Store = NULL; + + UnregisterObject(m_Fader); + m_Fader = NULL; + + for (i = 0; i < m_RegObjects.GetSize(); i++) { + delete m_RegObjects[i]; + m_RegObjects[i] = NULL; + } + m_RegObjects.RemoveAll(); + + m_Windows.RemoveAll(); // refs only + m_FocusedWindow = NULL; // ref only + + delete[] m_SaveImageName; + delete[] m_LoadImageName; + m_SaveImageName = NULL; + m_LoadImageName = NULL; + + delete m_CursorNoninteractive; + delete m_Cursor; + delete m_ActiveCursor; + m_CursorNoninteractive = NULL; + m_Cursor = NULL; + m_ActiveCursor = NULL; + + delete m_ScValue; + delete m_SFX; + m_ScValue = NULL; + m_SFX = NULL; + + for (i = 0; i < m_Scripts.GetSize(); i++) { + m_Scripts[i]->m_Owner = NULL; + m_Scripts[i]->Finish(); + } + m_Scripts.RemoveAll(); + + m_FontStorage->RemoveFont(m_SystemFont); + m_SystemFont = NULL; + + m_FontStorage->RemoveFont(m_VideoFont); + m_VideoFont = NULL; + + for (i = 0; i < m_QuickMessages.GetSize(); i++) delete m_QuickMessages[i]; + m_QuickMessages.RemoveAll(); + + m_ViewportStack.RemoveAll(); + m_ViewportSP = -1; + + delete[] m_Name; + delete[] m_Filename; + m_Name = NULL; + m_Filename = NULL; + for (int i = 0; i < 7; i++) { + delete[] m_Caption[i]; + m_Caption[i] = NULL; + } + + m_LastCursor = NULL; + + delete m_KeyboardState; + m_KeyboardState = NULL; + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////// +HRESULT CBGame::Initialize1() { + m_SurfaceStorage = new CBSurfaceStorage(this); + if (m_SurfaceStorage == NULL) goto init_fail; + + m_FontStorage = new CBFontStorage(this); + if (m_FontStorage == NULL) goto init_fail; + + m_FileManager = new CBFileManager(this); + if (m_FileManager == NULL) goto init_fail; + + m_SoundMgr = new CBSoundMgr(this); + if (m_SoundMgr == NULL) goto init_fail; + + m_DebugMgr = new CBDebugger(this); + if (m_DebugMgr == NULL) goto init_fail; + + m_MathClass = new CSXMath(this); + if (m_MathClass == NULL) goto init_fail; + + m_ScEngine = new CScEngine(this); + if (m_ScEngine == NULL) goto init_fail; + + m_TransMgr = new CBTransitionMgr(this); + if (m_TransMgr == NULL) goto init_fail; + + m_KeyboardState = new CBKeyboardState(this); + if (m_KeyboardState == NULL) goto init_fail; + + m_Fader = new CBFader(this); + if (m_Fader == NULL) goto init_fail; + RegisterObject(m_Fader); + + m_Store = new CSXStore(this); + if (m_Store == NULL) goto init_fail; + RegisterObject(m_Store); + + return S_OK; + +init_fail: + if (m_MathClass) delete m_MathClass; + if (m_Store) delete m_Store; + if (m_KeyboardState) delete m_KeyboardState; + if (m_TransMgr) delete m_TransMgr; + if (m_DebugMgr) delete m_DebugMgr; + if (m_SurfaceStorage) delete m_SurfaceStorage; + if (m_FontStorage) delete m_FontStorage; + if (m_SoundMgr) delete m_SoundMgr; + if (m_FileManager) delete m_FileManager; + if (m_ScEngine) delete m_ScEngine; + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////// +HRESULT CBGame::Initialize2() { // we know whether we are going to be accelerated + m_Renderer = new CBRenderSDL(this); + if (m_Renderer == NULL) goto init_fail; + + return S_OK; + +init_fail: + if (m_Renderer) delete m_Renderer; + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////// +HRESULT CBGame::Initialize3() { // renderer is initialized + m_PosX = m_Renderer->m_Width / 2; + m_PosY = m_Renderer->m_Height / 2; + + if (m_IndicatorY == -1) m_IndicatorY = m_Renderer->m_Height - m_IndicatorHeight; + if (m_IndicatorX == -1) m_IndicatorX = 0; + if (m_IndicatorWidth == -1) m_IndicatorWidth = m_Renderer->m_Width; + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////// +void CBGame::DEBUG_DebugEnable(const char *Filename) { + m_DEBUG_DebugMode = true; + +#ifndef __IPHONEOS__ + if (Filename)m_DEBUG_LogFile = fopen(Filename, "a+"); + else m_DEBUG_LogFile = fopen("./zz_debug.log", "a+"); + + if (!m_DEBUG_LogFile) { + AnsiString safeLogFileName = PathUtil::GetSafeLogFileName(); + m_DEBUG_LogFile = fopen(safeLogFileName.c_str(), "a+"); + } + + if (m_DEBUG_LogFile != NULL) fprintf(m_DEBUG_LogFile, "\n"); +#endif + + time_t timeNow; + time(&timeNow); + struct tm *tm = localtime(&timeNow); + +#ifdef _DEBUG + LOG(0, "********** DEBUG LOG OPENED %02d-%02d-%04d (Debug Build) *******************", tm->tm_mday, tm->tm_mon, tm->tm_year + 1900); +#else + LOG(0, "********** DEBUG LOG OPENED %02d-%02d-%04d (Release Build) *****************", tm->tm_mday, tm->tm_mon, tm->tm_year + 1900); +#endif + + LOG(0, "%s ver %d.%d.%d%s, Compiled on " __DATE__ ", " __TIME__, DCGF_NAME, DCGF_VER_MAJOR, DCGF_VER_MINOR, DCGF_VER_BUILD, DCGF_VER_SUFFIX); + //LOG(0, "Extensions: %s ver %d.%02d", EXT_NAME, EXT_VER_MAJOR, EXT_VER_MINOR); + + AnsiString platform = CBPlatform::GetPlatformName(); + LOG(0, "Platform: %s", platform.c_str()); + LOG(0, ""); +} + + +////////////////////////////////////////////////////////////////////// +void CBGame::DEBUG_DebugDisable() { + if (m_DEBUG_LogFile != NULL) { + LOG(0, "********** DEBUG LOG CLOSED ********************************************"); + fclose(m_DEBUG_LogFile); + m_DEBUG_LogFile = NULL; + } + m_DEBUG_DebugMode = false; +} + + +////////////////////////////////////////////////////////////////////// +void CBGame::LOG(HRESULT res, LPCSTR fmt, ...) { +#ifndef __IPHONEOS__ + if (!m_DEBUG_DebugMode) return; +#endif + time_t timeNow; + time(&timeNow); + struct tm *tm = localtime(&timeNow); + + char buff[512]; + va_list va; + + va_start(va, fmt); + vsprintf(buff, fmt, va); + va_end(va); + +#ifdef __IPHONEOS__ + printf("%02d:%02d:%02d: %s\n", tm->tm_hour, tm->tm_min, tm->tm_sec, buff); + fflush(stdout); +#else + if (m_DEBUG_LogFile == NULL) return; + + // redirect to an engine's own callback + if (m_EngineLogCallback) { + m_EngineLogCallback(buff, res, m_EngineLogCallbackData); + } + if (m_DebugMgr) m_DebugMgr->OnLog(res, buff); + + warning("%02d:%02d: %s\n", tm->tm_hour, tm->tm_min, buff); + fprintf(m_DEBUG_LogFile, "%02d:%02d: %s\n", tm->tm_hour, tm->tm_min, buff); + fflush(m_DEBUG_LogFile); +#endif + + //QuickMessage(buff); +} + + +////////////////////////////////////////////////////////////////////////// +void CBGame::SetEngineLogCallback(ENGINE_LOG_CALLBACK Callback, void *Data) { + m_EngineLogCallback = Callback; + m_EngineLogCallbackData = Data; +} + + +////////////////////////////////////////////////////////////////////// +HRESULT CBGame::InitLoop() { + m_ViewportSP = -1; + + m_CurrentTime = CBPlatform::GetTime(); + + GetDebugMgr()->OnGameTick(); + m_Renderer->InitLoop(); + m_SoundMgr->InitLoop(); + UpdateMusicCrossfade(); + + m_SurfaceStorage->InitLoop(); + m_FontStorage->InitLoop(); + + + //m_ActiveObject = NULL; + + // count FPS + m_DeltaTime = m_CurrentTime - m_LastTime; + m_LastTime = m_CurrentTime; + m_FpsTime += m_DeltaTime; + + m_LiveTimerDelta = m_LiveTimer - m_LiveTimerLast; + m_LiveTimerLast = m_LiveTimer; + m_LiveTimer += MIN(1000, m_DeltaTime); + + if (m_State != GAME_FROZEN) { + m_TimerDelta = m_Timer - m_TimerLast; + m_TimerLast = m_Timer; + m_Timer += MIN(1000, m_DeltaTime); + } else m_TimerDelta = 0; + + m_FramesRendered++; + if (m_FpsTime > 1000) { + m_Fps = m_FramesRendered; + m_FramesRendered = 0; + m_FpsTime = 0; + } + //Game->LOG(0, "%d", m_Fps); + + GetMousePos(&m_MousePos); + + m_FocusedWindow = NULL; + for (int i = m_Windows.GetSize() - 1; i >= 0; i--) { + if (m_Windows[i]->m_Visible) { + m_FocusedWindow = m_Windows[i]; + break; + } + } + + UpdateSounds(); + + if (m_Fader) m_Fader->Update(); + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////// +HRESULT CBGame::InitInput(HINSTANCE hInst, HWND hWnd) { + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +int CBGame::GetSequence() { + return ++m_Sequence; +} + + +////////////////////////////////////////////////////////////////////////// +void CBGame::SetOffset(int OffsetX, int OffsetY) { + m_OffsetX = OffsetX; + m_OffsetY = OffsetY; +} + +////////////////////////////////////////////////////////////////////////// +void CBGame::GetOffset(int *OffsetX, int *OffsetY) { + if (OffsetX != NULL) *OffsetX = m_OffsetX; + if (OffsetY != NULL) *OffsetY = m_OffsetY; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::LoadFile(const char *Filename) { + byte *Buffer = Game->m_FileManager->ReadWholeFile(Filename); + if (Buffer == NULL) { + Game->LOG(0, "CBGame::LoadFile failed for file '%s'", Filename); + return E_FAIL; + } + + HRESULT ret; + + m_Filename = new char [strlen(Filename) + 1]; + strcpy(m_Filename, Filename); + + if (FAILED(ret = LoadBuffer(Buffer, true))) Game->LOG(0, "Error parsing GAME file '%s'", Filename); + + + delete [] Buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(GAME) +TOKEN_DEF(TEMPLATE) +TOKEN_DEF(NAME) +TOKEN_DEF(SYSTEM_FONT) +TOKEN_DEF(VIDEO_FONT) +TOKEN_DEF(EVENTS) +TOKEN_DEF(CURSOR) +TOKEN_DEF(ACTIVE_CURSOR) +TOKEN_DEF(NONINTERACTIVE_CURSOR) +TOKEN_DEF(STRING_TABLE) +TOKEN_DEF(RESOLUTION) +TOKEN_DEF(SETTINGS) +TOKEN_DEF(REQUIRE_3D_ACCELERATION) +TOKEN_DEF(REQUIRE_SOUND) +TOKEN_DEF(HWTL_MODE) +TOKEN_DEF(ALLOW_WINDOWED_MODE) +TOKEN_DEF(ALLOW_ACCESSIBILITY_TAB) +TOKEN_DEF(ALLOW_ABOUT_TAB) +TOKEN_DEF(ALLOW_ADVANCED) +TOKEN_DEF(ALLOW_DESKTOP_RES) +TOKEN_DEF(REGISTRY_PATH) +TOKEN_DEF(PERSONAL_SAVEGAMES) +TOKEN_DEF(SCRIPT) +TOKEN_DEF(CAPTION) +TOKEN_DEF(PROPERTY) +TOKEN_DEF(SUBTITLES_SPEED) +TOKEN_DEF(SUBTITLES) +TOKEN_DEF(VIDEO_SUBTITLES) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF(THUMBNAIL_WIDTH) +TOKEN_DEF(THUMBNAIL_HEIGHT) +TOKEN_DEF(INDICATOR_X) +TOKEN_DEF(INDICATOR_Y) +TOKEN_DEF(INDICATOR_WIDTH) +TOKEN_DEF(INDICATOR_HEIGHT) +TOKEN_DEF(INDICATOR_COLOR) +TOKEN_DEF(SAVE_IMAGE_X) +TOKEN_DEF(SAVE_IMAGE_Y) +TOKEN_DEF(SAVE_IMAGE) +TOKEN_DEF(LOAD_IMAGE_X) +TOKEN_DEF(LOAD_IMAGE_Y) +TOKEN_DEF(LOAD_IMAGE) +TOKEN_DEF(LOCAL_SAVE_DIR) +TOKEN_DEF(RICH_SAVED_GAMES) +TOKEN_DEF(SAVED_GAME_EXT) +TOKEN_DEF(GUID) +TOKEN_DEF(COMPAT_KILL_METHOD_THREADS) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::LoadBuffer(byte *Buffer, bool Complete) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(GAME) + TOKEN_TABLE(TEMPLATE) + TOKEN_TABLE(NAME) + TOKEN_TABLE(SYSTEM_FONT) + TOKEN_TABLE(VIDEO_FONT) + TOKEN_TABLE(EVENTS) + TOKEN_TABLE(CURSOR) + TOKEN_TABLE(ACTIVE_CURSOR) + TOKEN_TABLE(NONINTERACTIVE_CURSOR) + TOKEN_TABLE(PERSONAL_SAVEGAMES) + TOKEN_TABLE(SCRIPT) + TOKEN_TABLE(CAPTION) + TOKEN_TABLE(PROPERTY) + TOKEN_TABLE(SUBTITLES_SPEED) + TOKEN_TABLE(SUBTITLES) + TOKEN_TABLE(VIDEO_SUBTITLES) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE(THUMBNAIL_WIDTH) + TOKEN_TABLE(THUMBNAIL_HEIGHT) + TOKEN_TABLE(INDICATOR_X) + TOKEN_TABLE(INDICATOR_Y) + TOKEN_TABLE(INDICATOR_WIDTH) + TOKEN_TABLE(INDICATOR_HEIGHT) + TOKEN_TABLE(INDICATOR_COLOR) + TOKEN_TABLE(SAVE_IMAGE_X) + TOKEN_TABLE(SAVE_IMAGE_Y) + TOKEN_TABLE(SAVE_IMAGE) + TOKEN_TABLE(LOAD_IMAGE_X) + TOKEN_TABLE(LOAD_IMAGE_Y) + TOKEN_TABLE(LOAD_IMAGE) + TOKEN_TABLE(LOCAL_SAVE_DIR) + TOKEN_TABLE(COMPAT_KILL_METHOD_THREADS) + TOKEN_TABLE_END + + byte *params; + int cmd; + CBParser parser(Game); + + if (Complete) { + if (parser.GetCommand((char **)&Buffer, commands, (char **)¶ms) != TOKEN_GAME) { + Game->LOG(0, "'GAME' keyword expected."); + return E_FAIL; + } + Buffer = params; + } + + while ((cmd = parser.GetCommand((char **)&Buffer, commands, (char **)¶ms)) > 0) { + switch (cmd) { + case TOKEN_TEMPLATE: + if (FAILED(LoadFile((char *)params))) cmd = PARSERR_GENERIC; + break; + + case TOKEN_NAME: + SetName((char *)params); + break; + + case TOKEN_CAPTION: + SetCaption((char *)params); + break; + + case TOKEN_SYSTEM_FONT: + if (m_SystemFont) m_FontStorage->RemoveFont(m_SystemFont); + m_SystemFont = NULL; + + m_SystemFont = Game->m_FontStorage->AddFont((char *)params); + break; + + case TOKEN_VIDEO_FONT: + if (m_VideoFont) m_FontStorage->RemoveFont(m_VideoFont); + m_VideoFont = NULL; + + m_VideoFont = Game->m_FontStorage->AddFont((char *)params); + break; + + + case TOKEN_CURSOR: + delete m_Cursor; + m_Cursor = new CBSprite(Game); + if (!m_Cursor || FAILED(m_Cursor->LoadFile((char *)params))) { + delete m_Cursor; + m_Cursor = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_ACTIVE_CURSOR: + delete m_ActiveCursor; + m_ActiveCursor = NULL; + m_ActiveCursor = new CBSprite(Game); + if (!m_ActiveCursor || FAILED(m_ActiveCursor->LoadFile((char *)params))) { + delete m_ActiveCursor; + m_ActiveCursor = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_NONINTERACTIVE_CURSOR: + delete m_CursorNoninteractive; + m_CursorNoninteractive = new CBSprite(Game); + if (!m_CursorNoninteractive || FAILED(m_CursorNoninteractive->LoadFile((char *)params))) { + delete m_CursorNoninteractive; + m_CursorNoninteractive = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_SCRIPT: + AddScript((char *)params); + break; + + case TOKEN_PERSONAL_SAVEGAMES: + parser.ScanStr((char *)params, "%b", &m_PersonalizedSave); + break; + + case TOKEN_SUBTITLES: + parser.ScanStr((char *)params, "%b", &m_Subtitles); + break; + + case TOKEN_SUBTITLES_SPEED: + parser.ScanStr((char *)params, "%d", &m_SubtitlesSpeed); + break; + + case TOKEN_VIDEO_SUBTITLES: + parser.ScanStr((char *)params, "%b", &m_VideoSubtitles); + break; + + case TOKEN_PROPERTY: + ParseProperty(params, false); + break; + + case TOKEN_EDITOR_PROPERTY: + ParseEditorProperty(params, false); + break; + + case TOKEN_THUMBNAIL_WIDTH: + parser.ScanStr((char *)params, "%d", &m_ThumbnailWidth); + break; + + case TOKEN_THUMBNAIL_HEIGHT: + parser.ScanStr((char *)params, "%d", &m_ThumbnailHeight); + break; + + case TOKEN_INDICATOR_X: + parser.ScanStr((char *)params, "%d", &m_IndicatorX); + break; + + case TOKEN_INDICATOR_Y: + parser.ScanStr((char *)params, "%d", &m_IndicatorY); + break; + + case TOKEN_INDICATOR_COLOR: { + int r, g, b, a; + parser.ScanStr((char *)params, "%d,%d,%d,%d", &r, &g, &b, &a); + m_IndicatorColor = DRGBA(r, g, b, a); + } + break; + + case TOKEN_INDICATOR_WIDTH: + parser.ScanStr((char *)params, "%d", &m_IndicatorWidth); + break; + + case TOKEN_INDICATOR_HEIGHT: + parser.ScanStr((char *)params, "%d", &m_IndicatorHeight); + break; + + case TOKEN_SAVE_IMAGE: + CBUtils::SetString(&m_SaveImageName, (char *)params); + break; + + case TOKEN_SAVE_IMAGE_X: + parser.ScanStr((char *)params, "%d", &m_SaveImageX); + break; + + case TOKEN_SAVE_IMAGE_Y: + parser.ScanStr((char *)params, "%d", &m_SaveImageY); + break; + + case TOKEN_LOAD_IMAGE: + CBUtils::SetString(&m_LoadImageName, (char *)params); + break; + + case TOKEN_LOAD_IMAGE_X: + parser.ScanStr((char *)params, "%d", &m_LoadImageX); + break; + + case TOKEN_LOAD_IMAGE_Y: + parser.ScanStr((char *)params, "%d", &m_LoadImageY); + break; + + case TOKEN_LOCAL_SAVE_DIR: + CBUtils::SetString(&m_LocalSaveDir, (char *)params); + break; + + case TOKEN_COMPAT_KILL_METHOD_THREADS: + parser.ScanStr((char *)params, "%b", &m_CompatKillMethodThreads); + break; + } + } + + if (!m_SystemFont) m_SystemFont = Game->m_FontStorage->AddFont("system_font.fnt"); + + + if (cmd == PARSERR_TOKENNOTFOUND) { + Game->LOG(0, "Syntax error in GAME definition"); + return E_FAIL; + } + if (cmd == PARSERR_GENERIC) { + Game->LOG(0, "Error loading GAME definition"); + return E_FAIL; + } + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name) { + ////////////////////////////////////////////////////////////////////////// + // LOG + ////////////////////////////////////////////////////////////////////////// + if (strcmp(Name, "LOG") == 0) { + Stack->CorrectParams(1); + LOG(0, Stack->Pop()->GetString()); + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Caption + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Caption") == 0) { + HRESULT res = CBObject::ScCallMethod(Script, Stack, ThisStack, Name); + SetWindowTitle(); + return res; + } + + ////////////////////////////////////////////////////////////////////////// + // Msg + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Msg") == 0) { + Stack->CorrectParams(1); + QuickMessage(Stack->Pop()->GetString()); + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // RunScript + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "RunScript") == 0) { + Game->LOG(0, "**Warning** The 'RunScript' method is now obsolete. Use 'AttachScript' instead (same syntax)"); + Stack->CorrectParams(1); + if (FAILED(AddScript(Stack->Pop()->GetString()))) + Stack->PushBool(false); + else + Stack->PushBool(true); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // LoadStringTable + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "LoadStringTable") == 0) { + Stack->CorrectParams(2); + char *Filename = Stack->Pop()->GetString(); + CScValue *Val = Stack->Pop(); + + bool ClearOld; + if (Val->IsNULL()) ClearOld = true; + else ClearOld = Val->GetBool(); + + if (FAILED(m_StringTable->LoadFile(Filename, ClearOld))) + Stack->PushBool(false); + else + Stack->PushBool(true); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ValidObject + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "ValidObject") == 0) { + Stack->CorrectParams(1); + CBScriptable *obj = Stack->Pop()->GetNative(); + if (ValidObject((CBObject *) obj)) Stack->PushBool(true); + else Stack->PushBool(false); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Reset + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Reset") == 0) { + Stack->CorrectParams(0); + ResetContent(); + Stack->PushNULL(); + + return S_OK; + } + + + ////////////////////////////////////////////////////////////////////////// + // UnloadObject + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "UnloadObject") == 0) { + Stack->CorrectParams(1); + CScValue *val = Stack->Pop(); + CBObject *obj = (CBObject *)val->GetNative(); + UnregisterObject(obj); + if (val->GetType() == VAL_VARIABLE_REF) val->SetNULL(); + + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // LoadWindow + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "LoadWindow") == 0) { + Stack->CorrectParams(1); + CUIWindow *win = new CUIWindow(Game); + if (win && SUCCEEDED(win->LoadFile(Stack->Pop()->GetString()))) { + m_Windows.Add(win); + RegisterObject(win); + Stack->PushNative(win, true); + } else { + delete win; + win = NULL; + Stack->PushNULL(); + } + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ExpandString + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "ExpandString") == 0) { + Stack->CorrectParams(1); + CScValue *val = Stack->Pop(); + char *str = new char[strlen(val->GetString()) + 1]; + strcpy(str, val->GetString()); + m_StringTable->Expand(&str); + Stack->PushString(str); + delete [] str; + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // PlayMusic / PlayMusicChannel + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "PlayMusic") == 0 || strcmp(Name, "PlayMusicChannel") == 0) { + int Channel = 0; + if (strcmp(Name, "PlayMusic") == 0) Stack->CorrectParams(3); + else { + Stack->CorrectParams(4); + Channel = Stack->Pop()->GetInt(); + } + + char *Filename = Stack->Pop()->GetString(); + CScValue *ValLooping = Stack->Pop(); + bool Looping = ValLooping->IsNULL() ? true : ValLooping->GetBool(); + + CScValue *ValLoopStart = Stack->Pop(); + uint32 LoopStart = (uint32)(ValLoopStart->IsNULL() ? 0 : ValLoopStart->GetInt()); + + + if (FAILED(PlayMusic(Channel, Filename, Looping, LoopStart))) Stack->PushBool(false); + else Stack->PushBool(true); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // StopMusic / StopMusicChannel + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "StopMusic") == 0 || strcmp(Name, "StopMusicChannel") == 0) { + int Channel = 0; + + if (strcmp(Name, "StopMusic") == 0) Stack->CorrectParams(0); + else { + Stack->CorrectParams(1); + Channel = Stack->Pop()->GetInt(); + } + + if (FAILED(StopMusic(Channel))) Stack->PushBool(false); + else Stack->PushBool(true); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // PauseMusic / PauseMusicChannel + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "PauseMusic") == 0 || strcmp(Name, "PauseMusicChannel") == 0) { + int Channel = 0; + + if (strcmp(Name, "PauseMusic") == 0) Stack->CorrectParams(0); + else { + Stack->CorrectParams(1); + Channel = Stack->Pop()->GetInt(); + } + + if (FAILED(PauseMusic(Channel))) Stack->PushBool(false); + else Stack->PushBool(true); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ResumeMusic / ResumeMusicChannel + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "ResumeMusic") == 0 || strcmp(Name, "ResumeMusicChannel") == 0) { + int Channel = 0; + if (strcmp(Name, "ResumeMusic") == 0) Stack->CorrectParams(0); + else { + Stack->CorrectParams(1); + Channel = Stack->Pop()->GetInt(); + } + + if (FAILED(ResumeMusic(Channel))) Stack->PushBool(false); + else Stack->PushBool(true); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetMusic / GetMusicChannel + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "GetMusic") == 0 || strcmp(Name, "GetMusicChannel") == 0) { + int Channel = 0; + if (strcmp(Name, "GetMusic") == 0) Stack->CorrectParams(0); + else { + Stack->CorrectParams(1); + Channel = Stack->Pop()->GetInt(); + } + if (Channel < 0 || Channel >= NUM_MUSIC_CHANNELS) Stack->PushNULL(); + else { + if (!m_Music[Channel] || !m_Music[Channel]->m_SoundFilename) Stack->PushNULL(); + else Stack->PushString(m_Music[Channel]->m_SoundFilename); + } + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetMusicPosition / SetMusicChannelPosition + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SetMusicPosition") == 0 || strcmp(Name, "SetMusicChannelPosition") == 0 || strcmp(Name, "SetMusicPositionChannel") == 0) { + int Channel = 0; + if (strcmp(Name, "SetMusicPosition") == 0) Stack->CorrectParams(1); + else { + Stack->CorrectParams(2); + Channel = Stack->Pop()->GetInt(); + } + + uint32 Time = Stack->Pop()->GetInt(); + + if (FAILED(SetMusicStartTime(Channel, Time))) Stack->PushBool(false); + else Stack->PushBool(true); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetMusicPosition / GetMusicChannelPosition + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "GetMusicPosition") == 0 || strcmp(Name, "GetMusicChannelPosition") == 0) { + int Channel = 0; + if (strcmp(Name, "GetMusicPosition") == 0) Stack->CorrectParams(0); + else { + Stack->CorrectParams(1); + Channel = Stack->Pop()->GetInt(); + } + + if (Channel < 0 || Channel >= NUM_MUSIC_CHANNELS || !m_Music[Channel]) Stack->PushInt(0); + else Stack->PushInt(m_Music[Channel]->GetPositionTime()); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // IsMusicPlaying / IsMusicChannelPlaying + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "IsMusicPlaying") == 0 || strcmp(Name, "IsMusicChannelPlaying") == 0) { + int Channel = 0; + if (strcmp(Name, "IsMusicPlaying") == 0) Stack->CorrectParams(0); + else { + Stack->CorrectParams(1); + Channel = Stack->Pop()->GetInt(); + } + + if (Channel < 0 || Channel >= NUM_MUSIC_CHANNELS || !m_Music[Channel]) Stack->PushBool(false); + else Stack->PushBool(m_Music[Channel]->IsPlaying()); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetMusicVolume / SetMusicChannelVolume + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SetMusicVolume") == 0 || strcmp(Name, "SetMusicChannelVolume") == 0) { + int Channel = 0; + if (strcmp(Name, "SetMusicVolume") == 0) Stack->CorrectParams(1); + else { + Stack->CorrectParams(2); + Channel = Stack->Pop()->GetInt(); + } + + int Volume = Stack->Pop()->GetInt(); + if (Channel < 0 || Channel >= NUM_MUSIC_CHANNELS || !m_Music[Channel]) Stack->PushBool(false); + else { + if (FAILED(m_Music[Channel]->SetVolume(Volume))) Stack->PushBool(false); + else Stack->PushBool(true); + } + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetMusicVolume / GetMusicChannelVolume + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "GetMusicVolume") == 0 || strcmp(Name, "GetMusicChannelVolume") == 0) { + int Channel = 0; + if (strcmp(Name, "GetMusicVolume") == 0) Stack->CorrectParams(0); + else { + Stack->CorrectParams(1); + Channel = Stack->Pop()->GetInt(); + } + + if (Channel < 0 || Channel >= NUM_MUSIC_CHANNELS || !m_Music[Channel]) Stack->PushInt(0); + else Stack->PushInt(m_Music[Channel]->GetVolume()); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // MusicCrossfade + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "MusicCrossfade") == 0) { + Stack->CorrectParams(4); + int Channel1 = Stack->Pop()->GetInt(0); + int Channel2 = Stack->Pop()->GetInt(0); + uint32 FadeLength = (uint32)Stack->Pop()->GetInt(0); + bool Swap = Stack->Pop()->GetBool(true); + + if (m_MusicCrossfadeRunning) { + Script->RuntimeError("Game.MusicCrossfade: Music crossfade is already in progress."); + Stack->PushBool(false); + return S_OK; + } + + m_MusicCrossfadeStartTime = m_LiveTimer; + m_MusicCrossfadeChannel1 = Channel1; + m_MusicCrossfadeChannel2 = Channel2; + m_MusicCrossfadeLength = FadeLength; + m_MusicCrossfadeSwap = Swap; + + m_MusicCrossfadeRunning = true; + + Stack->PushBool(true); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetSoundLength + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "GetSoundLength") == 0) { + Stack->CorrectParams(1); + + int Length = 0; + char *Filename = Stack->Pop()->GetString(); + + CBSound *Sound = new CBSound(Game); + if (Sound && SUCCEEDED(Sound->SetSound(Filename, SOUND_MUSIC, true))) { + Length = Sound->GetLength(); + delete Sound; + Sound = NULL; + } + Stack->PushInt(Length); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetMousePos + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SetMousePos") == 0) { + Stack->CorrectParams(2); + int x = Stack->Pop()->GetInt(); + int y = Stack->Pop()->GetInt(); + x = std::max(x, 0); + x = std::min(x, m_Renderer->m_Width); + y = std::max(y, 0); + y = std::min(y, m_Renderer->m_Height); + POINT p; + p.x = x + m_Renderer->m_DrawOffsetX; + p.y = y + m_Renderer->m_DrawOffsetY; + + CBPlatform::SetCursorPos(p.x, p.y); + + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // LockMouseRect + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "LockMouseRect") == 0) { + Stack->CorrectParams(4); + int left = Stack->Pop()->GetInt(); + int top = Stack->Pop()->GetInt(); + int right = Stack->Pop()->GetInt(); + int bottom = Stack->Pop()->GetInt(); + + if (right < left) CBUtils::Swap(&left, &right); + if (bottom < top) CBUtils::Swap(&top, &bottom); + + CBPlatform::SetRect(&m_MouseLockRect, left, top, right, bottom); + + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // PlayVideo + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "PlayVideo") == 0) { + Stack->CorrectParams(0); + Stack->PushBool(false); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // PlayTheora + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "PlayTheora") == 0) { + Stack->CorrectParams(0); + Stack->PushBool(false); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // QuitGame + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "QuitGame") == 0) { + Stack->CorrectParams(0); + Stack->PushNULL(); + m_Quitting = true; + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // RegWriteNumber + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "RegWriteNumber") == 0) { + Stack->CorrectParams(2); + char *Key = Stack->Pop()->GetString(); + int Val = Stack->Pop()->GetInt(); + m_Registry->WriteInt("PrivateSettings", Key, Val); + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // RegReadNumber + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "RegReadNumber") == 0) { + Stack->CorrectParams(2); + char *Key = Stack->Pop()->GetString(); + int InitVal = Stack->Pop()->GetInt(); + Stack->PushInt(m_Registry->ReadInt("PrivateSettings", Key, InitVal)); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // RegWriteString + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "RegWriteString") == 0) { + Stack->CorrectParams(2); + char *Key = Stack->Pop()->GetString(); + char *Val = Stack->Pop()->GetString(); + m_Registry->WriteString("PrivateSettings", Key, Val); + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // RegReadString + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "RegReadString") == 0) { + Stack->CorrectParams(2); + char *Key = Stack->Pop()->GetString(); + char *InitVal = Stack->Pop()->GetString(); + AnsiString val = m_Registry->ReadString("PrivateSettings", Key, InitVal); + Stack->PushString((char *)val.c_str()); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SaveGame + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SaveGame") == 0) { + Stack->CorrectParams(3); + int Slot = Stack->Pop()->GetInt(); + char *xdesc = Stack->Pop()->GetString(); + bool quick = Stack->Pop()->GetBool(false); + + char *Desc = new char[strlen(xdesc) + 1]; + strcpy(Desc, xdesc); + Stack->PushBool(true); + if (FAILED(SaveGame(Slot, Desc, quick))) { + Stack->Pop(); + Stack->PushBool(false); + } + delete [] Desc; + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // LoadGame + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "LoadGame") == 0) { + Stack->CorrectParams(1); + m_ScheduledLoadSlot = Stack->Pop()->GetInt(); + m_Loading = true; + Stack->PushBool(false); + Script->Sleep(0); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // IsSaveSlotUsed + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "IsSaveSlotUsed") == 0) { + Stack->CorrectParams(1); + int Slot = Stack->Pop()->GetInt(); + Stack->PushBool(IsSaveSlotUsed(Slot)); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetSaveSlotDescription + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "GetSaveSlotDescription") == 0) { + Stack->CorrectParams(1); + int Slot = Stack->Pop()->GetInt(); + char Desc[512]; + Desc[0] = '\0'; + GetSaveSlotDescription(Slot, Desc); + Stack->PushString(Desc); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // EmptySaveSlot + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "EmptySaveSlot") == 0) { + Stack->CorrectParams(1); + int Slot = Stack->Pop()->GetInt(); + EmptySaveSlot(Slot); + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetGlobalSFXVolume + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SetGlobalSFXVolume") == 0) { + Stack->CorrectParams(1); + Game->m_SoundMgr->SetVolumePercent(SOUND_SFX, (byte )Stack->Pop()->GetInt()); + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetGlobalSpeechVolume + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SetGlobalSpeechVolume") == 0) { + Stack->CorrectParams(1); + Game->m_SoundMgr->SetVolumePercent(SOUND_SPEECH, (byte )Stack->Pop()->GetInt()); + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetGlobalMusicVolume + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SetGlobalMusicVolume") == 0) { + Stack->CorrectParams(1); + Game->m_SoundMgr->SetVolumePercent(SOUND_MUSIC, (byte )Stack->Pop()->GetInt()); + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetGlobalMasterVolume + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SetGlobalMasterVolume") == 0) { + Stack->CorrectParams(1); + Game->m_SoundMgr->SetMasterVolumePercent((byte )Stack->Pop()->GetInt()); + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetGlobalSFXVolume + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "GetGlobalSFXVolume") == 0) { + Stack->CorrectParams(0); + Stack->PushInt(m_SoundMgr->GetVolumePercent(SOUND_SFX)); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetGlobalSpeechVolume + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "GetGlobalSpeechVolume") == 0) { + Stack->CorrectParams(0); + Stack->PushInt(m_SoundMgr->GetVolumePercent(SOUND_SPEECH)); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetGlobalMusicVolume + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "GetGlobalMusicVolume") == 0) { + Stack->CorrectParams(0); + Stack->PushInt(m_SoundMgr->GetVolumePercent(SOUND_MUSIC)); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetGlobalMasterVolume + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "GetGlobalMasterVolume") == 0) { + Stack->CorrectParams(0); + Stack->PushInt(m_SoundMgr->GetMasterVolumePercent()); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetActiveCursor + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SetActiveCursor") == 0) { + Stack->CorrectParams(1); + if (SUCCEEDED(SetActiveCursor(Stack->Pop()->GetString()))) Stack->PushBool(true); + else Stack->PushBool(false); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetActiveCursor + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "GetActiveCursor") == 0) { + Stack->CorrectParams(0); + if (!m_ActiveCursor || !m_ActiveCursor->m_Filename) Stack->PushNULL(); + else Stack->PushString(m_ActiveCursor->m_Filename); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetActiveCursorObject + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "GetActiveCursorObject") == 0) { + Stack->CorrectParams(0); + if (!m_ActiveCursor) Stack->PushNULL(); + else Stack->PushNative(m_ActiveCursor, true); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // RemoveActiveCursor + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "RemoveActiveCursor") == 0) { + Stack->CorrectParams(0); + delete m_ActiveCursor; + m_ActiveCursor = NULL; + Stack->PushNULL(); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // HasActiveCursor + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "HasActiveCursor") == 0) { + Stack->CorrectParams(0); + + if (m_ActiveCursor) Stack->PushBool(true); + else Stack->PushBool(false); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // FileExists + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "FileExists") == 0) { + Stack->CorrectParams(1); + char *Filename = Stack->Pop()->GetString(); + + CBFile *File = m_FileManager->OpenFile(Filename, false); + if (!File) Stack->PushBool(false); + else { + m_FileManager->CloseFile(File); + Stack->PushBool(true); + } + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // FadeOut / FadeOutAsync / SystemFadeOut / SystemFadeOutAsync + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "FadeOut") == 0 || strcmp(Name, "FadeOutAsync") == 0 || strcmp(Name, "SystemFadeOut") == 0 || strcmp(Name, "SystemFadeOutAsync") == 0) { + Stack->CorrectParams(5); + uint32 Duration = Stack->Pop()->GetInt(500); + byte Red = Stack->Pop()->GetInt(0); + byte Green = Stack->Pop()->GetInt(0); + byte Blue = Stack->Pop()->GetInt(0); + byte Alpha = Stack->Pop()->GetInt(0xFF); + + bool System = (strcmp(Name, "SystemFadeOut") == 0 || strcmp(Name, "SystemFadeOutAsync") == 0); + + m_Fader->FadeOut(DRGBA(Red, Green, Blue, Alpha), Duration, System); + if (strcmp(Name, "FadeOutAsync") != 0 && strcmp(Name, "SystemFadeOutAsync") != 0) Script->WaitFor(m_Fader); + + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // FadeIn / FadeInAsync / SystemFadeIn / SystemFadeInAsync + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "FadeIn") == 0 || strcmp(Name, "FadeInAsync") == 0 || strcmp(Name, "SystemFadeIn") == 0 || strcmp(Name, "SystemFadeInAsync") == 0) { + Stack->CorrectParams(5); + uint32 Duration = Stack->Pop()->GetInt(500); + byte Red = Stack->Pop()->GetInt(0); + byte Green = Stack->Pop()->GetInt(0); + byte Blue = Stack->Pop()->GetInt(0); + byte Alpha = Stack->Pop()->GetInt(0xFF); + + bool System = (strcmp(Name, "SystemFadeIn") == 0 || strcmp(Name, "SystemFadeInAsync") == 0); + + m_Fader->FadeIn(DRGBA(Red, Green, Blue, Alpha), Duration, System); + if (strcmp(Name, "FadeInAsync") != 0 && strcmp(Name, "SystemFadeInAsync") != 0) Script->WaitFor(m_Fader); + + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetFadeColor + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "GetFadeColor") == 0) { + Stack->CorrectParams(0); + Stack->PushInt(m_Fader->GetCurrentColor()); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Screenshot + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Screenshot") == 0) { + Stack->CorrectParams(1); + char Filename[MAX_PATH]; + + CScValue *Val = Stack->Pop(); + + int FileNum = 0; + while (true) { + sprintf(Filename, "%s%03d.bmp", Val->IsNULL() ? m_Name : Val->GetString(), FileNum); + FILE *f = fopen(Filename, "rb"); + if (!f) break; + else fclose(f); + FileNum++; + } + + bool ret = false; + CBImage *Image = Game->m_Renderer->TakeScreenshot(); + if (Image) { + ret = SUCCEEDED(Image->SaveBMPFile(Filename)); + delete Image; + } else ret = false; + + Stack->PushBool(ret); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ScreenshotEx + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "ScreenshotEx") == 0) { + Stack->CorrectParams(3); + char *Filename = Stack->Pop()->GetString(); + int SizeX = Stack->Pop()->GetInt(m_Renderer->m_Width); + int SizeY = Stack->Pop()->GetInt(m_Renderer->m_Height); + + bool ret = false; + CBImage *Image = Game->m_Renderer->TakeScreenshot(); + if (Image) { + ret = SUCCEEDED(Image->Resize(SizeX, SizeY)); + if (ret) ret = SUCCEEDED(Image->SaveBMPFile(Filename)); + delete Image; + } else ret = false; + + Stack->PushBool(ret); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // CreateWindow + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "CreateWindow") == 0) { + Stack->CorrectParams(1); + CScValue *Val = Stack->Pop(); + + CUIWindow *Win = new CUIWindow(Game); + m_Windows.Add(Win); + RegisterObject(Win); + if (!Val->IsNULL()) Win->SetName(Val->GetString()); + Stack->PushNative(Win, true); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // DeleteWindow + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "DeleteWindow") == 0) { + Stack->CorrectParams(1); + CBObject *Obj = (CBObject *)Stack->Pop()->GetNative(); + for (int i = 0; i < m_Windows.GetSize(); i++) { + if (m_Windows[i] == Obj) { + UnregisterObject(m_Windows[i]); + Stack->PushBool(true); + return S_OK; + } + } + Stack->PushBool(false); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // OpenDocument + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "OpenDocument") == 0) { +#ifdef __WIN32__ + Stack->CorrectParams(1); + if (!m_Renderer->m_Windowed) CBPlatform::ShowWindow(m_Renderer->m_Window, SW_MINIMIZE); + HINSTANCE i = CBPlatform::ShellExecute(m_Renderer->m_Window, "open", Stack->Pop()->GetString(), NULL, NULL, SW_MAXIMIZE); + Stack->PushBool((int)i > 32); +#else + Stack->CorrectParams(0); + Stack->PushNULL(); +#endif + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // DEBUG_DumpClassRegistry + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "DEBUG_DumpClassRegistry") == 0) { + Stack->CorrectParams(0); + DEBUG_DumpClassRegistry(); + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetLoadingScreen + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SetLoadingScreen") == 0) { + Stack->CorrectParams(3); + CScValue *Val = Stack->Pop(); + m_LoadImageX = Stack->Pop()->GetInt(); + m_LoadImageY = Stack->Pop()->GetInt(); + + if (Val->IsNULL()) { + delete[] m_LoadImageName; + m_LoadImageName = NULL; + } else { + CBUtils::SetString(&m_LoadImageName, Val->GetString()); + } + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetSavingScreen + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SetSavingScreen") == 0) { + Stack->CorrectParams(3); + CScValue *Val = Stack->Pop(); + m_SaveImageX = Stack->Pop()->GetInt(); + m_SaveImageY = Stack->Pop()->GetInt(); + + if (Val->IsNULL()) { + delete[] m_SaveImageName; + m_SaveImageName = NULL; + } else { + CBUtils::SetString(&m_SaveImageName, Val->GetString()); + } + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetWaitCursor + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SetWaitCursor") == 0) { + Stack->CorrectParams(1); + if (SUCCEEDED(SetWaitCursor(Stack->Pop()->GetString()))) Stack->PushBool(true); + else Stack->PushBool(false); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // RemoveWaitCursor + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "RemoveWaitCursor") == 0) { + Stack->CorrectParams(0); + delete m_CursorNoninteractive; + m_CursorNoninteractive = NULL; + + Stack->PushNULL(); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetWaitCursor + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "GetWaitCursor") == 0) { + Stack->CorrectParams(0); + if (!m_CursorNoninteractive || !m_CursorNoninteractive->m_Filename) Stack->PushNULL(); + else Stack->PushString(m_CursorNoninteractive->m_Filename); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetWaitCursorObject + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "GetWaitCursorObject") == 0) { + Stack->CorrectParams(0); + if (!m_CursorNoninteractive) Stack->PushNULL(); + else Stack->PushNative(m_CursorNoninteractive, true); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ClearScriptCache + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "ClearScriptCache") == 0) { + Stack->CorrectParams(0); + Stack->PushBool(SUCCEEDED(m_ScEngine->EmptyScriptCache())); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // DisplayLoadingIcon + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "DisplayLoadingIcon") == 0) { + Stack->CorrectParams(4); + + char *Filename = Stack->Pop()->GetString(); + m_LoadingIconX = Stack->Pop()->GetInt(); + m_LoadingIconY = Stack->Pop()->GetInt(); + m_LoadingIconPersistent = Stack->Pop()->GetBool(); + + delete m_LoadingIcon; + m_LoadingIcon = new CBSprite(this); + if (!m_LoadingIcon || FAILED(m_LoadingIcon->LoadFile(Filename))) { + delete m_LoadingIcon; + m_LoadingIcon = NULL; + } else { + DisplayContent(false, true); + Game->m_Renderer->Flip(); + Game->m_Renderer->InitLoop(); + } + Stack->PushNULL(); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // HideLoadingIcon + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "HideLoadingIcon") == 0) { + Stack->CorrectParams(0); + delete m_LoadingIcon; + m_LoadingIcon = NULL; + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // DumpTextureStats + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "DumpTextureStats") == 0) { + Stack->CorrectParams(1); + char *Filename = Stack->Pop()->GetString(); + + m_Renderer->DumpData(Filename); + + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // AccOutputText + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "AccOutputText") == 0) { + Stack->CorrectParams(2); + char *Str = Stack->Pop()->GetString(); + int Type = Stack->Pop()->GetInt(); + // do nothing + Stack->PushNULL(); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // StoreSaveThumbnail + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "StoreSaveThumbnail") == 0) { + Stack->CorrectParams(0); + delete m_CachedThumbnail; + m_CachedThumbnail = new CBSaveThumbHelper(this); + if (FAILED(m_CachedThumbnail->StoreThumbnail())) { + delete m_CachedThumbnail; + m_CachedThumbnail = NULL; + Stack->PushBool(false); + } else Stack->PushBool(true); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // DeleteSaveThumbnail + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "DeleteSaveThumbnail") == 0) { + Stack->CorrectParams(0); + delete m_CachedThumbnail; + m_CachedThumbnail = NULL; + Stack->PushNULL(); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetFileChecksum + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "GetFileChecksum") == 0) { + Stack->CorrectParams(2); + char *Filename = Stack->Pop()->GetString(); + bool AsHex = Stack->Pop()->GetBool(false); + + CBFile *File = m_FileManager->OpenFile(Filename, false); + if (File) { + crc remainder = crc_initialize(); + byte Buf[1024]; + int BytesRead = 0; + + while (BytesRead < File->GetSize()) { + int BufSize = MIN(1024, File->GetSize() - BytesRead); + BytesRead += BufSize; + + File->Read(Buf, BufSize); + for (int i = 0; i < BufSize; i++) { + remainder = crc_process_byte(Buf[i], remainder); + } + } + crc checksum = crc_finalize(remainder); + + if (AsHex) { + char Hex[100]; + sprintf(Hex, "%x", checksum); + Stack->PushString(Hex); + } else + Stack->PushInt(checksum); + + m_FileManager->CloseFile(File); + File = NULL; + } else Stack->PushNULL(); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // EnableScriptProfiling + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "EnableScriptProfiling") == 0) { + Stack->CorrectParams(0); + m_ScEngine->EnableProfiling(); + Stack->PushNULL(); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // DisableScriptProfiling + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "DisableScriptProfiling") == 0) { + Stack->CorrectParams(0); + m_ScEngine->DisableProfiling(); + Stack->PushNULL(); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ShowStatusLine + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "ShowStatusLine") == 0) { + Stack->CorrectParams(0); +#ifdef __IPHONEOS__ + IOS_ShowStatusLine(TRUE); +#endif + Stack->PushNULL(); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // HideStatusLine + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "HideStatusLine") == 0) { + Stack->CorrectParams(0); +#ifdef __IPHONEOS__ + IOS_ShowStatusLine(FALSE); +#endif + Stack->PushNULL(); + + return S_OK; + } + + else return CBObject::ScCallMethod(Script, Stack, ThisStack, Name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CBGame::ScGetProperty(char *Name) { + m_ScValue->SetNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type + ////////////////////////////////////////////////////////////////////////// + if (strcmp(Name, "Type") == 0) { + m_ScValue->SetString("game"); + return m_ScValue; + } + ////////////////////////////////////////////////////////////////////////// + // Name + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Name") == 0) { + m_ScValue->SetString(m_Name); + return m_ScValue; + } + ////////////////////////////////////////////////////////////////////////// + // Hwnd (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Hwnd") == 0) { + m_ScValue->SetInt((int)m_Renderer->m_Window); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // CurrentTime (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "CurrentTime") == 0) { + m_ScValue->SetInt((int)m_Timer); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // WindowsTime (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "WindowsTime") == 0) { + m_ScValue->SetInt((int)CBPlatform::GetTime()); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // WindowedMode (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "WindowedMode") == 0) { + m_ScValue->SetBool(m_Renderer->m_Windowed); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // MouseX + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "MouseX") == 0) { + m_ScValue->SetInt(m_MousePos.x); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // MouseY + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "MouseY") == 0) { + m_ScValue->SetInt(m_MousePos.y); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // MainObject + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "MainObject") == 0) { + m_ScValue->SetNative(m_MainObject, true); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // ActiveObject (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "ActiveObject") == 0) { + m_ScValue->SetNative(m_ActiveObject, true); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // ScreenWidth (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "ScreenWidth") == 0) { + m_ScValue->SetInt(m_Renderer->m_Width); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // ScreenHeight (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "ScreenHeight") == 0) { + m_ScValue->SetInt(m_Renderer->m_Height); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Interactive + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Interactive") == 0) { + m_ScValue->SetBool(m_Interactive); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // DebugMode (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "DebugMode") == 0) { + m_ScValue->SetBool(m_DEBUG_DebugMode); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // SoundAvailable (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SoundAvailable") == 0) { + m_ScValue->SetBool(m_SoundMgr->m_SoundAvailable); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // SFXVolume + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SFXVolume") == 0) { + Game->LOG(0, "**Warning** The SFXVolume attribute is obsolete"); + m_ScValue->SetInt(m_SoundMgr->GetVolumePercent(SOUND_SFX)); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // SpeechVolume + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SpeechVolume") == 0) { + Game->LOG(0, "**Warning** The SpeechVolume attribute is obsolete"); + m_ScValue->SetInt(m_SoundMgr->GetVolumePercent(SOUND_SPEECH)); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // MusicVolume + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "MusicVolume") == 0) { + Game->LOG(0, "**Warning** The MusicVolume attribute is obsolete"); + m_ScValue->SetInt(m_SoundMgr->GetVolumePercent(SOUND_MUSIC)); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // MasterVolume + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "MasterVolume") == 0) { + Game->LOG(0, "**Warning** The MasterVolume attribute is obsolete"); + m_ScValue->SetInt(m_SoundMgr->GetMasterVolumePercent()); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Keyboard (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Keyboard") == 0) { + if (m_KeyboardState) m_ScValue->SetNative(m_KeyboardState, true); + else m_ScValue->SetNULL(); + + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Subtitles + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Subtitles") == 0) { + m_ScValue->SetBool(m_Subtitles); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // SubtitlesSpeed + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SubtitlesSpeed") == 0) { + m_ScValue->SetInt(m_SubtitlesSpeed); + return m_ScValue; + } + ////////////////////////////////////////////////////////////////////////// + // VideoSubtitles + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "VideoSubtitles") == 0) { + m_ScValue->SetBool(m_VideoSubtitles); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // FPS (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "FPS") == 0) { + m_ScValue->SetInt(m_Fps); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // AcceleratedMode / Accelerated (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "AcceleratedMode") == 0 || strcmp(Name, "Accelerated") == 0) { + m_ScValue->SetBool(m_UseD3D); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // TextEncoding + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "TextEncoding") == 0) { + m_ScValue->SetInt(m_TextEncoding); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // TextRTL + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "TextRTL") == 0) { + m_ScValue->SetBool(m_TextRTL); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // SoundBufferSize + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SoundBufferSize") == 0) { + m_ScValue->SetInt(m_SoundBufferSizeSec); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // SuspendedRendering + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SuspendedRendering") == 0) { + m_ScValue->SetBool(m_SuspendedRendering); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // SuppressScriptErrors + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SuppressScriptErrors") == 0) { + m_ScValue->SetBool(m_SuppressScriptErrors); + return m_ScValue; + } + + + ////////////////////////////////////////////////////////////////////////// + // Frozen + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Frozen") == 0) { + m_ScValue->SetBool(m_State == GAME_FROZEN); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // AccTTSEnabled + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "AccTTSEnabled") == 0) { + m_ScValue->SetBool(false); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // AccTTSTalk + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "AccTTSTalk") == 0) { + m_ScValue->SetBool(false); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // AccTTSCaptions + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "AccTTSCaptions") == 0) { + m_ScValue->SetBool(false); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // AccTTSKeypress + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "AccTTSKeypress") == 0) { + m_ScValue->SetBool(false); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // AccKeyboardEnabled + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "AccKeyboardEnabled") == 0) { + m_ScValue->SetBool(false); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // AccKeyboardCursorSkip + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "AccKeyboardCursorSkip") == 0) { + m_ScValue->SetBool(false); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // AccKeyboardPause + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "AccKeyboardPause") == 0) { + m_ScValue->SetBool(false); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // AutorunDisabled + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "AutorunDisabled") == 0) { + m_ScValue->SetBool(m_AutorunDisabled); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // SaveDirectory (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SaveDirectory") == 0) { + AnsiString dataDir = GetDataDir(); + m_ScValue->SetString((char *)dataDir.c_str()); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // AutoSaveOnExit + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "AutoSaveOnExit") == 0) { + m_ScValue->SetBool(m_AutoSaveOnExit); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // AutoSaveSlot + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "AutoSaveSlot") == 0) { + m_ScValue->SetInt(m_AutoSaveSlot); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // CursorHidden + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "CursorHidden") == 0) { + m_ScValue->SetBool(m_CursorHidden); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Platform (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Platform") == 0) { + m_ScValue->SetString(CBPlatform::GetPlatformName().c_str()); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // DeviceType (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "DeviceType") == 0) { + m_ScValue->SetString(GetDeviceType().c_str()); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // MostRecentSaveSlot (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "MostRecentSaveSlot") == 0) { + m_ScValue->SetInt(m_Registry->ReadInt("System", "MostRecentSaveSlot", -1)); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Store (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Store") == 0) { + if (m_Store) m_ScValue->SetNative(m_Store, true); + else m_ScValue->SetNULL(); + + return m_ScValue; + } + + else return CBObject::ScGetProperty(Name); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::ScSetProperty(char *Name, CScValue *Value) { + ////////////////////////////////////////////////////////////////////////// + // Name + ////////////////////////////////////////////////////////////////////////// + if (strcmp(Name, "Name") == 0) { + SetName(Value->GetString()); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // MouseX + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "MouseX") == 0) { + m_MousePos.x = Value->GetInt(); + ResetMousePos(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // MouseY + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "MouseY") == 0) { + m_MousePos.y = Value->GetInt(); + ResetMousePos(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Caption + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Name") == 0) { + HRESULT res = CBObject::ScSetProperty(Name, Value); + SetWindowTitle(); + return res; + } + + ////////////////////////////////////////////////////////////////////////// + // MainObject + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "MainObject") == 0) { + CBScriptable *obj = Value->GetNative(); + if (obj == NULL || ValidObject((CBObject *)obj)) m_MainObject = (CBObject *)obj; + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Interactive + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Interactive") == 0) { + SetInteractive(Value->GetBool()); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SFXVolume + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SFXVolume") == 0) { + Game->LOG(0, "**Warning** The SFXVolume attribute is obsolete"); + Game->m_SoundMgr->SetVolumePercent(SOUND_SFX, (byte )Value->GetInt()); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SpeechVolume + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SpeechVolume") == 0) { + Game->LOG(0, "**Warning** The SpeechVolume attribute is obsolete"); + Game->m_SoundMgr->SetVolumePercent(SOUND_SPEECH, (byte )Value->GetInt()); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // MusicVolume + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "MusicVolume") == 0) { + Game->LOG(0, "**Warning** The MusicVolume attribute is obsolete"); + Game->m_SoundMgr->SetVolumePercent(SOUND_MUSIC, (byte )Value->GetInt()); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // MasterVolume + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "MasterVolume") == 0) { + Game->LOG(0, "**Warning** The MasterVolume attribute is obsolete"); + Game->m_SoundMgr->SetMasterVolumePercent((byte )Value->GetInt()); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Subtitles + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Subtitles") == 0) { + m_Subtitles = Value->GetBool(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SubtitlesSpeed + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SubtitlesSpeed") == 0) { + m_SubtitlesSpeed = Value->GetInt(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // VideoSubtitles + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "VideoSubtitles") == 0) { + m_VideoSubtitles = Value->GetBool(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // TextEncoding + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "TextEncoding") == 0) { + int Enc = Value->GetInt(); + if (Enc < 0) Enc = 0; + if (Enc >= NUM_TEXT_ENCODINGS) Enc = NUM_TEXT_ENCODINGS - 1; + m_TextEncoding = (TTextEncoding)Enc; + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // TextRTL + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "TextRTL") == 0) { + m_TextRTL = Value->GetBool(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SoundBufferSize + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SoundBufferSize") == 0) { + m_SoundBufferSizeSec = Value->GetInt(); + m_SoundBufferSizeSec = std::max(3, m_SoundBufferSizeSec); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SuspendedRendering + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SuspendedRendering") == 0) { + m_SuspendedRendering = Value->GetBool(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SuppressScriptErrors + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SuppressScriptErrors") == 0) { + m_SuppressScriptErrors = Value->GetBool(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // AutorunDisabled + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "AutorunDisabled") == 0) { + m_AutorunDisabled = Value->GetBool(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // AutoSaveOnExit + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "AutoSaveOnExit") == 0) { + m_AutoSaveOnExit = Value->GetBool(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // AutoSaveSlot + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "AutoSaveSlot") == 0) { + m_AutoSaveSlot = Value->GetInt(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // CursorHidden + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "CursorHidden") == 0) { + m_CursorHidden = Value->GetBool(); + return S_OK; + } + + else return CBObject::ScSetProperty(Name, Value); +} + + +////////////////////////////////////////////////////////////////////////// +char *CBGame::ScToString() { + return "[game object]"; +} + + + +#define QUICK_MSG_DURATION 3000 +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::DisplayQuickMsg() { + if (m_QuickMessages.GetSize() == 0 || !m_SystemFont) return S_OK; + + int i; + + // update + for (i = 0; i < m_QuickMessages.GetSize(); i++) { + if (m_CurrentTime - m_QuickMessages[i]->m_StartTime >= QUICK_MSG_DURATION) { + delete m_QuickMessages[i]; + m_QuickMessages.RemoveAt(i); + i--; + } + } + + int PosY = 20; + + // display + for (i = 0; i < m_QuickMessages.GetSize(); i++) { + m_SystemFont->DrawText((byte *)m_QuickMessages[i]->GetText(), 0, PosY, m_Renderer->m_Width); + PosY += m_SystemFont->GetTextHeight((byte *)m_QuickMessages[i]->GetText(), m_Renderer->m_Width); + } + return S_OK; +} + + +#define MAX_QUICK_MSG 5 +////////////////////////////////////////////////////////////////////////// +void CBGame::QuickMessage(char *Text) { + if (m_QuickMessages.GetSize() >= MAX_QUICK_MSG) { + delete m_QuickMessages[0]; + m_QuickMessages.RemoveAt(0); + } + m_QuickMessages.Add(new CBQuickMsg(Game, Text)); +} + + +////////////////////////////////////////////////////////////////////////// +void CBGame::QuickMessageForm(LPSTR fmt, ...) { + char buff[256]; + va_list va; + + va_start(va, fmt); + vsprintf(buff, fmt, va); + va_end(va); + + QuickMessage(buff); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::RegisterObject(CBObject *Object) { + m_RegObjects.Add(Object); + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::UnregisterObject(CBObject *Object) { + if (!Object) return S_OK; + + int i; + + // is it a window? + for (i = 0; i < m_Windows.GetSize(); i++) { + if ((CBObject *)m_Windows[i] == Object) { + m_Windows.RemoveAt(i); + + // get new focused window + if (m_FocusedWindow == Object) m_FocusedWindow = NULL; + + break; + } + } + + // is it active object? + if (m_ActiveObject == Object) m_ActiveObject = NULL; + + // is it main object? + if (m_MainObject == Object) m_MainObject = NULL; + + if (m_Store) m_Store->OnObjectDestroyed(Object); + + // destroy object + for (i = 0; i < m_RegObjects.GetSize(); i++) { + if (m_RegObjects[i] == Object) { + m_RegObjects.RemoveAt(i); + if (!m_LoadInProgress) CSysClassRegistry::GetInstance()->EnumInstances(InvalidateValues, "CScValue", (void *)Object); + delete Object; + return S_OK; + } + } + + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +void CBGame::InvalidateValues(void *Value, void *Data) { + CScValue *val = (CScValue *)Value; + if (val->IsNative() && val->GetNative() == Data) { + if (!val->m_Persistent && ((CBScriptable *)Data)->m_RefCount == 1) { + ((CBScriptable *)Data)->m_RefCount++; + } + val->SetNative(NULL); + val->SetNULL(); + } +} + + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::ValidObject(CBObject *Object) { + if (!Object) return false; + if (Object == this) return true; + + for (int i = 0; i < m_RegObjects.GetSize(); i++) { + if (m_RegObjects[i] == Object) return true; + } + return false; +} + + +////////////////////////////////////////////////////////////////////////// +void CBGame::PublishNatives() { + if (!m_ScEngine || !m_ScEngine->m_CompilerAvailable) return; + + m_ScEngine->ExtDefineFunction("LOG"); + m_ScEngine->ExtDefineFunction("String"); + m_ScEngine->ExtDefineFunction("MemBuffer"); + m_ScEngine->ExtDefineFunction("File"); + m_ScEngine->ExtDefineFunction("Date"); + m_ScEngine->ExtDefineFunction("Array"); + m_ScEngine->ExtDefineFunction("TcpClient"); + m_ScEngine->ExtDefineFunction("Object"); + //m_ScEngine->ExtDefineFunction("Game"); + m_ScEngine->ExtDefineFunction("Sleep"); + m_ScEngine->ExtDefineFunction("WaitFor"); + m_ScEngine->ExtDefineFunction("Random"); + m_ScEngine->ExtDefineFunction("SetScriptTimeSlice"); + m_ScEngine->ExtDefineFunction("MakeRGBA"); + m_ScEngine->ExtDefineFunction("MakeRGB"); + m_ScEngine->ExtDefineFunction("MakeHSL"); + m_ScEngine->ExtDefineFunction("RGB"); + m_ScEngine->ExtDefineFunction("GetRValue"); + m_ScEngine->ExtDefineFunction("GetGValue"); + m_ScEngine->ExtDefineFunction("GetBValue"); + m_ScEngine->ExtDefineFunction("GetAValue"); + m_ScEngine->ExtDefineFunction("GetHValue"); + m_ScEngine->ExtDefineFunction("GetSValue"); + m_ScEngine->ExtDefineFunction("GetLValue"); + m_ScEngine->ExtDefineFunction("Debug"); + + m_ScEngine->ExtDefineFunction("ToString"); + m_ScEngine->ExtDefineFunction("ToInt"); + m_ScEngine->ExtDefineFunction("ToBool"); + m_ScEngine->ExtDefineFunction("ToFloat"); + + m_ScEngine->ExtDefineVariable("Game"); + m_ScEngine->ExtDefineVariable("Math"); + m_ScEngine->ExtDefineVariable("Directory"); + m_ScEngine->ExtDefineVariable("self"); + m_ScEngine->ExtDefineVariable("this"); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::ExternalCall(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name) { + CScValue *this_obj; + + ////////////////////////////////////////////////////////////////////////// + // LOG + ////////////////////////////////////////////////////////////////////////// + if (strcmp(Name, "LOG") == 0) { + Stack->CorrectParams(1); + Game->LOG(0, "sc: %s", Stack->Pop()->GetString()); + Stack->PushNULL(); + } + + ////////////////////////////////////////////////////////////////////////// + // String + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "String") == 0) { + this_obj = ThisStack->GetTop(); + + this_obj->SetNative(new CSXString(Game, Stack)); + Stack->PushNULL(); + } + + ////////////////////////////////////////////////////////////////////////// + // MemBuffer + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "MemBuffer") == 0) { + this_obj = ThisStack->GetTop(); + + this_obj->SetNative(new CSXMemBuffer(Game, Stack)); + Stack->PushNULL(); + } + + ////////////////////////////////////////////////////////////////////////// + // File + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "File") == 0) { + this_obj = ThisStack->GetTop(); + + this_obj->SetNative(new CSXFile(Game, Stack)); + Stack->PushNULL(); + } + + ////////////////////////////////////////////////////////////////////////// + // Date + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Date") == 0) { + this_obj = ThisStack->GetTop(); + + this_obj->SetNative(new CSXDate(Game, Stack)); + Stack->PushNULL(); + } + + ////////////////////////////////////////////////////////////////////////// + // Array + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Array") == 0) { + this_obj = ThisStack->GetTop(); + + this_obj->SetNative(new CSXArray(Game, Stack)); + Stack->PushNULL(); + } + + ////////////////////////////////////////////////////////////////////////// + // Object + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Object") == 0) { + this_obj = ThisStack->GetTop(); + + this_obj->SetNative(new CSXObject(Game, Stack)); + Stack->PushNULL(); + } + + ////////////////////////////////////////////////////////////////////////// + // Sleep + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Sleep") == 0) { + Stack->CorrectParams(1); + + Script->Sleep((uint32)Stack->Pop()->GetInt()); + Stack->PushNULL(); + } + + ////////////////////////////////////////////////////////////////////////// + // WaitFor + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "WaitFor") == 0) { + Stack->CorrectParams(1); + + CBScriptable *obj = Stack->Pop()->GetNative(); + if (ValidObject((CBObject *)obj)) Script->WaitForExclusive((CBObject *)obj); + Stack->PushNULL(); + } + + ////////////////////////////////////////////////////////////////////////// + // Random + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Random") == 0) { + Stack->CorrectParams(2); + + int from = Stack->Pop()->GetInt(); + int to = Stack->Pop()->GetInt(); + + Stack->PushInt(CBUtils::RandomInt(from, to)); + } + + ////////////////////////////////////////////////////////////////////////// + // SetScriptTimeSlice + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SetScriptTimeSlice") == 0) { + Stack->CorrectParams(1); + + Script->m_TimeSlice = (uint32)Stack->Pop()->GetInt(); + Stack->PushNULL(); + } + + ////////////////////////////////////////////////////////////////////////// + // MakeRGBA / MakeRGB / RGB + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "MakeRGBA") == 0 || strcmp(Name, "MakeRGB") == 0 || strcmp(Name, "RGB") == 0) { + Stack->CorrectParams(4); + int r = Stack->Pop()->GetInt(); + int g = Stack->Pop()->GetInt(); + int b = Stack->Pop()->GetInt(); + int a; + CScValue *val = Stack->Pop(); + if (val->IsNULL()) a = 255; + else a = val->GetInt(); + + Stack->PushInt(DRGBA(r, g, b, a)); + } + + ////////////////////////////////////////////////////////////////////////// + // MakeHSL + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "MakeHSL") == 0) { + Stack->CorrectParams(3); + int h = Stack->Pop()->GetInt(); + int s = Stack->Pop()->GetInt(); + int l = Stack->Pop()->GetInt(); + + Stack->PushInt(CBUtils::HSLtoRGB(h, s, l)); + } + + ////////////////////////////////////////////////////////////////////////// + // GetRValue + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "GetRValue") == 0) { + Stack->CorrectParams(1); + + uint32 rgba = (uint32)Stack->Pop()->GetInt(); + Stack->PushInt(D3DCOLGetR(rgba)); + } + + ////////////////////////////////////////////////////////////////////////// + // GetGValue + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "GetGValue") == 0) { + Stack->CorrectParams(1); + + uint32 rgba = (uint32)Stack->Pop()->GetInt(); + Stack->PushInt(D3DCOLGetG(rgba)); + } + + ////////////////////////////////////////////////////////////////////////// + // GetBValue + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "GetBValue") == 0) { + Stack->CorrectParams(1); + + uint32 rgba = (uint32)Stack->Pop()->GetInt(); + Stack->PushInt(D3DCOLGetB(rgba)); + } + + ////////////////////////////////////////////////////////////////////////// + // GetAValue + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "GetAValue") == 0) { + Stack->CorrectParams(1); + + uint32 rgba = (uint32)Stack->Pop()->GetInt(); + Stack->PushInt(D3DCOLGetA(rgba)); + } + + ////////////////////////////////////////////////////////////////////////// + // GetHValue + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "GetHValue") == 0) { + Stack->CorrectParams(1); + uint32 rgb = (uint32)Stack->Pop()->GetInt(); + + byte H, S, L; + CBUtils::RGBtoHSL(rgb, &H, &S, &L); + Stack->PushInt(H); + } + + ////////////////////////////////////////////////////////////////////////// + // GetSValue + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "GetSValue") == 0) { + Stack->CorrectParams(1); + uint32 rgb = (uint32)Stack->Pop()->GetInt(); + + byte H, S, L; + CBUtils::RGBtoHSL(rgb, &H, &S, &L); + Stack->PushInt(S); + } + + ////////////////////////////////////////////////////////////////////////// + // GetLValue + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "GetLValue") == 0) { + Stack->CorrectParams(1); + uint32 rgb = (uint32)Stack->Pop()->GetInt(); + + byte H, S, L; + CBUtils::RGBtoHSL(rgb, &H, &S, &L); + Stack->PushInt(L); + } + + ////////////////////////////////////////////////////////////////////////// + // Debug + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Debug") == 0) { + Stack->CorrectParams(0); + + if (Game->GetDebugMgr()->m_Enabled) { + Game->GetDebugMgr()->OnScriptHitBreakpoint(Script); + Script->Sleep(0); + } + Stack->PushNULL(); + } + + ////////////////////////////////////////////////////////////////////////// + // ToString + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "ToString") == 0) { + Stack->CorrectParams(1); + char *Str = Stack->Pop()->GetString(); + char *Str2 = new char[strlen(Str) + 1]; + strcpy(Str2, Str); + Stack->PushString(Str2); + delete [] Str2; + } + + ////////////////////////////////////////////////////////////////////////// + // ToInt + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "ToInt") == 0) { + Stack->CorrectParams(1); + int Val = Stack->Pop()->GetInt(); + Stack->PushInt(Val); + } + + ////////////////////////////////////////////////////////////////////////// + // ToFloat + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "ToFloat") == 0) { + Stack->CorrectParams(1); + double Val = Stack->Pop()->GetFloat(); + Stack->PushFloat(Val); + } + + ////////////////////////////////////////////////////////////////////////// + // ToBool + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "ToBool") == 0) { + Stack->CorrectParams(1); + bool Val = Stack->Pop()->GetBool(); + Stack->PushBool(Val); + } + + ////////////////////////////////////////////////////////////////////////// + // failure + else { + Script->RuntimeError("Call to undefined function '%s'. Ignored.", Name); + Stack->CorrectParams(0); + Stack->PushNULL(); + } + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::ShowCursor() { + if (m_CursorHidden) return S_OK; + + if (!m_Interactive && Game->m_State == GAME_RUNNING) { + if (m_CursorNoninteractive) return DrawCursor(m_CursorNoninteractive); + } else { + if (m_ActiveObject && !FAILED(m_ActiveObject->ShowCursor())) return S_OK; + else { + if (m_ActiveObject && m_ActiveCursor && m_ActiveObject->GetExtendedFlag("usable")) return DrawCursor(m_ActiveCursor); + else if (m_Cursor) return DrawCursor(m_Cursor); + } + } + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::SaveGame(int slot, char *desc, bool quickSave) { + char Filename[MAX_PATH + 1]; + GetSaveSlotFilename(slot, Filename); + + LOG(0, "Saving game '%s'...", Filename); + + Game->ApplyEvent("BeforeSave", true); + + HRESULT ret; + + m_IndicatorDisplay = true; + m_IndicatorProgress = 0; + CBPersistMgr *pm = new CBPersistMgr(Game); + if (FAILED(ret = pm->InitSave(desc))) goto save_finish; + + if (!quickSave) { + delete m_SaveLoadImage; + m_SaveLoadImage = NULL; + if (m_SaveImageName) { + m_SaveLoadImage = new CBSurfaceSDL(this); + + if (!m_SaveLoadImage || FAILED(m_SaveLoadImage->Create(m_SaveImageName, true, 0, 0, 0))) { + delete m_SaveLoadImage; + m_SaveLoadImage = NULL; + } + } + } + + if (FAILED(ret = CSysClassRegistry::GetInstance()->SaveTable(Game, pm, quickSave))) goto save_finish; + if (FAILED(ret = CSysClassRegistry::GetInstance()->SaveInstances(Game, pm, quickSave))) goto save_finish; + if (FAILED(ret = pm->SaveFile(Filename))) goto save_finish; + + m_Registry->WriteInt("System", "MostRecentSaveSlot", slot); + +save_finish: + delete pm; + m_IndicatorDisplay = false; + + delete m_SaveLoadImage; + m_SaveLoadImage = NULL; + + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::LoadGame(int Slot) { + //Game->LOG(0, "Load start %d", CBUtils::GetUsedMemMB()); + + m_Loading = false; + m_ScheduledLoadSlot = -1; + + char Filename[MAX_PATH + 1]; + GetSaveSlotFilename(Slot, Filename); + + return LoadGame(Filename); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::LoadGame(char *Filename) { + LOG(0, "Loading game '%s'...", Filename); + GetDebugMgr()->OnGameShutdown(); + + HRESULT ret; + + delete m_SaveLoadImage; + m_SaveLoadImage = NULL; + if (m_LoadImageName) { + m_SaveLoadImage = new CBSurfaceSDL(this); + + if (!m_SaveLoadImage || FAILED(m_SaveLoadImage->Create(m_LoadImageName, true, 0, 0, 0))) { + delete m_SaveLoadImage; + m_SaveLoadImage = NULL; + } + } + + + m_LoadInProgress = true; + m_IndicatorDisplay = true; + m_IndicatorProgress = 0; + CBPersistMgr *pm = new CBPersistMgr(Game); + m_DEBUG_AbsolutePathWarning = false; + if (FAILED(ret = pm->InitLoad(Filename))) goto load_finish; + + //if(FAILED(ret = Cleanup())) goto load_finish; + if (FAILED(ret = CSysClassRegistry::GetInstance()->LoadTable(Game, pm))) goto load_finish; + if (FAILED(ret = CSysClassRegistry::GetInstance()->LoadInstances(Game, pm))) goto load_finish; + + // data initialization after load + InitAfterLoad(); + + Game->ApplyEvent("AfterLoad", true); + + DisplayContent(true, false); + //m_Renderer->Flip(); + + GetDebugMgr()->OnGameInit(); + +load_finish: + m_DEBUG_AbsolutePathWarning = true; + + m_IndicatorDisplay = false; + delete pm; + m_LoadInProgress = false; + + delete m_SaveLoadImage; + m_SaveLoadImage = NULL; + + //Game->LOG(0, "Load end %d", CBUtils::GetUsedMemMB()); + + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::InitAfterLoad() { + CSysClassRegistry::GetInstance()->EnumInstances(AfterLoadRegion, "CBRegion", NULL); + CSysClassRegistry::GetInstance()->EnumInstances(AfterLoadSubFrame, "CBSubFrame", NULL); + CSysClassRegistry::GetInstance()->EnumInstances(AfterLoadSound, "CBSound", NULL); + CSysClassRegistry::GetInstance()->EnumInstances(AfterLoadFont, "CBFontTT", NULL); + CSysClassRegistry::GetInstance()->EnumInstances(AfterLoadScript, "CScScript", NULL); + + m_ScEngine->RefreshScriptBreakpoints(); + if (m_Store) m_Store->AfterLoad(); + + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +void CBGame::AfterLoadRegion(void *Region, void *Data) { + ((CBRegion *)Region)->CreateRegion(); +} + + +////////////////////////////////////////////////////////////////////////// +void CBGame::AfterLoadSubFrame(void *Subframe, void *Data) { + ((CBSubFrame *)Subframe)->SetSurfaceSimple(); +} + + +////////////////////////////////////////////////////////////////////////// +void CBGame::AfterLoadSound(void *Sound, void *Data) { + ((CBSound *)Sound)->SetSoundSimple(); +} + +////////////////////////////////////////////////////////////////////////// +void CBGame::AfterLoadFont(void *Font, void *Data) { + ((CBFontTT *)Font)->AfterLoad(); +} + +////////////////////////////////////////////////////////////////////////// +void CBGame::AfterLoadScript(void *script, void *data) { + ((CScScript *)script)->AfterLoad(); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::DisplayWindows(bool InGame) { + HRESULT res; + + int i; + + // did we lose focus? focus topmost window + if (m_FocusedWindow == NULL || !m_FocusedWindow->m_Visible || m_FocusedWindow->m_Disable) { + m_FocusedWindow = NULL; + for (i = m_Windows.GetSize() - 1; i >= 0; i--) { + if (m_Windows[i]->m_Visible && !m_Windows[i]->m_Disable) { + m_FocusedWindow = m_Windows[i]; + break; + } + } + } + + // display all windows + for (i = 0; i < m_Windows.GetSize(); i++) { + if (m_Windows[i]->m_Visible && m_Windows[i]->m_InGame == InGame) { + + res = m_Windows[i]->Display(); + if (FAILED(res)) return res; + } + } + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::PlayMusic(int Channel, char *Filename, bool Looping, uint32 LoopStart) { + if (Channel >= NUM_MUSIC_CHANNELS) { + Game->LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", Channel, NUM_MUSIC_CHANNELS); + return E_FAIL; + } + + delete m_Music[Channel]; + m_Music[Channel] = NULL; + + m_Music[Channel] = new CBSound(Game); + if (m_Music[Channel] && SUCCEEDED(m_Music[Channel]->SetSound(Filename, SOUND_MUSIC, true))) { + if (m_MusicStartTime[Channel]) { + m_Music[Channel]->SetPositionTime(m_MusicStartTime[Channel]); + m_MusicStartTime[Channel] = 0; + } + if (LoopStart) m_Music[Channel]->SetLoopStart(LoopStart); + return m_Music[Channel]->Play(Looping); + } else { + delete m_Music[Channel]; + m_Music[Channel] = NULL; + return E_FAIL; + } +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::StopMusic(int Channel) { + if (Channel >= NUM_MUSIC_CHANNELS) { + Game->LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", Channel, NUM_MUSIC_CHANNELS); + return E_FAIL; + } + + if (m_Music[Channel]) { + m_Music[Channel]->Stop(); + delete m_Music[Channel]; + m_Music[Channel] = NULL; + return S_OK; + } else return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::PauseMusic(int Channel) { + if (Channel >= NUM_MUSIC_CHANNELS) { + Game->LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", Channel, NUM_MUSIC_CHANNELS); + return E_FAIL; + } + + if (m_Music[Channel]) return m_Music[Channel]->Pause(); + else return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::ResumeMusic(int Channel) { + if (Channel >= NUM_MUSIC_CHANNELS) { + Game->LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", Channel, NUM_MUSIC_CHANNELS); + return E_FAIL; + } + + if (m_Music[Channel]) return m_Music[Channel]->Resume(); + else return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::SetMusicStartTime(int Channel, uint32 Time) { + + if (Channel >= NUM_MUSIC_CHANNELS) { + Game->LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", Channel, NUM_MUSIC_CHANNELS); + return E_FAIL; + } + + m_MusicStartTime[Channel] = Time; + if (m_Music[Channel] && m_Music[Channel]->IsPlaying()) return m_Music[Channel]->SetPositionTime(Time); + else return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::LoadSettings(char *Filename) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(SETTINGS) + TOKEN_TABLE(GAME) + TOKEN_TABLE(STRING_TABLE) + TOKEN_TABLE(RESOLUTION) + TOKEN_TABLE(REQUIRE_3D_ACCELERATION) + TOKEN_TABLE(REQUIRE_SOUND) + TOKEN_TABLE(HWTL_MODE) + TOKEN_TABLE(ALLOW_WINDOWED_MODE) + TOKEN_TABLE(ALLOW_ACCESSIBILITY_TAB) + TOKEN_TABLE(ALLOW_ABOUT_TAB) + TOKEN_TABLE(ALLOW_ADVANCED) + TOKEN_TABLE(ALLOW_DESKTOP_RES) + TOKEN_TABLE(REGISTRY_PATH) + TOKEN_TABLE(RICH_SAVED_GAMES) + TOKEN_TABLE(SAVED_GAME_EXT) + TOKEN_TABLE(GUID) + TOKEN_TABLE_END + + + byte *OrigBuffer = Game->m_FileManager->ReadWholeFile(Filename); + if (OrigBuffer == NULL) { + Game->LOG(0, "CBGame::LoadSettings failed for file '%s'", Filename); + return E_FAIL; + } + + HRESULT ret = S_OK; + + byte *Buffer = OrigBuffer; + byte *params; + int cmd; + CBParser parser(Game); + + if (parser.GetCommand((char **)&Buffer, commands, (char **)¶ms) != TOKEN_SETTINGS) { + Game->LOG(0, "'SETTINGS' keyword expected in game settings file."); + return E_FAIL; + } + Buffer = params; + while ((cmd = parser.GetCommand((char **)&Buffer, commands, (char **)¶ms)) > 0) { + switch (cmd) { + case TOKEN_GAME: + SAFE_DELETE_ARRAY(m_SettingsGameFile); + m_SettingsGameFile = new char[strlen((char *)params) + 1]; + if (m_SettingsGameFile) strcpy(m_SettingsGameFile, (char *)params); + break; + + case TOKEN_STRING_TABLE: + if (FAILED(m_StringTable->LoadFile((char *)params))) cmd = PARSERR_GENERIC; + break; + + case TOKEN_RESOLUTION: + parser.ScanStr((char *)params, "%d,%d", &m_SettingsResWidth, &m_SettingsResHeight); + break; + + case TOKEN_REQUIRE_3D_ACCELERATION: + parser.ScanStr((char *)params, "%b", &m_SettingsRequireAcceleration); + break; + + case TOKEN_REQUIRE_SOUND: + parser.ScanStr((char *)params, "%b", &m_SettingsRequireSound); + break; + + case TOKEN_HWTL_MODE: + parser.ScanStr((char *)params, "%d", &m_SettingsTLMode); + break; + + case TOKEN_ALLOW_WINDOWED_MODE: + parser.ScanStr((char *)params, "%b", &m_SettingsAllowWindowed); + break; + + case TOKEN_ALLOW_DESKTOP_RES: + parser.ScanStr((char *)params, "%b", &m_SettingsAllowDesktopRes); + break; + + case TOKEN_ALLOW_ADVANCED: + parser.ScanStr((char *)params, "%b", &m_SettingsAllowAdvanced); + break; + + case TOKEN_ALLOW_ACCESSIBILITY_TAB: + parser.ScanStr((char *)params, "%b", &m_SettingsAllowAccessTab); + break; + + case TOKEN_ALLOW_ABOUT_TAB: + parser.ScanStr((char *)params, "%b", &m_SettingsAllowAboutTab); + break; + + case TOKEN_REGISTRY_PATH: + m_Registry->SetBasePath((char *)params); + break; + + case TOKEN_RICH_SAVED_GAMES: + parser.ScanStr((char *)params, "%b", &m_RichSavedGames); + break; + + case TOKEN_SAVED_GAME_EXT: + CBUtils::SetString(&m_SavedGameExt, (char *)params); + break; + + case TOKEN_GUID: + break; + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + Game->LOG(0, "Syntax error in game settings '%s'", Filename); + ret = E_FAIL; + } + if (cmd == PARSERR_GENERIC) { + Game->LOG(0, "Error loading game settings '%s'", Filename); + ret = E_FAIL; + } + + m_SettingsAllowWindowed = m_Registry->ReadBool("Debug", "AllowWindowed", m_SettingsAllowWindowed); + m_CompressedSavegames = m_Registry->ReadBool("Debug", "CompressedSavegames", m_CompressedSavegames); + //m_CompressedSavegames = false; + + delete [] OrigBuffer; + + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::Persist(CBPersistMgr *PersistMgr) { + if (!PersistMgr->m_Saving) Cleanup(); + + CBObject::Persist(PersistMgr); + + PersistMgr->Transfer(TMEMBER(m_ActiveObject)); + PersistMgr->Transfer(TMEMBER(m_CapturedObject)); + PersistMgr->Transfer(TMEMBER(m_CursorNoninteractive)); + PersistMgr->Transfer(TMEMBER(m_DoNotExpandStrings)); + PersistMgr->Transfer(TMEMBER(m_EditorMode)); + PersistMgr->Transfer(TMEMBER(m_Fader)); + PersistMgr->Transfer(TMEMBER(m_FreezeLevel)); + PersistMgr->Transfer(TMEMBER(m_FocusedWindow)); + PersistMgr->Transfer(TMEMBER(m_FontStorage)); + PersistMgr->Transfer(TMEMBER(m_Interactive)); + PersistMgr->Transfer(TMEMBER(m_KeyboardState)); + PersistMgr->Transfer(TMEMBER(m_LastTime)); + PersistMgr->Transfer(TMEMBER(m_MainObject)); + for (int i = 0; i < NUM_MUSIC_CHANNELS; i++) { + PersistMgr->Transfer(TMEMBER(m_Music[i])); + PersistMgr->Transfer(TMEMBER(m_MusicStartTime[i])); + } + + PersistMgr->Transfer(TMEMBER(m_OffsetX)); + PersistMgr->Transfer(TMEMBER(m_OffsetY)); + PersistMgr->Transfer(TMEMBER(m_OffsetPercentX)); + PersistMgr->Transfer(TMEMBER(m_OffsetPercentY)); + + PersistMgr->Transfer(TMEMBER(m_OrigInteractive)); + PersistMgr->Transfer(TMEMBER_INT(m_OrigState)); + PersistMgr->Transfer(TMEMBER(m_PersonalizedSave)); + PersistMgr->Transfer(TMEMBER(m_Quitting)); + + m_RegObjects.Persist(PersistMgr); + + PersistMgr->Transfer(TMEMBER(m_ScEngine)); + //PersistMgr->Transfer(TMEMBER(m_SoundMgr)); + PersistMgr->Transfer(TMEMBER_INT(m_State)); + //PersistMgr->Transfer(TMEMBER(m_SurfaceStorage)); + PersistMgr->Transfer(TMEMBER(m_Subtitles)); + PersistMgr->Transfer(TMEMBER(m_SubtitlesSpeed)); + PersistMgr->Transfer(TMEMBER(m_SystemFont)); + PersistMgr->Transfer(TMEMBER(m_VideoFont)); + PersistMgr->Transfer(TMEMBER(m_VideoSubtitles)); + + PersistMgr->Transfer(TMEMBER(m_Timer)); + PersistMgr->Transfer(TMEMBER(m_TimerDelta)); + PersistMgr->Transfer(TMEMBER(m_TimerLast)); + + PersistMgr->Transfer(TMEMBER(m_LiveTimer)); + PersistMgr->Transfer(TMEMBER(m_LiveTimerDelta)); + PersistMgr->Transfer(TMEMBER(m_LiveTimerLast)); + + PersistMgr->Transfer(TMEMBER(m_MusicCrossfadeRunning)); + PersistMgr->Transfer(TMEMBER(m_MusicCrossfadeStartTime)); + PersistMgr->Transfer(TMEMBER(m_MusicCrossfadeLength)); + PersistMgr->Transfer(TMEMBER(m_MusicCrossfadeChannel1)); + PersistMgr->Transfer(TMEMBER(m_MusicCrossfadeChannel2)); + PersistMgr->Transfer(TMEMBER(m_MusicCrossfadeSwap)); + + PersistMgr->Transfer(TMEMBER(m_LoadImageName)); + PersistMgr->Transfer(TMEMBER(m_SaveImageName)); + PersistMgr->Transfer(TMEMBER(m_SaveImageX)); + PersistMgr->Transfer(TMEMBER(m_SaveImageY)); + PersistMgr->Transfer(TMEMBER(m_LoadImageX)); + PersistMgr->Transfer(TMEMBER(m_LoadImageY)); + + PersistMgr->Transfer(TMEMBER_INT(m_TextEncoding)); + PersistMgr->Transfer(TMEMBER(m_TextRTL)); + + PersistMgr->Transfer(TMEMBER(m_SoundBufferSizeSec)); + PersistMgr->Transfer(TMEMBER(m_SuspendedRendering)); + + PersistMgr->Transfer(TMEMBER(m_MouseLockRect)); + + m_Windows.Persist(PersistMgr); + + PersistMgr->Transfer(TMEMBER(m_SuppressScriptErrors)); + PersistMgr->Transfer(TMEMBER(m_AutorunDisabled)); + + PersistMgr->Transfer(TMEMBER(m_AutoSaveOnExit)); + PersistMgr->Transfer(TMEMBER(m_AutoSaveSlot)); + PersistMgr->Transfer(TMEMBER(m_CursorHidden)); + + if (PersistMgr->CheckVersion(1, 0, 1)) + PersistMgr->Transfer(TMEMBER(m_Store)); + else + m_Store = NULL; + + if (!PersistMgr->m_Saving) m_Quitting = false; + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::FocusWindow(CUIWindow *Window) { + CUIWindow *Prev = m_FocusedWindow; + + int i; + for (i = 0; i < m_Windows.GetSize(); i++) { + if (m_Windows[i] == Window) { + if (i < m_Windows.GetSize() - 1) { + m_Windows.RemoveAt(i); + m_Windows.Add(Window); + + Game->m_FocusedWindow = Window; + } + + if (Window->m_Mode == WINDOW_NORMAL && Prev != Window && Game->ValidObject(Prev) && (Prev->m_Mode == WINDOW_EXCLUSIVE || Prev->m_Mode == WINDOW_SYSTEM_EXCLUSIVE)) + return FocusWindow(Prev); + else return S_OK; + } + } + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::Freeze(bool IncludingMusic) { + if (m_FreezeLevel == 0) { + m_ScEngine->PauseAll(); + m_SoundMgr->PauseAll(IncludingMusic); + m_OrigState = m_State; + m_OrigInteractive = m_Interactive; + m_Interactive = true; + } + m_State = GAME_FROZEN; + m_FreezeLevel++; + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::Unfreeze() { + if (m_FreezeLevel == 0) return S_OK; + + m_FreezeLevel--; + if (m_FreezeLevel == 0) { + m_State = m_OrigState; + m_Interactive = m_OrigInteractive; + m_ScEngine->ResumeAll(); + m_SoundMgr->ResumeAll(); + } + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::HandleKeypress(SDL_Event *event) { +#ifdef __WIN32__ + // handle Alt+F4 on windows + if (event->type == SDL_KEYDOWN && event->key.keysym.sym == SDLK_F4 && (event->key.keysym.mod == KMOD_LALT || event->key.keysym.mod == KMOD_RALT)) { + OnWindowClose(); + return true; + } +#endif + + if (event->type == SDL_KEYDOWN && event->key.keysym.sym == SDLK_RETURN && (event->key.keysym.mod == KMOD_LALT || event->key.keysym.mod == KMOD_RALT)) { + m_Renderer->SwitchFullscreen(); + return true; + } + + + + m_KeyboardState->ReadKey(event); + + if (m_FocusedWindow) { + if (!Game->m_FocusedWindow->HandleKeypress(event)) { + if (event->type != SDL_TEXTINPUT) { + if (Game->m_FocusedWindow->CanHandleEvent("Keypress")) + Game->m_FocusedWindow->ApplyEvent("Keypress"); + else + ApplyEvent("Keypress"); + } + } + return true; + } else if (event->type != SDL_TEXTINPUT) { + ApplyEvent("Keypress"); + return true; + } else return true; +} + + + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::HandleMouseWheel(int Delta) { + bool Handled = false; + if (m_FocusedWindow) { + Handled = Game->m_FocusedWindow->HandleMouseWheel(Delta); + + if (!Handled) { + if (Delta < 0 && Game->m_FocusedWindow->CanHandleEvent("MouseWheelDown")) { + Game->m_FocusedWindow->ApplyEvent("MouseWheelDown"); + Handled = true; + } else if (Game->m_FocusedWindow->CanHandleEvent("MouseWheelUp")) { + Game->m_FocusedWindow->ApplyEvent("MouseWheelUp"); + Handled = true; + } + + } + } + + if (!Handled) { + if (Delta < 0) { + ApplyEvent("MouseWheelDown"); + } else { + ApplyEvent("MouseWheelUp"); + } + } + + return true; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::GetVersion(byte *VerMajor, byte *VerMinor, byte *ExtMajor, byte *ExtMinor) { + if (VerMajor) *VerMajor = DCGF_VER_MAJOR; + if (VerMinor) *VerMinor = DCGF_VER_MINOR; + + if (ExtMajor) *ExtMajor = 0; + if (ExtMinor) *ExtMinor = 0; + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void CBGame::SetWindowTitle() { + if (m_Renderer) { + char Title[512]; + strcpy(Title, m_Caption[0]); + if (Title[0] != '\0') strcat(Title, " - "); + strcat(Title, "WME Lite"); + + + Utf8String title; + if (m_TextEncoding == TEXT_UTF8) { + title = Utf8String(Title); + } else { + WideString wstr = StringUtil::AnsiToWide(Title); + title = StringUtil::WideToUtf8(wstr); + } + + CBRenderSDL *renderer = static_cast(m_Renderer); + SDL_SetWindowTitle(renderer->GetSdlWindow(), title.c_str()); + } +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::GetSaveSlotFilename(int Slot, char *Buffer) { + AnsiString dataDir = GetDataDir(); + sprintf(Buffer, "%s/save%03d.%s", dataDir.c_str(), Slot, m_SavedGameExt); + + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +AnsiString CBGame::GetDataDir() { + AnsiString userDir = PathUtil::GetUserDirectory(); +#ifdef __IPHONEOS__ + return userDir; +#else + AnsiString baseDir = m_Registry->GetBasePath(); + return PathUtil::Combine(userDir, baseDir); +#endif +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::GetSaveSlotDescription(int Slot, char *Buffer) { + Buffer[0] = '\0'; + + char Filename[MAX_PATH + 1]; + GetSaveSlotFilename(Slot, Filename); + CBPersistMgr *pm = new CBPersistMgr(Game); + if (!pm) return E_FAIL; + + m_DEBUG_AbsolutePathWarning = false; + if (FAILED(pm->InitLoad(Filename))) { + m_DEBUG_AbsolutePathWarning = true; + delete pm; + return E_FAIL; + } + + m_DEBUG_AbsolutePathWarning = true; + strcpy(Buffer, pm->m_SavedDescription); + delete pm; + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBGame::IsSaveSlotUsed(int Slot) { + char Filename[MAX_PATH + 1]; + GetSaveSlotFilename(Slot, Filename); + + CBFile *File = m_FileManager->OpenFile(Filename, false); + if (!File) return false; + + m_FileManager->CloseFile(File); + return true; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::EmptySaveSlot(int Slot) { + char Filename[MAX_PATH + 1]; + GetSaveSlotFilename(Slot, Filename); + + CBPlatform::DeleteFile(Filename); + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::SetActiveObject(CBObject *Obj) { + // not-active when game is frozen + if (Obj && !Game->m_Interactive && !Obj->m_NonIntMouseEvents) { + Obj = NULL; + } + + if (Obj == m_ActiveObject) return S_OK; + + if (m_ActiveObject) m_ActiveObject->ApplyEvent("MouseLeave"); + //if(ValidObject(m_ActiveObject)) m_ActiveObject->ApplyEvent("MouseLeave"); + m_ActiveObject = Obj; + if (m_ActiveObject) { + m_ActiveObject->ApplyEvent("MouseEntry"); + } + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::PushViewport(CBViewport *Viewport) { + m_ViewportSP++; + if (m_ViewportSP >= m_ViewportStack.GetSize()) m_ViewportStack.Add(Viewport); + else m_ViewportStack[m_ViewportSP] = Viewport; + + m_Renderer->SetViewport(Viewport->GetRect()); + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::PopViewport() { + m_ViewportSP--; + if (m_ViewportSP < -1) Game->LOG(0, "Fatal: Viewport stack underflow!"); + + if (m_ViewportSP >= 0 && m_ViewportSP < m_ViewportStack.GetSize()) m_Renderer->SetViewport(m_ViewportStack[m_ViewportSP]->GetRect()); + else m_Renderer->SetViewport(m_Renderer->m_DrawOffsetX, + m_Renderer->m_DrawOffsetY, + m_Renderer->m_Width + m_Renderer->m_DrawOffsetX, + m_Renderer->m_Height + m_Renderer->m_DrawOffsetY); + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::GetCurrentViewportRect(RECT *Rect, bool *Custom) { + if (Rect == NULL) return E_FAIL; + else { + if (m_ViewportSP >= 0) { + CBPlatform::CopyRect(Rect, m_ViewportStack[m_ViewportSP]->GetRect()); + if (Custom) *Custom = true; + } else { + CBPlatform::SetRect(Rect, m_Renderer->m_DrawOffsetX, + m_Renderer->m_DrawOffsetY, + m_Renderer->m_Width + m_Renderer->m_DrawOffsetX, + m_Renderer->m_Height + m_Renderer->m_DrawOffsetY); + if (Custom) *Custom = false; + } + + return S_OK; + } +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::GetCurrentViewportOffset(int *OffsetX, int *OffsetY) { + if (m_ViewportSP >= 0) { + if (OffsetX) *OffsetX = m_ViewportStack[m_ViewportSP]->m_OffsetX; + if (OffsetY) *OffsetY = m_ViewportStack[m_ViewportSP]->m_OffsetY; + } else { + if (OffsetX) *OffsetX = 0; + if (OffsetY) *OffsetY = 0; + } + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::WindowLoadHook(CUIWindow *Win, char **Buf, char **Params) { + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::WindowScriptMethodHook(CUIWindow *Win, CScScript *Script, CScStack *Stack, char *Name) { + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +void CBGame::SetInteractive(bool State) { + m_Interactive = State; + if (m_TransMgr) m_TransMgr->m_OrigInteractive = State; +} + + +////////////////////////////////////////////////////////////////////////// +void CBGame::ResetMousePos() { + POINT p; + p.x = m_MousePos.x + m_Renderer->m_DrawOffsetX; + p.y = m_MousePos.y + m_Renderer->m_DrawOffsetY; + + CBPlatform::SetCursorPos(p.x, p.y); +} + + +////////////////////////////////////////////////////////////////////////// +void CBGame::SetResourceModule(HMODULE ResModule) { + m_ResourceModule = ResModule; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::DisplayContent(bool Update, bool DisplayAll) { + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::DisplayContentSimple() { + // fill black + m_Renderer->Fill(0, 0, 0); + if (m_IndicatorDisplay) DisplayIndicator(); + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::DisplayIndicator() { + if (m_SaveLoadImage) { + RECT rc; + CBPlatform::SetRect(&rc, 0, 0, m_SaveLoadImage->GetWidth(), m_SaveLoadImage->GetHeight()); + if (m_LoadInProgress) m_SaveLoadImage->DisplayTrans(m_LoadImageX, m_LoadImageY, rc); + else m_SaveLoadImage->DisplayTrans(m_SaveImageX, m_SaveImageY, rc); + } + + if (!m_IndicatorDisplay && m_IndicatorWidth <= 0 || m_IndicatorHeight <= 0) return S_OK; + m_Renderer->SetupLines(); + for (int i = 0; i < m_IndicatorHeight; i++) + m_Renderer->DrawLine(m_IndicatorX, m_IndicatorY + i, m_IndicatorX + (int)(m_IndicatorWidth * (float)((float)m_IndicatorProgress / 100.0f)), m_IndicatorY + i, m_IndicatorColor); + + m_Renderer->Setup2D(); + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::UpdateMusicCrossfade() { + byte GlobMusicVol = m_SoundMgr->GetVolumePercent(SOUND_MUSIC); + + if (!m_MusicCrossfadeRunning) return S_OK; + if (m_State == GAME_FROZEN) return S_OK; + + if (m_MusicCrossfadeChannel1 < 0 || m_MusicCrossfadeChannel1 >= NUM_MUSIC_CHANNELS || !m_Music[m_MusicCrossfadeChannel1]) { + m_MusicCrossfadeRunning = false; + return S_OK; + } + if (m_MusicCrossfadeChannel2 < 0 || m_MusicCrossfadeChannel2 >= NUM_MUSIC_CHANNELS || !m_Music[m_MusicCrossfadeChannel2]) { + m_MusicCrossfadeRunning = false; + return S_OK; + } + + if (!m_Music[m_MusicCrossfadeChannel1]->IsPlaying()) m_Music[m_MusicCrossfadeChannel1]->Play(); + if (!m_Music[m_MusicCrossfadeChannel2]->IsPlaying()) m_Music[m_MusicCrossfadeChannel2]->Play(); + + uint32 CurrentTime = Game->m_LiveTimer - m_MusicCrossfadeStartTime; + + if (CurrentTime >= m_MusicCrossfadeLength) { + m_MusicCrossfadeRunning = false; + //m_Music[m_MusicCrossfadeChannel2]->SetVolume(GlobMusicVol); + m_Music[m_MusicCrossfadeChannel2]->SetVolume(100); + + m_Music[m_MusicCrossfadeChannel1]->Stop(); + //m_Music[m_MusicCrossfadeChannel1]->SetVolume(GlobMusicVol); + m_Music[m_MusicCrossfadeChannel1]->SetVolume(100); + + + if (m_MusicCrossfadeSwap) { + // swap channels + CBSound *Dummy = m_Music[m_MusicCrossfadeChannel1]; + int DummyInt = m_MusicStartTime[m_MusicCrossfadeChannel1]; + + m_Music[m_MusicCrossfadeChannel1] = m_Music[m_MusicCrossfadeChannel2]; + m_MusicStartTime[m_MusicCrossfadeChannel1] = m_MusicStartTime[m_MusicCrossfadeChannel2]; + + m_Music[m_MusicCrossfadeChannel2] = Dummy; + m_MusicStartTime[m_MusicCrossfadeChannel2] = DummyInt; + } + } else { + //m_Music[m_MusicCrossfadeChannel1]->SetVolume(GlobMusicVol - (float)CurrentTime / (float)m_MusicCrossfadeLength * GlobMusicVol); + //m_Music[m_MusicCrossfadeChannel2]->SetVolume((float)CurrentTime / (float)m_MusicCrossfadeLength * GlobMusicVol); + m_Music[m_MusicCrossfadeChannel1]->SetVolume(100 - (float)CurrentTime / (float)m_MusicCrossfadeLength * 100); + m_Music[m_MusicCrossfadeChannel2]->SetVolume((float)CurrentTime / (float)m_MusicCrossfadeLength * 100); + + //Game->QuickMessageForm("%d %d", m_Music[m_MusicCrossfadeChannel1]->GetVolume(), m_Music[m_MusicCrossfadeChannel2]->GetVolume()); + } + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::ResetContent() { + m_ScEngine->ClearGlobals(); + //m_Timer = 0; + //m_LiveTimer = 0; + + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +void CBGame::DEBUG_DumpClassRegistry() { + FILE *f = fopen("./zz_class_reg_dump.log", "wt"); + + CSysClassRegistry::GetInstance()->DumpClasses(f); + + fclose(f); + Game->QuickMessage("Classes dump completed."); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::InvalidateDeviceObjects() { + for (int i = 0; i < m_RegObjects.GetSize(); i++) { + m_RegObjects[i]->InvalidateDeviceObjects(); + } + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::RestoreDeviceObjects() { + for (int i = 0; i < m_RegObjects.GetSize(); i++) { + m_RegObjects[i]->RestoreDeviceObjects(); + } + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::SetWaitCursor(char *Filename) { + delete m_CursorNoninteractive; + m_CursorNoninteractive = NULL; + + m_CursorNoninteractive = new CBSprite(Game); + if (!m_CursorNoninteractive || FAILED(m_CursorNoninteractive->LoadFile(Filename))) { + delete m_CursorNoninteractive; + m_CursorNoninteractive = NULL; + return E_FAIL; + } else return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::DrawCursor(CBSprite *Cursor) { + if (!Cursor) return E_FAIL; + if (Cursor != m_LastCursor) { + Cursor->Reset(); + m_LastCursor = Cursor; + } + return Cursor->Draw(m_MousePos.x, m_MousePos.y); +} + + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::OnActivate(bool Activate, bool RefreshMouse) { + if (m_ShuttingDown || !m_Renderer) return S_OK; + + m_Renderer->m_Active = Activate; + + if (RefreshMouse) { + POINT p; + GetMousePos(&p); + SetActiveObject(m_Renderer->GetObjectAt(p.x, p.y)); + } + + if (Activate) m_SoundMgr->ResumeAll(); + else m_SoundMgr->PauseAll(); + + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::OnMouseLeftDown() { + if (m_ActiveObject) m_ActiveObject->HandleMouse(MOUSE_CLICK, MOUSE_BUTTON_LEFT); + + bool Handled = m_State == GAME_RUNNING && SUCCEEDED(ApplyEvent("LeftClick")); + if (!Handled) { + if (m_ActiveObject != NULL) { + m_ActiveObject->ApplyEvent("LeftClick"); + } + } + + if (m_ActiveObject != NULL) m_CapturedObject = m_ActiveObject; + m_MouseLeftDown = true; + CBPlatform::SetCapture(m_Renderer->m_Window); + + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::OnMouseLeftUp() { + if (m_ActiveObject) m_ActiveObject->HandleMouse(MOUSE_RELEASE, MOUSE_BUTTON_LEFT); + + CBPlatform::ReleaseCapture(); + m_CapturedObject = NULL; + m_MouseLeftDown = false; + + bool Handled = m_State == GAME_RUNNING && SUCCEEDED(ApplyEvent("LeftRelease")); + if (!Handled) { + if (m_ActiveObject != NULL) { + m_ActiveObject->ApplyEvent("LeftRelease"); + } + } + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::OnMouseLeftDblClick() { + if (m_State == GAME_RUNNING && !m_Interactive) return S_OK; + + if (m_ActiveObject) m_ActiveObject->HandleMouse(MOUSE_DBLCLICK, MOUSE_BUTTON_LEFT); + + bool Handled = m_State == GAME_RUNNING && SUCCEEDED(ApplyEvent("LeftDoubleClick")); + if (!Handled) { + if (m_ActiveObject != NULL) { + m_ActiveObject->ApplyEvent("LeftDoubleClick"); + } + } + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::OnMouseRightDblClick() { + if (m_State == GAME_RUNNING && !m_Interactive) return S_OK; + + if (m_ActiveObject) m_ActiveObject->HandleMouse(MOUSE_DBLCLICK, MOUSE_BUTTON_RIGHT); + + bool Handled = m_State == GAME_RUNNING && SUCCEEDED(ApplyEvent("RightDoubleClick")); + if (!Handled) { + if (m_ActiveObject != NULL) { + m_ActiveObject->ApplyEvent("RightDoubleClick"); + } + } + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::OnMouseRightDown() { + if (m_ActiveObject) m_ActiveObject->HandleMouse(MOUSE_CLICK, MOUSE_BUTTON_RIGHT); + + bool Handled = m_State == GAME_RUNNING && SUCCEEDED(ApplyEvent("RightClick")); + if (!Handled) { + if (m_ActiveObject != NULL) { + m_ActiveObject->ApplyEvent("RightClick"); + } + } + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::OnMouseRightUp() { + if (m_ActiveObject) m_ActiveObject->HandleMouse(MOUSE_RELEASE, MOUSE_BUTTON_RIGHT); + + bool Handled = m_State == GAME_RUNNING && SUCCEEDED(ApplyEvent("RightRelease")); + if (!Handled) { + if (m_ActiveObject != NULL) { + m_ActiveObject->ApplyEvent("RightRelease"); + } + } + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::OnMouseMiddleDown() { + if (m_State == GAME_RUNNING && !m_Interactive) return S_OK; + + if (m_ActiveObject) m_ActiveObject->HandleMouse(MOUSE_CLICK, MOUSE_BUTTON_MIDDLE); + + bool Handled = m_State == GAME_RUNNING && SUCCEEDED(ApplyEvent("MiddleClick")); + if (!Handled) { + if (m_ActiveObject != NULL) { + m_ActiveObject->ApplyEvent("MiddleClick"); + } + } + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::OnMouseMiddleUp() { + if (m_ActiveObject) m_ActiveObject->HandleMouse(MOUSE_RELEASE, MOUSE_BUTTON_MIDDLE); + + bool Handled = m_State == GAME_RUNNING && SUCCEEDED(ApplyEvent("MiddleRelease")); + if (!Handled) { + if (m_ActiveObject != NULL) { + m_ActiveObject->ApplyEvent("MiddleRelease"); + } + } + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::OnPaint() { + if (m_Renderer && m_Renderer->m_Windowed && m_Renderer->m_Ready) { + m_Renderer->InitLoop(); + DisplayContent(false, true); + DisplayDebugInfo(); + m_Renderer->WindowedBlt(); + } + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::OnWindowClose() { + if (CanHandleEvent("QuitGame")) { + if (m_State != GAME_FROZEN) Game->ApplyEvent("QuitGame"); + return S_OK; + } else return E_FAIL; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::DisplayDebugInfo() { + char str[100]; + + if (m_DEBUG_ShowFPS) { + sprintf(str, "FPS: %d", Game->m_Fps); + m_SystemFont->DrawText((byte *)str, 0, 0, 100, TAL_LEFT); + } + + if (Game->m_DEBUG_DebugMode) { + if (!Game->m_Renderer->m_Windowed) + sprintf(str, "Mode: %dx%dx%d", m_Renderer->m_Width, m_Renderer->m_Height, m_Renderer->m_BPP); + else + sprintf(str, "Mode: %dx%d windowed", m_Renderer->m_Width, m_Renderer->m_Height); + + strcat(str, " ("); + strcat(str, m_Renderer->GetName()); + strcat(str, ")"); + m_SystemFont->DrawText((byte *)str, 0, 0, m_Renderer->m_Width, TAL_RIGHT); + + m_Renderer->DisplayDebugInfo(); + + int ScrTotal, ScrRunning, ScrWaiting, ScrPersistent; + ScrTotal = m_ScEngine->GetNumScripts(&ScrRunning, &ScrWaiting, &ScrPersistent); + sprintf(str, "Running scripts: %d (r:%d w:%d p:%d)", ScrTotal, ScrRunning, ScrWaiting, ScrPersistent); + m_SystemFont->DrawText((byte *)str, 0, 70, m_Renderer->m_Width, TAL_RIGHT); + + + sprintf(str, "Timer: %d", m_Timer); + Game->m_SystemFont->DrawText((byte *)str, 0, 130, m_Renderer->m_Width, TAL_RIGHT); + + if (m_ActiveObject != NULL) m_SystemFont->DrawText((byte *)m_ActiveObject->m_Name, 0, 150, m_Renderer->m_Width, TAL_RIGHT); + + sprintf(str, "GfxMem: %dMB", m_UsedMem / (1024 * 1024)); + m_SystemFont->DrawText((byte *)str, 0, 170, m_Renderer->m_Width, TAL_RIGHT); + + } + + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +CBDebugger *CBGame::GetDebugMgr() { + if (!m_DebugMgr) m_DebugMgr = new CBDebugger(this); + return m_DebugMgr; +} + + +////////////////////////////////////////////////////////////////////////// +void CBGame::GetMousePos(POINT *Pos) { + CBPlatform::GetCursorPos(Pos); + + Pos->x -= m_Renderer->m_DrawOffsetX; + Pos->y -= m_Renderer->m_DrawOffsetY; + + /* + // Windows can squish maximized window if it's larger than desktop + // so we need to modify mouse position appropriately (tnx mRax) + if(m_Renderer->m_Windowed && ::IsZoomed(m_Renderer->m_Window)) + { + RECT rc; + ::GetClientRect(m_Renderer->m_Window, &rc); + Pos->x *= Game->m_Renderer->m_RealWidth; + Pos->x /= (rc.right - rc.left); + Pos->y *= Game->m_Renderer->m_RealHeight; + Pos->y /= (rc.bottom - rc.top); + } + */ + + if (m_MouseLockRect.left != 0 && m_MouseLockRect.right != 0 && m_MouseLockRect.top != 0 && m_MouseLockRect.bottom != 0) { + if (!CBPlatform::PtInRect(&m_MouseLockRect, *Pos)) { + Pos->x = std::max(m_MouseLockRect.left, Pos->x); + Pos->y = std::max(m_MouseLockRect.top, Pos->y); + + Pos->x = std::min(m_MouseLockRect.right, Pos->x); + Pos->y = std::min(m_MouseLockRect.bottom, Pos->y); + + POINT NewPos = *Pos; + + NewPos.x += m_Renderer->m_DrawOffsetX; + NewPos.y += m_Renderer->m_DrawOffsetY; + + CBPlatform::SetCursorPos(NewPos.x, NewPos.y); + } + } +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::MiniUpdate() { + if (!m_MiniUpdateEnabled) return S_OK; + + if (CBPlatform::GetTime() - m_LastMiniUpdate > 200) { + if (m_SoundMgr) m_SoundMgr->InitLoop(); + m_LastMiniUpdate = CBPlatform::GetTime(); + } + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBGame::OnScriptShutdown(CScScript *Script) { + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBGame::IsLeftDoubleClick() { + return IsDoubleClick(0); +} + +////////////////////////////////////////////////////////////////////////// +bool CBGame::IsRightDoubleClick() { + return IsDoubleClick(1); +} + +////////////////////////////////////////////////////////////////////////// +bool CBGame::IsDoubleClick(int buttonIndex) { + uint32 maxDoubleCLickTime = 500; + int maxMoveX = 4; + int maxMoveY = 4; + +#if __WIN32__ + maxDoubleCLickTime = GetDoubleClickTime(); + maxMoveX = GetSystemMetrics(SM_CXDOUBLECLK); + maxMoveY = GetSystemMetrics(SM_CYDOUBLECLK); +#elif __IPHONEOS__ + maxMoveX = 16; + maxMoveY = 16; +#endif + + POINT pos; + CBPlatform::GetCursorPos(&pos); + + int moveX = abs(pos.x - m_LastClick[buttonIndex].PosX); + int moveY = abs(pos.y - m_LastClick[buttonIndex].PosY); + + + if (m_LastClick[buttonIndex].Time == 0 || CBPlatform::GetTime() - m_LastClick[buttonIndex].Time > maxDoubleCLickTime || moveX > maxMoveX || moveY > maxMoveY) { + m_LastClick[buttonIndex].Time = CBPlatform::GetTime(); + m_LastClick[buttonIndex].PosX = pos.x; + m_LastClick[buttonIndex].PosY = pos.y; + return false; + } else { + m_LastClick[buttonIndex].Time = 0; + return true; + } +} + +////////////////////////////////////////////////////////////////////////// +void CBGame::AutoSaveOnExit() { + m_SoundMgr->SaveSettings(); + m_Registry->SaveValues(); + + if (!m_AutoSaveOnExit) return; + if (m_State == GAME_FROZEN) return; + + SaveGame(m_AutoSaveSlot, "autosave", true); +} + +////////////////////////////////////////////////////////////////////////// +void CBGame::AddMem(int bytes) { + m_UsedMem += bytes; +} + +////////////////////////////////////////////////////////////////////////// +AnsiString CBGame::GetDeviceType() const { +#ifdef __IPHONEOS__ + char devType[128]; + IOS_GetDeviceType(devType); + return AnsiString(devType); +#else + return "computer"; +#endif +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BGame.h b/engines/wintermute/BGame.h index a61ba1270d..b3df2b3046 100644 --- a/engines/wintermute/BGame.h +++ b/engines/wintermute/BGame.h @@ -29,10 +29,10 @@ #ifndef WINTERMUTE_BGAME_H #define WINTERMUTE_BGAME_H -#include "BDebugger.h" +#include "engines/wintermute/BDebugger.h" //#include "BSaveThumbHelper.h" //#include "BFader.h" -//#include "BRenderer.h" +#include "engines/wintermute/BRenderer.h" //#include "BSurfaceStorage.h" #include "engines/wintermute/BObject.h" #include "engines/wintermute/persistent.h" @@ -53,7 +53,9 @@ class CBStringTable; class CBQuickMsg; class CUIWindow; class CBViewport; +class CBRenderer; class CBRegistry; +class CBSurfaceStorage; class CSXStore; class CSXMath; class CBKeyboardState; @@ -63,7 +65,7 @@ class CBKeyboardState; class CBGame: public CBObject { public: DECLARE_PERSISTENT(CBGame, CBObject) -#if 0 + virtual HRESULT OnScriptShutdown(CScScript *Script); virtual HRESULT OnActivate(bool Activate, bool RefreshMouse); @@ -80,7 +82,7 @@ public: bool IsLeftDoubleClick(); bool IsRightDoubleClick(); -#endif + bool m_AutorunDisabled; uint32 m_LastMiniUpdate; @@ -175,7 +177,7 @@ public: #endif //TODO: STUB CBDebugger *GetDebugMgr(); void LOG(HRESULT res, LPCSTR fmt, ...) {} -#if 0 + CBRenderer *m_Renderer; CBSoundMgr *m_SoundMgr; CScEngine *m_ScEngine; @@ -184,6 +186,7 @@ public: CBSurfaceStorage *m_SurfaceStorage; CBFontStorage *m_FontStorage; CBGame(); +#if 0 virtual ~CBGame(); void DEBUG_DebugDisable(); void DEBUG_DebugEnable(const char *Filename = NULL); @@ -216,19 +219,17 @@ public: char *m_SettingsGameFile; CBFader *m_Fader; bool m_SuppressScriptErrors; -#if 0 + virtual HRESULT InvalidateDeviceObjects(); virtual HRESULT RestoreDeviceObjects(); -#endif + virtual void PublishNatives(); virtual HRESULT ExternalCall(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name); -#if 0 // scripting interface virtual CScValue *ScGetProperty(char *Name); virtual HRESULT ScSetProperty(char *Name, CScValue *Value); virtual HRESULT ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name); virtual char *ScToString(); - // compatibility bits bool m_CompatKillMethodThreads; @@ -248,6 +249,7 @@ public: int m_ScheduledLoadSlot; bool m_Loading; bool m_PersonalizedSave; +#if 0 HRESULT EmptySaveSlot(int Slot); bool IsSaveSlotUsed(int Slot); HRESULT GetSaveSlotDescription(int Slot, char *Buffer); diff --git a/engines/wintermute/BImage.cpp b/engines/wintermute/BImage.cpp new file mode 100644 index 0000000000..6f0d0235aa --- /dev/null +++ b/engines/wintermute/BImage.cpp @@ -0,0 +1,117 @@ +/* +This file is part of WME Lite. +http://dead-code.org/redir.php?target=wmelite + +Copyright (c) 2011 Jan Nedoma + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "dcgf.h" +#include "BImage.h" +//#include "FreeImage.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +CBImage::CBImage(CBGame *inGame, FIBITMAP *bitmap): CBBase(inGame) { +#if 0 + m_Bitmap = bitmap; +#endif + m_Bitmap = NULL; +} + + +////////////////////////////////////////////////////////////////////// +CBImage::~CBImage() { +#if 0 + if (m_Bitmap) FreeImage_Unload(m_Bitmap); +#endif +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBImage::SaveBMPFile(char *Filename) { +#if 0 + if (!m_Bitmap) return E_FAIL; + + if (FreeImage_Save(FIF_BMP, m_Bitmap, Filename)) return S_OK; + else return E_FAIL; +#endif + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBImage::Resize(int NewWidth, int NewHeight) { +#if 0 + if (!m_Bitmap) return E_FAIL; + + if (NewWidth == 0) NewWidth = FreeImage_GetWidth(m_Bitmap); + if (NewHeight == 0) NewHeight = FreeImage_GetHeight(m_Bitmap); + + + FIBITMAP *newImg = FreeImage_Rescale(m_Bitmap, NewWidth, NewHeight, FILTER_BILINEAR); + if (newImg) { + FreeImage_Unload(m_Bitmap); + m_Bitmap = newImg; + return S_OK; + } else return E_FAIL; +#endif + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +byte *CBImage::CreateBMPBuffer(uint32 *BufferSize) { + if (!m_Bitmap) return NULL; +#if 0 + FIMEMORY *fiMem = FreeImage_OpenMemory(); + FreeImage_SaveToMemory(FIF_PNG, m_Bitmap, fiMem); + uint32 size; + byte *data; + FreeImage_AcquireMemory(fiMem, &data, &size); + + + byte *Buffer = new byte[size]; + memcpy(Buffer, data, size); + + FreeImage_CloseMemory(fiMem); + + if (BufferSize) *BufferSize = size; + + return Buffer; +#endif +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBImage::CopyFrom(CBImage *OrigImage, int NewWidth, int NewHeight) { +#if 0 + if (m_Bitmap) FreeImage_Unload(m_Bitmap); + + if (NewWidth == 0) NewWidth = FreeImage_GetWidth(OrigImage->GetBitmap()); + if (NewHeight == 0) NewHeight = FreeImage_GetHeight(OrigImage->GetBitmap()); + + m_Bitmap = FreeImage_Rescale(OrigImage->GetBitmap(), NewWidth, NewHeight, FILTER_BILINEAR); +#endif + return S_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BImage.h b/engines/wintermute/BImage.h new file mode 100644 index 0000000000..a738fb418b --- /dev/null +++ b/engines/wintermute/BImage.h @@ -0,0 +1,62 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BIMAGE_H +#define WINTERMUTE_BIMAGE_H + + +//#include "FreeImage.h" +#include "BBase.h" +#include "common/endian.h" + +struct FIBITMAP; + +namespace WinterMute { + +class CBImage: CBBase { + +public: + CBImage(CBGame *inGame, FIBITMAP *bitmap = NULL); + ~CBImage(); + + + byte *CreateBMPBuffer(uint32 *BufferSize = NULL); + HRESULT Resize(int NewWidth, int NewHeight); + HRESULT SaveBMPFile(char *Filename); + HRESULT CopyFrom(CBImage *OrigImage, int NewWidth = 0, int NewHeight = 0); + + FIBITMAP *GetBitmap() const { + return m_Bitmap; + } +private: + FIBITMAP *m_Bitmap; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BKeyboardState.cpp b/engines/wintermute/BKeyboardState.cpp new file mode 100644 index 0000000000..7e89d9827c --- /dev/null +++ b/engines/wintermute/BKeyboardState.cpp @@ -0,0 +1,243 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BKeyboardState.h" +#include "ScValue.h" +#include "ScStack.h" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CBKeyboardState, false) + +////////////////////////////////////////////////////////////////////////// +CBKeyboardState::CBKeyboardState(CBGame *inGame): CBScriptable(inGame) { + m_CurrentPrintable = false; + m_CurrentCharCode = 0; + m_CurrentKeyData = 0; + + m_CurrentShift = false; + m_CurrentAlt = false; + m_CurrentControl = false; +} + + +////////////////////////////////////////////////////////////////////////// +CBKeyboardState::~CBKeyboardState() { + +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +HRESULT CBKeyboardState::ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name) { + ////////////////////////////////////////////////////////////////////////// + // IsKeyDown + ////////////////////////////////////////////////////////////////////////// + if (strcmp(Name, "IsKeyDown") == 0) { + Stack->CorrectParams(1); + CScValue *val = Stack->Pop(); + int vKey; + + if (val->m_Type == VAL_STRING && strlen(val->GetString()) > 0) { + char *str = val->GetString(); + if (str[0] >= 'A' && str[0] <= 'Z') str[0] += ('a' - 'A'); + vKey = (int)str[0]; + } else vKey = val->GetInt(); + + Uint8 *state = SDL_GetKeyboardState(NULL); + SDL_Scancode scanCode = SDL_GetScancodeFromKey(VKeyToKeyCode(vKey)); + bool isDown = state[scanCode] > 0; + + Stack->PushBool(isDown); + return S_OK; + } + + else return CBScriptable::ScCallMethod(Script, Stack, ThisStack, Name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CBKeyboardState::ScGetProperty(char *Name) { + m_ScValue->SetNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type + ////////////////////////////////////////////////////////////////////////// + if (strcmp(Name, "Type") == 0) { + m_ScValue->SetString("keyboard"); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Key + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Key") == 0) { + if (m_CurrentPrintable) { + char key[2]; + key[0] = (char)m_CurrentCharCode; + key[1] = '\0'; + m_ScValue->SetString(key); + } else m_ScValue->SetString(""); + + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Printable + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Printable") == 0) { + m_ScValue->SetBool(m_CurrentPrintable); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // KeyCode + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "KeyCode") == 0) { + m_ScValue->SetInt(m_CurrentCharCode); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // IsShift + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "IsShift") == 0) { + m_ScValue->SetBool(m_CurrentShift); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // IsAlt + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "IsAlt") == 0) { + m_ScValue->SetBool(m_CurrentAlt); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // IsControl + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "IsControl") == 0) { + m_ScValue->SetBool(m_CurrentControl); + return m_ScValue; + } + + else return CBScriptable::ScGetProperty(Name); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBKeyboardState::ScSetProperty(char *Name, CScValue *Value) { + /* + ////////////////////////////////////////////////////////////////////////// + // Name + ////////////////////////////////////////////////////////////////////////// + if(strcmp(Name, "Name")==0){ + SetName(Value->GetString()); + if(m_Renderer) SetWindowText(m_Renderer->m_Window, m_Name); + return S_OK; + } + + else*/ return CBScriptable::ScSetProperty(Name, Value); +} + + +////////////////////////////////////////////////////////////////////////// +char *CBKeyboardState::ScToString() { + return "[keyboard state]"; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBKeyboardState::ReadKey(SDL_Event *event) { + m_CurrentPrintable = (event->type == SDL_TEXTINPUT); + m_CurrentCharCode = KeyCodeToVKey(event); + //m_CurrentKeyData = KeyData; + + m_CurrentControl = IsControlDown(); + m_CurrentAlt = IsAltDown(); + m_CurrentShift = IsShiftDown(); + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBKeyboardState::Persist(CBPersistMgr *PersistMgr) { + //if(!PersistMgr->m_Saving) Cleanup(); + CBScriptable::Persist(PersistMgr); + + PersistMgr->Transfer(TMEMBER(m_CurrentAlt)); + PersistMgr->Transfer(TMEMBER(m_CurrentCharCode)); + PersistMgr->Transfer(TMEMBER(m_CurrentControl)); + PersistMgr->Transfer(TMEMBER(m_CurrentKeyData)); + PersistMgr->Transfer(TMEMBER(m_CurrentPrintable)); + PersistMgr->Transfer(TMEMBER(m_CurrentShift)); + + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBKeyboardState::IsShiftDown() { + int mod = SDL_GetModState(); + return (mod & KMOD_LSHIFT) || (mod & KMOD_RSHIFT); +} + +////////////////////////////////////////////////////////////////////////// +bool CBKeyboardState::IsControlDown() { + int mod = SDL_GetModState(); + return (mod & KMOD_LCTRL) || (mod & KMOD_RCTRL); +} + +////////////////////////////////////////////////////////////////////////// +bool CBKeyboardState::IsAltDown() { + int mod = SDL_GetModState(); + return (mod & KMOD_LALT) || (mod & KMOD_RALT); +} + +////////////////////////////////////////////////////////////////////////// +uint32 CBKeyboardState::KeyCodeToVKey(SDL_Event *event) { + if (event->type != SDL_KEYDOWN) return 0; + + switch (event->key.keysym.sym) { + case SDLK_KP_ENTER: + return SDLK_RETURN; + default: + return event->key.keysym.sym; + } +} + +////////////////////////////////////////////////////////////////////////// +SDL_Keycode CBKeyboardState::VKeyToKeyCode(uint32 vkey) { + // todo + return (SDL_Keycode)vkey; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BKeyboardState.h b/engines/wintermute/BKeyboardState.h new file mode 100644 index 0000000000..f5ea56f055 --- /dev/null +++ b/engines/wintermute/BKeyboardState.h @@ -0,0 +1,71 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BKEYBOARD_STATE_H +#define WINTERMUTE_BKEYBOARD_STATE_H + + +#include "BBase.h" +#include "BScriptable.h" +#include + +namespace WinterMute { + +class CBKeyboardState : public CBScriptable { +public: + uint32 m_CurrentKeyData; + uint32 m_CurrentCharCode; + bool m_CurrentPrintable; + + bool m_CurrentShift; + bool m_CurrentAlt; + bool m_CurrentControl; + + DECLARE_PERSISTENT(CBKeyboardState, CBScriptable) + CBKeyboardState(CBGame *inGame); + virtual ~CBKeyboardState(); + HRESULT ReadKey(SDL_Event *event); + + static bool IsShiftDown(); + static bool IsControlDown(); + static bool IsAltDown(); + + // scripting interface + virtual CScValue *ScGetProperty(char *Name); + virtual HRESULT ScSetProperty(char *Name, CScValue *Value); + virtual HRESULT ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name); + virtual char *ScToString(); + +private: + uint32 KeyCodeToVKey(SDL_Event *event); + SDL_Keycode VKeyToKeyCode(uint32 vkey); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BPackage.cpp b/engines/wintermute/BPackage.cpp new file mode 100644 index 0000000000..d5ae12fa84 --- /dev/null +++ b/engines/wintermute/BPackage.cpp @@ -0,0 +1,102 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BPackage.h" +#include "BGame.h" +#include "BFileManager.h" + +namespace WinterMute { +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////// +CBPackage::CBPackage(CBGame *inGame): CBBase(inGame) { + m_File = NULL; + m_Name = NULL; + m_CD = 0; + m_Priority = 0; + m_BoundToExe = false; +} + + +////////////////////////////////////////////////////////////////////////// +CBPackage::~CBPackage() { + if (m_Name) delete [] m_Name; + CloseFilePointer(m_File); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBPackage::Open() { + if (m_File) return S_OK; + else { + m_File = GetFilePointer(); + return m_File ? S_OK : E_FAIL; + } +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBPackage::Close() { + if (m_File) fclose(m_File); + m_File = NULL; + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBPackage::Read(FILE *file, uint32 offset, byte *buffer, uint32 size) { + HRESULT ret; + if (FAILED(ret = Open())) return ret; + else { + if (fseek(file, offset, SEEK_SET)) return E_FAIL; + if (fread(buffer, size, 1, file) != 1) return E_FAIL; + else return S_OK; + } +} + +////////////////////////////////////////////////////////////////////////// +FILE *CBPackage::GetFilePointer() { + FILE *file = Game->m_FileManager->OpenPackage(m_Name); + if (!file) { + Game->m_FileManager->RequestCD(m_CD, m_Name, ""); + file = Game->m_FileManager->OpenPackage(m_Name); + } + return file; +} + +////////////////////////////////////////////////////////////////////////// +void CBPackage::CloseFilePointer(FILE*& file) { + if (file) fclose(file); + file = NULL; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BPackage.h b/engines/wintermute/BPackage.h new file mode 100644 index 0000000000..54f2e04a6c --- /dev/null +++ b/engines/wintermute/BPackage.h @@ -0,0 +1,57 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BPACKAGE_H +#define WINTERMUTE_BPACKAGE_H + + +#include "BBase.h" + +namespace WinterMute { + +class CBPackage : public CBBase { +public: + FILE *GetFilePointer(); + void CloseFilePointer(FILE*& file); + + bool m_BoundToExe; + byte m_Priority; + HRESULT Read(FILE *file, uint32 offset, byte *buffer, uint32 size); + HRESULT Close(); + HRESULT Open(); + char *m_Name; + int m_CD; + FILE *m_File; + CBPackage(CBGame *inGame); + virtual ~CBPackage(); + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BPkgFile.cpp b/engines/wintermute/BPkgFile.cpp new file mode 100644 index 0000000000..1210d90e24 --- /dev/null +++ b/engines/wintermute/BPkgFile.cpp @@ -0,0 +1,228 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BPackage.h" +#include "BPkgFile.h" +#include "BGame.h" +#include "BFileManager.h" + +#if _DEBUG +#pragma comment(lib, "zlib_d.lib") +#else +#pragma comment(lib, "zlib.lib") +#endif + + +extern "C" { +#include "zlib.h" +} + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CBPkgFile::CBPkgFile(CBGame *inGame): CBFile(inGame) { + m_FileEntry = NULL; + m_File = NULL; + m_Compressed = false; + + m_Stream.zalloc = (alloc_func)0; + m_Stream.zfree = (free_func)0; + m_Stream.opaque = (voidpf)0; + + m_InflateInit = false; +} + + +////////////////////////////////////////////////////////////////////////// +CBPkgFile::~CBPkgFile() { + Close(); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBPkgFile::Open(Common::String Filename) { + Close(); + + char fileName[MAX_PATH]; + strcpy(fileName, Filename.c_str()); + + // correct slashes + for (int i = 0; i < strlen(fileName); i++) { + if (fileName[i] == '/') fileName[i] = '\\'; + } + + m_FileEntry = Game->m_FileManager->GetPackageEntry(fileName); + if (!m_FileEntry) return E_FAIL; + + m_File = m_FileEntry->m_Package->GetFilePointer(); + if (!m_File) return E_FAIL; + + + m_Compressed = (m_FileEntry->m_CompressedLength != 0); + m_Size = m_FileEntry->m_Length; + + SeekToPos(0); + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBPkgFile::Close() { + if (m_FileEntry) { + m_FileEntry->m_Package->CloseFilePointer(m_File); + m_FileEntry = NULL; + } + m_File = NULL; + + m_Pos = 0; + m_Size = 0; + + if (m_InflateInit) inflateEnd(&m_Stream); + m_InflateInit = false; + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBPkgFile::Read(void *Buffer, uint32 Size) { + if (!m_FileEntry) return E_FAIL; + + HRESULT ret = S_OK; + + if (m_Pos + Size > m_Size) { + Size = m_Size - m_Pos; + if (Size == 0) return E_FAIL; + } + + if (m_Compressed) { + uint32 InitOut = m_Stream.total_out; + + m_Stream.avail_out = Size; + m_Stream.next_out = (byte *)Buffer; + + while (m_Stream.total_out - InitOut < Size && m_Stream.total_in < m_FileEntry->m_CompressedLength) { + // needs to read more data? + if (m_Stream.avail_in == 0) { + m_Stream.avail_in = MIN(COMPRESSED_BUFFER_SIZE, m_FileEntry->m_CompressedLength - m_Stream.total_in); + m_FileEntry->m_Package->Read(m_File, m_FileEntry->m_Offset + m_Stream.total_in, m_CompBuffer, m_Stream.avail_in); + m_Stream.next_in = m_CompBuffer; + } + + int res = inflate(&m_Stream, Z_SYNC_FLUSH); + if (res != Z_OK && res != Z_STREAM_END) { + Game->LOG(0, "zlib error: %d", res); + ret = E_FAIL; + break; + } + } + + + } else { + ret = m_FileEntry->m_Package->Read(m_File, m_FileEntry->m_Offset + m_Pos, (byte *)Buffer, Size); + } + + m_Pos += Size; + + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBPkgFile::Seek(uint32 Pos, TSeek Origin) { + if (!m_FileEntry) return E_FAIL; + + uint32 NewPos = 0; + + switch (Origin) { + case SEEK_TO_BEGIN: + NewPos = Pos; + break; + case SEEK_TO_END: + NewPos = m_Size + Pos; + break; + case SEEK_TO_CURRENT: + NewPos = m_Pos + Pos; + break; + } + + if (NewPos < 0 || NewPos > m_Size) return E_FAIL; + + return SeekToPos(NewPos); +} + + +#define STREAM_BUFFER_SIZE 4096 +////////////////////////////////////////////////////////////////////////// +HRESULT CBPkgFile::SeekToPos(uint32 NewPos) { + HRESULT ret = S_OK; + + // seek compressed stream to NewPos + if (m_Compressed) { + byte StreamBuffer[STREAM_BUFFER_SIZE]; + if (m_InflateInit) inflateEnd(&m_Stream); + m_InflateInit = false; + + m_Stream.avail_in = 0; + m_Stream.next_in = m_CompBuffer; + m_Stream.avail_out = MIN(STREAM_BUFFER_SIZE, NewPos); + m_Stream.next_out = StreamBuffer; + inflateInit(&m_Stream); + m_InflateInit = true; + + while (m_Stream.total_out < NewPos && m_Stream.total_in < m_FileEntry->m_CompressedLength) { + // needs to read more data? + if (m_Stream.avail_in == 0) { + m_Stream.avail_in = MIN(COMPRESSED_BUFFER_SIZE, m_FileEntry->m_CompressedLength - m_Stream.total_in); + m_FileEntry->m_Package->Read(m_File, m_FileEntry->m_Offset + m_Stream.total_in, m_CompBuffer, m_Stream.avail_in); + m_Stream.next_in = m_CompBuffer; + } + + // needs more space? + if (m_Stream.avail_out == 0) { + m_Stream.next_out = StreamBuffer; + m_Stream.avail_out = MIN(STREAM_BUFFER_SIZE, NewPos - m_Stream.total_out); + } + + // stream on! + int res = inflate(&m_Stream, Z_SYNC_FLUSH); + if (res != Z_OK && res != Z_STREAM_END) { + ret = E_FAIL; + break; + } + } + + } + + m_Pos = NewPos; + return ret; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BPkgFile.h b/engines/wintermute/BPkgFile.h new file mode 100644 index 0000000000..a00c954860 --- /dev/null +++ b/engines/wintermute/BPkgFile.h @@ -0,0 +1,61 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BPKGFILE_H +#define WINTERMUTE_BPKGFILE_H + + +#include "BFile.h" +#include "BFileEntry.h" +#include // Added by ClassView + +#define COMPRESSED_BUFFER_SIZE 4096 + +namespace WinterMute { + +class CBPkgFile : public CBFile { +public: + CBPkgFile(CBGame *inGame); + virtual ~CBPkgFile(); + virtual HRESULT Seek(uint32 Pos, TSeek Origin = SEEK_TO_BEGIN); + virtual HRESULT Read(void *Buffer, uint32 Size); + virtual HRESULT Close(); + virtual HRESULT Open(Common::String Filename); +private: + bool m_InflateInit; + HRESULT SeekToPos(uint32 NewPos); + bool m_Compressed; + CBFileEntry *m_FileEntry; + z_stream m_Stream; + byte m_CompBuffer[COMPRESSED_BUFFER_SIZE]; + FILE *m_File; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BPoint.cpp b/engines/wintermute/BPoint.cpp new file mode 100644 index 0000000000..331e9252f4 --- /dev/null +++ b/engines/wintermute/BPoint.cpp @@ -0,0 +1,64 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BPoint.h" +#include "BPersistMgr.h" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CBPoint, false) + +////////////////////////////////////////////////////////////////////////// +CBPoint::CBPoint() { + x = y = 0; +} + + +////////////////////////////////////////////////////////////////////////// +CBPoint::~CBPoint() { + +} + + +////////////////////////////////////////////////////////////////////////// +CBPoint::CBPoint(int initX, int initY) { + x = initX; + y = initY; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBPoint::Persist(CBPersistMgr *PersistMgr) { + + PersistMgr->Transfer(TMEMBER(x)); + PersistMgr->Transfer(TMEMBER(y)); + + return S_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BPoint.h b/engines/wintermute/BPoint.h new file mode 100644 index 0000000000..6cd17653d9 --- /dev/null +++ b/engines/wintermute/BPoint.h @@ -0,0 +1,50 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BPOINT_H +#define WINTERMUTE_BPOINT_H + +#include "persistent.h" +#include "BBase.h" + +namespace WinterMute { + +class CBPoint: public CBBase { +public: + DECLARE_PERSISTENT(CBPoint, CBBase) + CBPoint(); + CBPoint(int initX, int initY); + int y; + int x; + virtual ~CBPoint(); + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BQuickMsg.cpp b/engines/wintermute/BQuickMsg.cpp new file mode 100644 index 0000000000..0f8c54f030 --- /dev/null +++ b/engines/wintermute/BQuickMsg.cpp @@ -0,0 +1,54 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BQuickMsg.h" +#include "BGame.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CBQuickMsg::CBQuickMsg(CBGame *inGame, char *Text): CBBase(inGame) { + m_Text = new char [strlen(Text) + 1]; + if (m_Text) strcpy(m_Text, Text); + m_StartTime = Game->m_CurrentTime; +} + + +////////////////////////////////////////////////////////////////////////// +CBQuickMsg::~CBQuickMsg() { + if (m_Text) delete [] m_Text; +} + + +////////////////////////////////////////////////////////////////////////// +char *CBQuickMsg::GetText() { + return m_Text; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BQuickMsg.h b/engines/wintermute/BQuickMsg.h new file mode 100644 index 0000000000..67bb8cf8bf --- /dev/null +++ b/engines/wintermute/BQuickMsg.h @@ -0,0 +1,48 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BQUICKMSG_H +#define WINTERMUTE_BQUICKMSG_H + +#include "BBase.h" + +namespace WinterMute { + +class CBQuickMsg : public CBBase { +public: + char *GetText(); + uint32 m_StartTime; + char *m_Text; + CBQuickMsg(CBGame *inGame, char *Text); + virtual ~CBQuickMsg(); + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BRegion.cpp b/engines/wintermute/BRegion.cpp new file mode 100644 index 0000000000..309d44edab --- /dev/null +++ b/engines/wintermute/BRegion.cpp @@ -0,0 +1,508 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BRegion.h" +#include "BParser.h" +#include "BDynBuffer.h" +#include "ScValue.h" +#include "BGame.h" +#include "ScScript.h" +#include "ScStack.h" +#include "BFileManager.h" +#include "PlatformSDL.h" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CBRegion, false) + +////////////////////////////////////////////////////////////////////////// +CBRegion::CBRegion(CBGame *inGame): CBObject(inGame) { + m_Active = true; + m_EditorSelectedPoint = -1; + m_LastMimicScale = -1; + m_LastMimicX = m_LastMimicY = INT_MIN; + + CBPlatform::SetRectEmpty(&m_Rect); +} + + +////////////////////////////////////////////////////////////////////////// +CBRegion::~CBRegion() { + Cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +void CBRegion::Cleanup() { + for (int i = 0; i < m_Points.GetSize(); i++) delete m_Points[i]; + m_Points.RemoveAll(); + + CBPlatform::SetRectEmpty(&m_Rect); + m_EditorSelectedPoint = -1; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBRegion::CreateRegion() { + return SUCCEEDED(GetBoundingRect(&m_Rect)); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBRegion::PointInRegion(int X, int Y) { + if (m_Points.GetSize() < 3) return false; + + POINT pt; + pt.x = X; + pt.y = Y; + + RECT rect; + rect.left = X - 1; + rect.right = X + 2; + rect.top = Y - 1; + rect.bottom = Y + 2; + + if (CBPlatform::PtInRect(&m_Rect, pt)) return PtInPolygon(X, Y); + else return false; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRegion::LoadFile(char *Filename) { + byte *Buffer = Game->m_FileManager->ReadWholeFile(Filename); + if (Buffer == NULL) { + Game->LOG(0, "CBRegion::LoadFile failed for file '%s'", Filename); + return E_FAIL; + } + + HRESULT ret; + + m_Filename = new char [strlen(Filename) + 1]; + strcpy(m_Filename, Filename); + + if (FAILED(ret = LoadBuffer(Buffer, true))) Game->LOG(0, "Error parsing REGION file '%s'", Filename); + + + delete [] Buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(REGION) +TOKEN_DEF(TEMPLATE) +TOKEN_DEF(NAME) +TOKEN_DEF(ACTIVE) +TOKEN_DEF(POINT) +TOKEN_DEF(CAPTION) +TOKEN_DEF(SCRIPT) +TOKEN_DEF(EDITOR_SELECTED_POINT) +TOKEN_DEF(PROPERTY) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +HRESULT CBRegion::LoadBuffer(byte *Buffer, bool Complete) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(REGION) + TOKEN_TABLE(TEMPLATE) + TOKEN_TABLE(NAME) + TOKEN_TABLE(ACTIVE) + TOKEN_TABLE(POINT) + TOKEN_TABLE(CAPTION) + TOKEN_TABLE(SCRIPT) + TOKEN_TABLE(EDITOR_SELECTED_POINT) + TOKEN_TABLE(PROPERTY) + TOKEN_TABLE_END + + byte *params; + int cmd; + CBParser parser(Game); + + if (Complete) { + if (parser.GetCommand((char **)&Buffer, commands, (char **)¶ms) != TOKEN_REGION) { + Game->LOG(0, "'REGION' keyword expected."); + return E_FAIL; + } + Buffer = params; + } + + int i; + + for (i = 0; i < m_Points.GetSize(); i++) delete m_Points[i]; + m_Points.RemoveAll(); + + while ((cmd = parser.GetCommand((char **)&Buffer, commands, (char **)¶ms)) > 0) { + switch (cmd) { + case TOKEN_TEMPLATE: + if (FAILED(LoadFile((char *)params))) cmd = PARSERR_GENERIC; + break; + + case TOKEN_NAME: + SetName((char *)params); + break; + + case TOKEN_CAPTION: + SetCaption((char *)params); + break; + + case TOKEN_ACTIVE: + parser.ScanStr((char *)params, "%b", &m_Active); + break; + + case TOKEN_POINT: { + int x, y; + parser.ScanStr((char *)params, "%d,%d", &x, &y); + m_Points.Add(new CBPoint(x, y)); + } + break; + + case TOKEN_SCRIPT: + AddScript((char *)params); + break; + + case TOKEN_EDITOR_SELECTED_POINT: + parser.ScanStr((char *)params, "%d", &m_EditorSelectedPoint); + break; + + case TOKEN_PROPERTY: + ParseProperty(params, false); + break; + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + Game->LOG(0, "Syntax error in REGION definition"); + return E_FAIL; + } + + CreateRegion(); + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +HRESULT CBRegion::ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name) { + + ////////////////////////////////////////////////////////////////////////// + // AddPoint + ////////////////////////////////////////////////////////////////////////// + if (strcmp(Name, "AddPoint") == 0) { + Stack->CorrectParams(2); + int X = Stack->Pop()->GetInt(); + int Y = Stack->Pop()->GetInt(); + + m_Points.Add(new CBPoint(X, Y)); + CreateRegion(); + + Stack->PushBool(true); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // InsertPoint + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "InsertPoint") == 0) { + Stack->CorrectParams(3); + int Index = Stack->Pop()->GetInt(); + int X = Stack->Pop()->GetInt(); + int Y = Stack->Pop()->GetInt(); + + if (Index >= 0 && Index < m_Points.GetSize()) { + m_Points.InsertAt(Index, new CBPoint(X, Y)); + CreateRegion(); + + Stack->PushBool(true); + } else Stack->PushBool(false); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetPoint + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SetPoint") == 0) { + Stack->CorrectParams(3); + int Index = Stack->Pop()->GetInt(); + int X = Stack->Pop()->GetInt(); + int Y = Stack->Pop()->GetInt(); + + if (Index >= 0 && Index < m_Points.GetSize()) { + m_Points[Index]->x = X; + m_Points[Index]->y = Y; + CreateRegion(); + + Stack->PushBool(true); + } else Stack->PushBool(false); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // RemovePoint + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "RemovePoint") == 0) { + Stack->CorrectParams(1); + int Index = Stack->Pop()->GetInt(); + + if (Index >= 0 && Index < m_Points.GetSize()) { + delete m_Points[Index]; + m_Points[Index] = NULL; + + m_Points.RemoveAt(Index); + CreateRegion(); + + Stack->PushBool(true); + } else Stack->PushBool(false); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetPoint + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "GetPoint") == 0) { + Stack->CorrectParams(1); + int Index = Stack->Pop()->GetInt(); + + if (Index >= 0 && Index < m_Points.GetSize()) { + CScValue *Val = Stack->GetPushValue(); + if (Val) { + Val->SetProperty("X", m_Points[Index]->x); + Val->SetProperty("Y", m_Points[Index]->y); + } + } else Stack->PushNULL(); + + return S_OK; + } + + else return CBObject::ScCallMethod(Script, Stack, ThisStack, Name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CBRegion::ScGetProperty(char *Name) { + m_ScValue->SetNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type + ////////////////////////////////////////////////////////////////////////// + if (strcmp(Name, "Type") == 0) { + m_ScValue->SetString("region"); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Name + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Name") == 0) { + m_ScValue->SetString(m_Name); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Active + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Active") == 0) { + m_ScValue->SetBool(m_Active); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // NumPoints + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "NumPoints") == 0) { + m_ScValue->SetInt(m_Points.GetSize()); + return m_ScValue; + } + + else return CBObject::ScGetProperty(Name); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRegion::ScSetProperty(char *Name, CScValue *Value) { + ////////////////////////////////////////////////////////////////////////// + // Name + ////////////////////////////////////////////////////////////////////////// + if (strcmp(Name, "Name") == 0) { + SetName(Value->GetString()); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Active + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Active") == 0) { + m_Active = Value->GetBool(); + return S_OK; + } + + else return CBObject::ScSetProperty(Name, Value); +} + + +////////////////////////////////////////////////////////////////////////// +char *CBRegion::ScToString() { + return "[region]"; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRegion::SaveAsText(CBDynBuffer *Buffer, int Indent, char *NameOverride) { + if (!NameOverride) Buffer->PutTextIndent(Indent, "REGION {\n"); + else Buffer->PutTextIndent(Indent, "%s {\n", NameOverride); + + Buffer->PutTextIndent(Indent + 2, "NAME=\"%s\"\n", m_Name); + Buffer->PutTextIndent(Indent + 2, "CAPTION=\"%s\"\n", GetCaption()); + Buffer->PutTextIndent(Indent + 2, "ACTIVE=%s\n", m_Active ? "TRUE" : "FALSE"); + Buffer->PutTextIndent(Indent + 2, "EDITOR_SELECTED_POINT=%d\n", m_EditorSelectedPoint); + + int i; + + for (i = 0; i < m_Scripts.GetSize(); i++) { + Buffer->PutTextIndent(Indent + 2, "SCRIPT=\"%s\"\n", m_Scripts[i]->m_Filename); + } + + for (i = 0; i < m_Points.GetSize(); i++) { + Buffer->PutTextIndent(Indent + 2, "POINT {%d,%d}\n", m_Points[i]->x, m_Points[i]->y); + } + + if (m_ScProp) m_ScProp->SaveAsText(Buffer, Indent + 2); + + Buffer->PutTextIndent(Indent, "}\n\n"); + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRegion::Persist(CBPersistMgr *PersistMgr) { + + CBObject::Persist(PersistMgr); + + PersistMgr->Transfer(TMEMBER(m_Active)); + PersistMgr->Transfer(TMEMBER(m_EditorSelectedPoint)); + PersistMgr->Transfer(TMEMBER(m_LastMimicScale)); + PersistMgr->Transfer(TMEMBER(m_LastMimicX)); + PersistMgr->Transfer(TMEMBER(m_LastMimicY)); + m_Points.Persist(PersistMgr); + + return S_OK; +} + + +typedef struct { + double x, y; +} dPoint; + +////////////////////////////////////////////////////////////////////////// +bool CBRegion::PtInPolygon(int X, int Y) { + if (m_Points.GetSize() < 3) return false; + + int counter = 0; + int i; + double xinters; + dPoint p, p1, p2; + + p.x = (double)X; + p.y = (double)Y; + + p1.x = (double)m_Points[0]->x; + p1.y = (double)m_Points[0]->y; + + for (i = 1; i <= m_Points.GetSize(); i++) { + p2.x = (double)m_Points[i % m_Points.GetSize()]->x; + p2.y = (double)m_Points[i % m_Points.GetSize()]->y; + + if (p.y > std::min(p1.y, p2.y)) { + if (p.y <= std::max(p1.y, p2.y)) { + if (p.x <= std::max(p1.x, p2.x)) { + if (p1.y != p2.y) { + xinters = (p.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x; + if (p1.x == p2.x || p.x <= xinters) + counter++; + } + } + } + } + p1 = p2; + } + + if (counter % 2 == 0) + return false; + else + return true; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRegion::GetBoundingRect(RECT *Rect) { + if (m_Points.GetSize() == 0) CBPlatform::SetRectEmpty(Rect); + else { + int MinX = INT_MAX, MinY = INT_MAX, MaxX = INT_MIN, MaxY = INT_MIN; + + for (int i = 0; i < m_Points.GetSize(); i++) { + MinX = std::min(MinX, m_Points[i]->x); + MinY = std::min(MinY, m_Points[i]->y); + + MaxX = std::max(MaxX, m_Points[i]->x); + MaxY = std::max(MaxY, m_Points[i]->y); + } + CBPlatform::SetRect(Rect, MinX, MinY, MaxX, MaxY); + } + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRegion::Mimic(CBRegion *Region, float Scale, int X, int Y) { + if (Scale == m_LastMimicScale && X == m_LastMimicX && Y == m_LastMimicY) return S_OK; + + Cleanup(); + + for (int i = 0; i < Region->m_Points.GetSize(); i++) { + int x, y; + + x = (int)((float)Region->m_Points[i]->x * Scale / 100.0f); + y = (int)((float)Region->m_Points[i]->y * Scale / 100.0f); + + m_Points.Add(new CBPoint(x + X, y + Y)); + } + + m_LastMimicScale = Scale; + m_LastMimicX = X; + m_LastMimicY = Y; + + return CreateRegion() ? S_OK : E_FAIL; +} + +} // end of namespace WinterMute \ No newline at end of file diff --git a/engines/wintermute/BRegion.h b/engines/wintermute/BRegion.h new file mode 100644 index 0000000000..94202ea8dd --- /dev/null +++ b/engines/wintermute/BRegion.h @@ -0,0 +1,68 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BREGION_H +#define WINTERMUTE_BREGION_H + +#include "BPoint.h" +#include "BObject.h" + +namespace WinterMute { + +class CBRegion : public CBObject { +public: + float m_LastMimicScale; + int m_LastMimicX; + int m_LastMimicY; + void Cleanup(); + HRESULT Mimic(CBRegion *Region, float Scale = 100.0f, int X = 0, int Y = 0); + HRESULT GetBoundingRect(RECT *Rect); + bool PtInPolygon(int X, int Y); + DECLARE_PERSISTENT(CBRegion, CBObject) + bool m_Active; + int m_EditorSelectedPoint; + CBRegion(CBGame *inGame); + virtual ~CBRegion(); + bool PointInRegion(int X, int Y); + bool CreateRegion(); + HRESULT LoadFile(char *Filename); + HRESULT LoadBuffer(byte *Buffer, bool Complete = true); + RECT m_Rect; + CBArray m_Points; + virtual HRESULT SaveAsText(CBDynBuffer *Buffer, int Indent, char *NameOverride = NULL); + + // scripting interface + virtual CScValue *ScGetProperty(char *Name); + virtual HRESULT ScSetProperty(char *Name, CScValue *Value); + virtual HRESULT ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name); + virtual char *ScToString(); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BRegistry.cpp b/engines/wintermute/BRegistry.cpp new file mode 100644 index 0000000000..4d7b1b6d37 --- /dev/null +++ b/engines/wintermute/BRegistry.cpp @@ -0,0 +1,227 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include +#include "BGame.h" +#include "BRegistry.h" +#include "PathUtil.h" +#include "StringUtil.h" +#include "tinyxml.h" +#include "utils.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CBRegistry::CBRegistry(CBGame *inGame): CBBase(inGame) { + m_IniName = NULL; + + SetIniName("./wme.ini"); + LoadValues(true); +} + + +////////////////////////////////////////////////////////////////////////// +CBRegistry::~CBRegistry() { + SaveValues(); + delete[] m_IniName; + m_IniName = NULL; +} + + + +////////////////////////////////////////////////////////////////////////// +AnsiString CBRegistry::ReadString(const AnsiString &subKey, const AnsiString &key, const AnsiString &init) { + AnsiString ret = ""; + +#ifdef __WIN32__ + // check ini file first (so what we can use project files on windows) + char buffer[32768]; + GetPrivateProfileString(subKey.c_str(), key.c_str(), init.c_str(), buffer, 32768, m_IniName); + ret = AnsiString(buffer); + + if (buffer != init) return ret; +#endif + + bool found = false; + ret = GetValue(m_LocalValues, subKey, key, found); + if (!found) ret = GetValue(m_Values, subKey, key, found); + if (!found) ret = init; + + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBRegistry::WriteString(const AnsiString &subKey, const AnsiString &key, const AnsiString &value) { + m_Values[subKey][key] = value; + return true; +} + + +////////////////////////////////////////////////////////////////////////// +int CBRegistry::ReadInt(const AnsiString &subKey, const AnsiString &key, int init) { +#ifdef __WIN32__ + int ret = GetPrivateProfileInt(subKey.c_str(), key.c_str(), init, m_IniName); + if (ret != init) return ret; +#endif + + AnsiString val = ReadString(subKey, key, ""); + if (val.empty()) return init; + else return atoi(val.c_str()); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBRegistry::WriteInt(const AnsiString &subKey, const AnsiString &key, int value) { + WriteString(subKey, key, StringUtil::ToString(value)); + return true; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBRegistry::ReadBool(const AnsiString &subKey, const AnsiString &key, bool init) { + return (ReadInt(subKey, key, (int)init) != 0); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBRegistry::WriteBool(const AnsiString &subKey, const AnsiString &key, bool value) { + return WriteInt(subKey, key, (int)value); +} + + +////////////////////////////////////////////////////////////////////////// +void CBRegistry::SetIniName(char *Name) { + delete[] m_IniName; + m_IniName = NULL; + + if (strchr(Name, '\\') == NULL && strchr(Name, '/') == NULL) { + m_IniName = new char [strlen(Name) + 3]; + sprintf(m_IniName, "./%s", Name); + } else { + m_IniName = new char [strlen(Name) + 1]; + strcpy(m_IniName, Name); + } +} + + +////////////////////////////////////////////////////////////////////////// +char *CBRegistry::GetIniName() { + return m_IniName; +} + +////////////////////////////////////////////////////////////////////////// +void CBRegistry::LoadValues(bool local) { + if (local) LoadXml("settings.xml", m_LocalValues); + else LoadXml(PathUtil::Combine(Game->GetDataDir(), "settings.xml"), m_Values); +} + +////////////////////////////////////////////////////////////////////////// +void CBRegistry::SaveValues() { + SaveXml(PathUtil::Combine(Game->GetDataDir(), "settings.xml"), m_Values); +} + +////////////////////////////////////////////////////////////////////////// +void CBRegistry::SetBasePath(const char *basePath) { + m_BasePath = PathUtil::GetFileNameWithoutExtension(basePath); + + LoadValues(false); +} + +////////////////////////////////////////////////////////////////////////// +AnsiString CBRegistry::GetValue(PathValueMap &values, const AnsiString path, const AnsiString &key, bool &found) { + found = false; + PathValueMap::iterator it = values.find(path); + if (it == values.end()) return ""; + + KeyValuePair pairs = (*it).second; + KeyValuePair::iterator keyIt = pairs.find(key); + if (keyIt == pairs.end()) return ""; + else { + found = true; + return (*keyIt).second; + } +} + +////////////////////////////////////////////////////////////////////////// +void CBRegistry::LoadXml(const AnsiString fileName, PathValueMap &values) { + TiXmlDocument doc(fileName); + if (!doc.LoadFile()) return; + + TiXmlElement *rootElem = doc.RootElement(); + if (!rootElem || rootElem->ValueStr() != "Settings") return; + + for (TiXmlElement *pathElem = rootElem->FirstChildElement(); pathElem != NULL; pathElem = pathElem->NextSiblingElement()) { + for (TiXmlElement *keyElem = pathElem->FirstChildElement(); keyElem != NULL; keyElem = keyElem->NextSiblingElement()) { + values[pathElem->ValueStr()][keyElem->ValueStr()] = keyElem->GetText(); + } + } +} + + +////////////////////////////////////////////////////////////////////////// +void CBRegistry::SaveXml(const AnsiString fileName, PathValueMap &values) { + CBUtils::CreatePath(fileName.c_str()); + + TiXmlDocument doc; + doc.LinkEndChild(new TiXmlDeclaration("1.0", "utf-8", "")); + + TiXmlElement *root = new TiXmlElement("Settings"); + doc.LinkEndChild(root); + + PathValueMap::iterator pathIt; + for (pathIt = m_Values.begin(); pathIt != m_Values.end(); ++pathIt) { + TiXmlElement *pathElem = new TiXmlElement((*pathIt).first); + root->LinkEndChild(pathElem); + + + KeyValuePair pairs = (*pathIt).second; + KeyValuePair::iterator keyIt; + for (keyIt = pairs.begin(); keyIt != pairs.end(); ++keyIt) { + TiXmlElement *keyElem = new TiXmlElement((*keyIt).first); + pathElem->LinkEndChild(keyElem); + + keyElem->LinkEndChild(new TiXmlText((*keyIt).second)); + } + } + + + TiXmlPrinter printer; + doc.Accept(&printer); + + std::ofstream stream; + stream.open(fileName.c_str()); + + if (!stream.is_open()) return; + else { + stream << printer.Str(); + stream.close(); + } +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BRegistry.h b/engines/wintermute/BRegistry.h new file mode 100644 index 0000000000..48b88fd663 --- /dev/null +++ b/engines/wintermute/BRegistry.h @@ -0,0 +1,76 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BREGISTRY_H +#define WINTERMUTE_BREGISTRY_H + +#include "BBase.h" + +namespace WinterMute { + +class CBRegistry : public CBBase { +public: + void SetIniName(char *Name); + char *GetIniName(); + bool WriteBool(const AnsiString &subKey, const AnsiString &key, bool Value); + bool ReadBool(const AnsiString &subKey, const AnsiString &key, bool init = false); + bool WriteInt(const AnsiString &subKey, const AnsiString &key, int value); + int ReadInt(const AnsiString &subKey, const AnsiString &key, int init = 0); + bool WriteString(const AnsiString &subKey, const AnsiString &key, const AnsiString &value); + AnsiString ReadString(const AnsiString &subKey, const AnsiString &key, const AnsiString &init = ""); + CBRegistry(CBGame *inGame); + virtual ~CBRegistry(); + + void SetBasePath(const char *basePath); + AnsiString GetBasePath() const { + return m_BasePath; + } + + void LoadValues(bool local); + void SaveValues(); + +private: + char *m_IniName; + + typedef std::map KeyValuePair; + typedef std::map PathValueMap; + + PathValueMap m_LocalValues; + PathValueMap m_Values; + + AnsiString m_BasePath; + + void LoadXml(const AnsiString fileName, PathValueMap &values); + void SaveXml(const AnsiString fileName, PathValueMap &values); + + AnsiString GetValue(PathValueMap &values, const AnsiString path, const AnsiString &key, bool &found); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BRenderSDL.cpp b/engines/wintermute/BRenderSDL.cpp new file mode 100644 index 0000000000..312954097d --- /dev/null +++ b/engines/wintermute/BRenderSDL.cpp @@ -0,0 +1,408 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BRenderSDL.h" +#include "BRegistry.h" +#include "BSurfaceSDL.h" +#include "BImage.h" +#include "MathUtil.h" +#include "BGame.h" +#include "BSprite.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CBRenderSDL::CBRenderSDL(CBGame *inGame) : CBRenderer(inGame) { + m_Renderer = NULL; + m_Win = NULL; + + m_BorderLeft = m_BorderRight = m_BorderTop = m_BorderBottom = 0; + m_RatioX = m_RatioY = 1.0f; +} + +////////////////////////////////////////////////////////////////////////// +CBRenderSDL::~CBRenderSDL() { + if (m_Renderer) SDL_DestroyRenderer(m_Renderer); + if (m_Win) SDL_DestroyWindow(m_Win); + + SDL_Quit(); +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRenderSDL::InitRenderer(int width, int height, bool windowed) { + if (SDL_Init(SDL_INIT_VIDEO) < 0) return E_FAIL; + + + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0); + SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, 1); + + + m_Width = width; + m_Height = height; + + m_RealWidth = width; + m_RealHeight = height; + + + // find suitable resolution +#ifdef __IPHONEOS__ + m_RealWidth = 480; + m_RealHeight = 320; + + int numModes = SDL_GetNumDisplayModes(0); + for (int i = 0; i < numModes; i++) { + SDL_DisplayMode mode; + SDL_GetDisplayMode(0, i, &mode); + + if (mode.w > mode.h) { + m_RealWidth = mode.w; + m_RealHeight = mode.h; + break; + } + } +#else + m_RealWidth = Game->m_Registry->ReadInt("Debug", "ForceResWidth", m_Width); + m_RealHeight = Game->m_Registry->ReadInt("Debug", "ForceResHeight", m_Height); +#endif + + /* + m_RealWidth = 480; + m_RealHeight = 320; + */ + + + float origAspect = (float)m_Width / (float)m_Height; + float realAspect = (float)m_RealWidth / (float)m_RealHeight; + + float ratio; + if (origAspect < realAspect) { + // normal to wide + ratio = (float)m_RealHeight / (float)m_Height; + } else { + // wide to normal + ratio = (float)m_RealWidth / (float)m_Width; + } + + m_BorderLeft = (m_RealWidth - (m_Width * ratio)) / 2; + m_BorderRight = m_RealWidth - (m_Width * ratio) - m_BorderLeft; + + m_BorderTop = (m_RealHeight - (m_Height * ratio)) / 2; + m_BorderBottom = m_RealHeight - (m_Height * ratio) - m_BorderTop; + + + + m_RatioX = (float)(m_RealWidth - m_BorderLeft - m_BorderRight) / (float)m_Width; + m_RatioY = (float)(m_RealHeight - m_BorderTop - m_BorderBottom) / (float)m_Height; + + + Uint32 flags = SDL_WINDOW_SHOWN; +#ifdef __IPHONEOS__ + flags |= SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS; +#endif + + //m_Windowed = Game->m_Registry->ReadBool("Video", "Windowed", true); + if (!windowed) flags |= SDL_WINDOW_FULLSCREEN; + + + m_Win = SDL_CreateWindow("WME Lite", + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + m_RealWidth, m_RealHeight, + flags); + + if (!m_Win) return E_FAIL; + + SDL_ShowCursor(SDL_DISABLE); + +#ifdef __IPHONEOS__ + // SDL defaults to OGL ES2, which doesn't work on old devices + SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengles"); +#else + //SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl"); +#endif + + m_Renderer = SDL_CreateRenderer(m_Win, -1, 0); + if (!m_Renderer) return E_FAIL; + + m_Active = true; + + + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRenderSDL::Flip() { + +#ifdef __IPHONEOS__ + // hack: until viewports work correctly, we just paint black bars instead + SDL_SetRenderDrawColor(m_Renderer, 0x00, 0x00, 0x00, 0xFF); + + static bool firstRefresh = true; // prevents a weird color glitch + if (firstRefresh) { + firstRefresh = false; + } else { + SDL_Rect rect; + if (m_BorderLeft > 0) { + rect.x = 0; + rect.y = 0; + rect.w = m_BorderLeft; + rect.h = m_RealHeight; + SDL_RenderFillRect(m_Renderer, &rect); + } + if (m_BorderRight > 0) { + rect.x = (m_RealWidth - m_BorderRight); + rect.y = 0; + rect.w = m_BorderRight; + rect.h = m_RealHeight; + SDL_RenderFillRect(m_Renderer, &rect); + } + if (m_BorderTop > 0) { + rect.x = 0; + rect.y = 0; + rect.w = m_RealWidth; + rect.h = m_BorderTop; + SDL_RenderFillRect(m_Renderer, &rect); + } + if (m_BorderBottom > 0) { + rect.x = 0; + rect.y = m_RealHeight - m_BorderBottom; + rect.w = m_RealWidth; + rect.h = m_BorderBottom; + SDL_RenderFillRect(m_Renderer, &rect); + } + } +#endif + + + SDL_RenderPresent(m_Renderer); + + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRenderSDL::Fill(byte r, byte g, byte b, RECT *rect) { + SDL_SetRenderDrawColor(m_Renderer, r, g, b, 0xFF); + SDL_RenderClear(m_Renderer); + + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRenderSDL::Fade(WORD Alpha) { + uint32 dwAlpha = 255 - Alpha; + return FadeToColor(dwAlpha << 24); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRenderSDL::FadeToColor(uint32 Color, RECT *rect) { + SDL_Rect fillRect; + + if (rect) { + fillRect.x = rect->left; + fillRect.y = rect->top; + fillRect.w = rect->right - rect->left; + fillRect.h = rect->bottom - rect->top; + } else { + RECT rc; + Game->GetCurrentViewportRect(&rc); + fillRect.x = rc.left; + fillRect.y = rc.top; + fillRect.w = rc.right - rc.left; + fillRect.h = rc.bottom - rc.top; + } + ModTargetRect(&fillRect); + + byte r = D3DCOLGetR(Color); + byte g = D3DCOLGetG(Color); + byte b = D3DCOLGetB(Color); + byte a = D3DCOLGetA(Color); + + SDL_SetRenderDrawColor(m_Renderer, r, g, b, a); + SDL_SetRenderDrawBlendMode(m_Renderer, SDL_BLENDMODE_BLEND); + SDL_RenderFillRect(m_Renderer, &fillRect); + + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRenderSDL::DrawLine(int X1, int Y1, int X2, int Y2, uint32 Color) { + byte r = D3DCOLGetR(Color); + byte g = D3DCOLGetG(Color); + byte b = D3DCOLGetB(Color); + byte a = D3DCOLGetA(Color); + + SDL_SetRenderDrawColor(m_Renderer, r, g, b, a); + SDL_SetRenderDrawBlendMode(m_Renderer, SDL_BLENDMODE_BLEND); + + POINT point1, point2; + point1.x = X1; + point1.y = Y1; + PointToScreen(&point1); + + point2.x = X2; + point2.y = Y2; + PointToScreen(&point2); + + + SDL_RenderDrawLine(m_Renderer, point1.x, point1.y, point2.x, point2.y); + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +CBImage *CBRenderSDL::TakeScreenshot() { +// TODO: Fix this +#if 0 + SDL_Rect viewport; + + SDL_RenderGetViewport(m_Renderer, &viewport); + + SDL_Surface *surface = SDL_CreateRGBSurface(0, viewport.w, viewport.h, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, 0x00000000); + if (!surface) return NULL; + + if (SDL_RenderReadPixels(m_Renderer, NULL, surface->format->format, surface->pixels, surface->pitch) < 0) return NULL; + + FIBITMAP *dib = FreeImage_Allocate(viewport.w, viewport.h, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK); + + int bytespp = FreeImage_GetLine(dib) / FreeImage_GetWidth(dib); + + for (unsigned y = 0; y < FreeImage_GetHeight(dib); y++) { + byte *bits = FreeImage_GetScanLine(dib, y); + byte *src = (byte *)surface->pixels + (viewport.h - y - 1) * surface->pitch; + memcpy(bits, src, bytespp * viewport.w); + } + + return new CBImage(Game, dib); +#endif + return NULL; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRenderSDL::SwitchFullscreen() { + if (m_Windowed) SDL_SetWindowFullscreen(m_Win, SDL_TRUE); + else SDL_SetWindowFullscreen(m_Win, SDL_FALSE); + + m_Windowed = !m_Windowed; + + Game->m_Registry->WriteBool("Video", "Windowed", m_Windowed); + + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +const char *CBRenderSDL::GetName() { + if (m_Name.empty()) { + if (m_Renderer) { + SDL_RendererInfo info; + SDL_GetRendererInfo(m_Renderer, &info); + m_Name = AnsiString(info.name); + } + } + return m_Name.c_str(); +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRenderSDL::SetViewport(int left, int top, int right, int bottom) { + SDL_Rect rect; + rect.x = left + m_BorderLeft; + rect.y = top + m_BorderTop; + rect.w = (right - left) * m_RatioX; + rect.h = (bottom - top) * m_RatioY; + + // TODO fix this once viewports work correctly in SDL/landscape +#ifndef __IPHONEOS__ + SDL_RenderSetViewport(GetSdlRenderer(), &rect); +#endif + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +void CBRenderSDL::ModTargetRect(SDL_Rect *rect) { + SDL_Rect viewportRect; + SDL_RenderGetViewport(GetSdlRenderer(), &viewportRect); + + rect->x = MathUtil::Round(rect->x * m_RatioX + m_BorderLeft - viewportRect.x); + rect->y = MathUtil::Round(rect->y * m_RatioY + m_BorderTop - viewportRect.y); + rect->w = MathUtil::RoundUp(rect->w * m_RatioX); + rect->h = MathUtil::RoundUp(rect->h * m_RatioY); +} + +////////////////////////////////////////////////////////////////////////// +void CBRenderSDL::PointFromScreen(POINT *point) { + SDL_Rect viewportRect; + SDL_RenderGetViewport(GetSdlRenderer(), &viewportRect); + + point->x = point->x / m_RatioX - m_BorderLeft / m_RatioX + viewportRect.x; + point->y = point->y / m_RatioY - m_BorderTop / m_RatioY + viewportRect.y; +} + + +////////////////////////////////////////////////////////////////////////// +void CBRenderSDL::PointToScreen(POINT *point) { + SDL_Rect viewportRect; + SDL_RenderGetViewport(GetSdlRenderer(), &viewportRect); + + point->x = MathUtil::RoundUp(point->x * m_RatioX) + m_BorderLeft - viewportRect.x; + point->y = MathUtil::RoundUp(point->y * m_RatioY) + m_BorderTop - viewportRect.y; + +} + +////////////////////////////////////////////////////////////////////////// +void CBRenderSDL::DumpData(char *Filename) { + FILE *f = fopen(Filename, "wt"); + if (!f) return; + + CBSurfaceStorage *Mgr = Game->m_SurfaceStorage; + + int TotalKB = 0; + int TotalLoss = 0; + fprintf(f, "Filename;Usage;Size;KBytes\n"); + for (int i = 0; i < Mgr->m_Surfaces.GetSize(); i++) { + CBSurfaceSDL *Surf = (CBSurfaceSDL *)Mgr->m_Surfaces[i]; + if (!Surf->m_Filename) continue; + if (!Surf->m_Valid) continue; + + fprintf(f, "%s;%d;", Surf->m_Filename, Surf->m_ReferenceCount); + fprintf(f, "%dx%d;", Surf->GetWidth(), Surf->GetHeight()); + + int kb = Surf->GetWidth() * Surf->GetHeight() * 4 / 1024; + + TotalKB += kb; + fprintf(f, "%d;", kb); + fprintf(f, "\n"); + } + fprintf(f, "Total %d;;;%d\n", Mgr->m_Surfaces.GetSize(), TotalKB); + + + fclose(f); + Game->LOG(0, "Texture Stats Dump completed."); + Game->QuickMessage("Texture Stats Dump completed."); +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BRenderSDL.h b/engines/wintermute/BRenderSDL.h new file mode 100644 index 0000000000..3489881e14 --- /dev/null +++ b/engines/wintermute/BRenderSDL.h @@ -0,0 +1,95 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BRENDERER_SDL_H +#define WINTERMUTE_BRENDERER_SDL_H + +#include "BRenderer.h" +#include "SDL.h" + +namespace WinterMute { + +class CBRenderSDL : public CBRenderer { +public: + CBRenderSDL(CBGame *inGame); + ~CBRenderSDL(); + + const char *GetName(); + + HRESULT InitRenderer(int width, int height, bool windowed); + HRESULT Flip(); + HRESULT Fill(byte r, byte g, byte b, RECT *rect); + + HRESULT Fade(WORD Alpha); + HRESULT FadeToColor(uint32 Color, RECT *rect = NULL); + + HRESULT SwitchFullscreen(); + + HRESULT DrawLine(int X1, int Y1, int X2, int Y2, uint32 Color); + + CBImage *TakeScreenshot(); + + SDL_Renderer *GetSdlRenderer() const { + return m_Renderer; + } + SDL_Window *GetSdlWindow() const { + return m_Win; + } + + HRESULT SetViewport(int left, int top, int right, int bottom); + + void ModTargetRect(SDL_Rect *rect); + void PointFromScreen(POINT *point); + void PointToScreen(POINT *point); + + void DumpData(char *Filename); + + float GetScaleRatioX() const { + return m_RatioX; + } + float GetScaleRatioY() const { + return m_RatioY; + } + +private: + SDL_Renderer *m_Renderer; + SDL_Window *m_Win; + AnsiString m_Name; + + int m_BorderLeft; + int m_BorderTop; + int m_BorderRight; + int m_BorderBottom; + + float m_RatioX; + float m_RatioY; +}; + +} // end of namespace WinterMute + +#endif // __WmeBRenderSDL_H__ diff --git a/engines/wintermute/BRenderer.cpp b/engines/wintermute/BRenderer.cpp new file mode 100644 index 0000000000..aaaca902fa --- /dev/null +++ b/engines/wintermute/BRenderer.cpp @@ -0,0 +1,259 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BActiveRect.h" +#include "BRenderer.h" +#include "BSurface.h" +#include "BSubFrame.h" +#include "BRegion.h" +#include "PlatformSDL.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +CBRenderer::CBRenderer(CBGame *inGame): CBBase(inGame) { + m_Instance = NULL; + m_Window = NULL; + m_ClipperWindow = NULL; + m_Active = false; + m_Ready = false; + m_Windowed = true; + m_ForceAlphaColor = 0x00; + + m_Width = m_Height = m_BPP = 0; + CBPlatform::SetRectEmpty(&m_MonitorRect); + + m_RealWidth = m_RealHeight = 0; + m_DrawOffsetX = m_DrawOffsetY = 0; +} + + +////////////////////////////////////////////////////////////////////// +CBRenderer::~CBRenderer() { + DeleteRectList(); + UnclipCursor(); +} + + +////////////////////////////////////////////////////////////////////// +void CBRenderer::InitLoop() { + DeleteRectList(); +} + + +////////////////////////////////////////////////////////////////////// +CBObject *CBRenderer::GetObjectAt(int X, int Y) { + POINT point; + point.x = X; + point.y = Y; + + for (int i = m_RectList.GetSize() - 1; i >= 0; i--) { + if (CBPlatform::PtInRect(&m_RectList[i]->m_Rect, point)) { + if (m_RectList[i]->m_Precise) { + // frame + if (m_RectList[i]->m_Frame) { + int XX = (int)((m_RectList[i]->m_Frame->m_Rect.left + X - m_RectList[i]->m_Rect.left + m_RectList[i]->m_OffsetX) / (float)((float)m_RectList[i]->m_ZoomX / (float)100)); + int YY = (int)((m_RectList[i]->m_Frame->m_Rect.top + Y - m_RectList[i]->m_Rect.top + m_RectList[i]->m_OffsetY) / (float)((float)m_RectList[i]->m_ZoomY / (float)100)); + + if (m_RectList[i]->m_Frame->m_MirrorX) { + int Width = m_RectList[i]->m_Frame->m_Rect.right - m_RectList[i]->m_Frame->m_Rect.left; + XX = Width - XX; + } + + if (m_RectList[i]->m_Frame->m_MirrorY) { + int Height = m_RectList[i]->m_Frame->m_Rect.bottom - m_RectList[i]->m_Frame->m_Rect.top; + YY = Height - YY; + } + + if (!m_RectList[i]->m_Frame->m_Surface->IsTransparentAt(XX, YY)) return m_RectList[i]->m_Owner; + } + // region + else if (m_RectList[i]->m_Region) { + if (m_RectList[i]->m_Region->PointInRegion(X + m_RectList[i]->m_OffsetX, Y + m_RectList[i]->m_OffsetY)) return m_RectList[i]->m_Owner; + } + } else return m_RectList[i]->m_Owner; + } + } + + return (CBObject *)NULL; +} + + +////////////////////////////////////////////////////////////////////////// +void CBRenderer::DeleteRectList() { + for (int i = 0; i < m_RectList.GetSize(); i++) { + delete m_RectList[i]; + } + m_RectList.RemoveAll(); +} + + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////// +HRESULT CBRenderer::SwitchFullscreen() { + return E_FAIL; +} + +////////////////////////////////////////////////////////////////////// +HRESULT CBRenderer::Flip() { + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////// +HRESULT CBRenderer::InitRenderer(int width, int height, bool windowed) { + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////// +void CBRenderer::OnWindowChange() { +} + + +////////////////////////////////////////////////////////////////////// +HRESULT CBRenderer::Fill(byte r, byte g, byte b, RECT *rect) { + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRenderer::WindowedBlt() { + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRenderer::Setup2D(bool Force) { + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRenderer::SetupLines() { + return E_FAIL; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRenderer::DrawLine(int X1, int Y1, int X2, int Y2, uint32 Color) { + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRenderer::DrawRect(int X1, int Y1, int X2, int Y2, uint32 Color, int Width) { + for (int i = 0; i < Width; i++) { + DrawLine(X1 + i, Y1 + i, X2 - i, Y1 + i, Color); // up + DrawLine(X1 + i, Y2 - i, X2 - i + 1, Y2 - i, Color); // down + + DrawLine(X1 + i, Y1 + i, X1 + i, Y2 - i, Color); // left + DrawLine(X2 - i, Y1 + i, X2 - i, Y2 - i + 1, Color); // right + } + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRenderer::Fade(WORD Alpha) { + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRenderer::FadeToColor(uint32 Color, RECT *rect) { + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRenderer::SetViewport(int left, int top, int right, int bottom) { + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRenderer::SetScreenViewport() { + return SetViewport(m_DrawOffsetX, m_DrawOffsetY, m_Width + m_DrawOffsetX, m_Height + m_DrawOffsetY); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRenderer::SetViewport(RECT *Rect) { + return SetViewport(Rect->left + m_DrawOffsetX, + Rect->top + m_DrawOffsetY, + Rect->right + m_DrawOffsetX, + Rect->bottom + m_DrawOffsetY); +} + + +////////////////////////////////////////////////////////////////////////// +CBImage *CBRenderer::TakeScreenshot() { + return NULL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRenderer::ClipCursor() { + /* + if(!m_Windowed) + { + RECT rc; + GetWindowRect(m_Window, &rc); + + // if "maintain aspect ratio" is in effect, lock mouse to visible area + rc.left = m_DrawOffsetX; + rc.top = m_DrawOffsetY; + rc.right = rc.left + m_Width; + rc.bottom = rc.top + m_Height; + + ::ClipCursor(&rc); + } + */ + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBRenderer::UnclipCursor() { + /* + if(!m_Windowed) ::ClipCursor(NULL); + */ + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBRenderer::PointInViewport(POINT *P) { + if (P->x < m_DrawOffsetX) return false; + if (P->y < m_DrawOffsetY) return false; + if (P->x > m_DrawOffsetX + m_Width) return false; + if (P->y > m_DrawOffsetY + m_Height) return false; + + return true; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BRenderer.h b/engines/wintermute/BRenderer.h new file mode 100644 index 0000000000..c1180a5ef5 --- /dev/null +++ b/engines/wintermute/BRenderer.h @@ -0,0 +1,124 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BRENDERER_H +#define WINTERMUTE_BRENDERER_H + + +#include "coll_templ.h" +#include "BBase.h" + +namespace WinterMute { + +class CBImage; +class CBActiveRect; +class CBObject; + +class CBRenderer: public CBBase { +public: + int m_RealWidth; + int m_RealHeight; + int m_DrawOffsetX; + int m_DrawOffsetY; + + virtual void DumpData(char *Filename) {}; + virtual CBImage *TakeScreenshot(); + virtual HRESULT SetViewport(int left, int top, int right, int bottom); + virtual HRESULT SetViewport(RECT *Rect); + virtual HRESULT SetScreenViewport(); + virtual HRESULT Fade(WORD Alpha); + virtual HRESULT FadeToColor(uint32 Color, RECT *rect = NULL); + virtual HRESULT DrawLine(int X1, int Y1, int X2, int Y2, uint32 Color); + virtual HRESULT DrawRect(int X1, int Y1, int X2, int Y2, uint32 Color, int Width = 1); + CBRenderer(CBGame *inGame = NULL); + virtual ~CBRenderer(); + virtual HRESULT SetProjection() { + return S_OK; + }; + + virtual HRESULT WindowedBlt(); + virtual HRESULT Fill(byte r, byte g, byte b, RECT *rect = NULL); + virtual void OnWindowChange(); + virtual HRESULT InitRenderer(int width, int height, bool windowed); + virtual HRESULT Flip(); + virtual void InitLoop(); + virtual HRESULT SwitchFullscreen(); + virtual HRESULT Setup2D(bool Force = false); + virtual HRESULT SetupLines(); + + virtual const char *GetName() { + return ""; + }; + virtual HRESULT DisplayDebugInfo() { + return E_FAIL; + }; + virtual HRESULT DrawShaderQuad() { + return E_FAIL; + } + + virtual float GetScaleRatioX() const { + return 1.0f; + } + virtual float GetScaleRatioY() const { + return 1.0f; + } + + HRESULT ClipCursor(); + HRESULT UnclipCursor(); + + CBObject *GetObjectAt(int X, int Y); + void DeleteRectList(); + + virtual HRESULT StartSpriteBatch() { + return S_OK; + }; + virtual HRESULT EndSpriteBatch() { + return S_OK; + }; + bool PointInViewport(POINT *P); + uint32 m_ForceAlphaColor; + HINSTANCE m_Instance; + HWND m_Window; + HWND m_ClipperWindow; + bool m_Active; + bool m_Ready; + bool m_Windowed; + RECT m_WindowRect; + RECT m_ViewportRect; + RECT m_ScreenRect; + RECT m_MonitorRect; + int m_BPP; + int m_Height; + int m_Width; + + CBArray m_RectList; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BResourceFile.cpp b/engines/wintermute/BResourceFile.cpp new file mode 100644 index 0000000000..84811d0e73 --- /dev/null +++ b/engines/wintermute/BResourceFile.cpp @@ -0,0 +1,103 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BResourceFile.h" +#include "BResources.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CBResourceFile::CBResourceFile(CBGame *inGame): CBFile(inGame) { + m_Data = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +CBResourceFile::~CBResourceFile() { + Close(); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBResourceFile::Open(Common::String Filename) { + Close(); + + if (CBResources::GetFile(Filename.c_str(), m_Data, m_Size)) { + m_Pos = 0; + return S_OK; + } + return E_FAIL; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBResourceFile::Close() { + m_Data = NULL; + m_Pos = 0; + m_Size = 0; + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBResourceFile::Read(void *Buffer, uint32 Size) { + if (!m_Data || m_Pos + Size > m_Size) return E_FAIL; + + memcpy(Buffer, (byte *)m_Data + m_Pos, Size); + m_Pos += Size; + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBResourceFile::Seek(uint32 Pos, TSeek Origin) { + if (!m_Data) return E_FAIL; + + uint32 NewPos = 0; + + switch (Origin) { + case SEEK_TO_BEGIN: + NewPos = Pos; + break; + case SEEK_TO_END: + NewPos = m_Size + Pos; + break; + case SEEK_TO_CURRENT: + NewPos = m_Pos + Pos; + break; + } + + if (NewPos < 0 || NewPos > m_Size) return E_FAIL; + else m_Pos = NewPos; + + return S_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BResourceFile.h b/engines/wintermute/BResourceFile.h new file mode 100644 index 0000000000..4d995d674d --- /dev/null +++ b/engines/wintermute/BResourceFile.h @@ -0,0 +1,50 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BRESOURCEFILE_H +#define WINTERMUTE_BRESOURCEFILE_H + +#include "BFile.h" + +namespace WinterMute { + +class CBResourceFile : public CBFile { +public: + CBResourceFile(CBGame *inGame); + virtual ~CBResourceFile(); + virtual HRESULT Seek(uint32 Pos, TSeek Origin = SEEK_TO_BEGIN); + virtual HRESULT Read(void *Buffer, uint32 Size); + virtual HRESULT Close(); + virtual HRESULT Open(Common::String Filename); +private: + byte *m_Data; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BResources.cpp b/engines/wintermute/BResources.cpp new file mode 100644 index 0000000000..dceade0984 --- /dev/null +++ b/engines/wintermute/BResources.cpp @@ -0,0 +1,2830 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "PlatformSDL.h" +#include "BResources.h" +#include "common/str.h" + +namespace WinterMute { + +unsigned char invalid[] = { + 0x42, 0x4d, 0x36, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x04, 0x00, 0x00, 0x28, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x4e, 0x00, 0x00, 0x20, 0x4e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +} ; + +unsigned char invaliddebug[] = { + 0x42, 0x4d, 0x36, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x04, 0x00, 0x00, 0x28, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x80, + 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0x00, 0xc0, 0xdc, 0xc0, 0x00, 0xf0, 0xca, 0xa6, 0x00, 0x00, 0x20, + 0x40, 0x00, 0x00, 0x20, 0x60, 0x00, 0x00, 0x20, 0x80, 0x00, 0x00, 0x20, 0xa0, 0x00, 0x00, 0x20, + 0xc0, 0x00, 0x00, 0x20, 0xe0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00, 0x40, + 0x40, 0x00, 0x00, 0x40, 0x60, 0x00, 0x00, 0x40, 0x80, 0x00, 0x00, 0x40, 0xa0, 0x00, 0x00, 0x40, + 0xc0, 0x00, 0x00, 0x40, 0xe0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x20, 0x00, 0x00, 0x60, + 0x40, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x60, 0xa0, 0x00, 0x00, 0x60, + 0xc0, 0x00, 0x00, 0x60, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0x80, + 0x40, 0x00, 0x00, 0x80, 0x60, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xa0, 0x00, 0x00, 0x80, + 0xc0, 0x00, 0x00, 0x80, 0xe0, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0xa0, 0x20, 0x00, 0x00, 0xa0, + 0x40, 0x00, 0x00, 0xa0, 0x60, 0x00, 0x00, 0xa0, 0x80, 0x00, 0x00, 0xa0, 0xa0, 0x00, 0x00, 0xa0, + 0xc0, 0x00, 0x00, 0xa0, 0xe0, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x00, 0xc0, + 0x40, 0x00, 0x00, 0xc0, 0x60, 0x00, 0x00, 0xc0, 0x80, 0x00, 0x00, 0xc0, 0xa0, 0x00, 0x00, 0xc0, + 0xc0, 0x00, 0x00, 0xc0, 0xe0, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xe0, 0x20, 0x00, 0x00, 0xe0, + 0x40, 0x00, 0x00, 0xe0, 0x60, 0x00, 0x00, 0xe0, 0x80, 0x00, 0x00, 0xe0, 0xa0, 0x00, 0x00, 0xe0, + 0xc0, 0x00, 0x00, 0xe0, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x20, 0x00, 0x40, 0x00, + 0x40, 0x00, 0x40, 0x00, 0x60, 0x00, 0x40, 0x00, 0x80, 0x00, 0x40, 0x00, 0xa0, 0x00, 0x40, 0x00, + 0xc0, 0x00, 0x40, 0x00, 0xe0, 0x00, 0x40, 0x20, 0x00, 0x00, 0x40, 0x20, 0x20, 0x00, 0x40, 0x20, + 0x40, 0x00, 0x40, 0x20, 0x60, 0x00, 0x40, 0x20, 0x80, 0x00, 0x40, 0x20, 0xa0, 0x00, 0x40, 0x20, + 0xc0, 0x00, 0x40, 0x20, 0xe0, 0x00, 0x40, 0x40, 0x00, 0x00, 0x40, 0x40, 0x20, 0x00, 0x40, 0x40, + 0x40, 0x00, 0x40, 0x40, 0x60, 0x00, 0x40, 0x40, 0x80, 0x00, 0x40, 0x40, 0xa0, 0x00, 0x40, 0x40, + 0xc0, 0x00, 0x40, 0x40, 0xe0, 0x00, 0x40, 0x60, 0x00, 0x00, 0x40, 0x60, 0x20, 0x00, 0x40, 0x60, + 0x40, 0x00, 0x40, 0x60, 0x60, 0x00, 0x40, 0x60, 0x80, 0x00, 0x40, 0x60, 0xa0, 0x00, 0x40, 0x60, + 0xc0, 0x00, 0x40, 0x60, 0xe0, 0x00, 0x40, 0x80, 0x00, 0x00, 0x40, 0x80, 0x20, 0x00, 0x40, 0x80, + 0x40, 0x00, 0x40, 0x80, 0x60, 0x00, 0x40, 0x80, 0x80, 0x00, 0x40, 0x80, 0xa0, 0x00, 0x40, 0x80, + 0xc0, 0x00, 0x40, 0x80, 0xe0, 0x00, 0x40, 0xa0, 0x00, 0x00, 0x40, 0xa0, 0x20, 0x00, 0x40, 0xa0, + 0x40, 0x00, 0x40, 0xa0, 0x60, 0x00, 0x40, 0xa0, 0x80, 0x00, 0x40, 0xa0, 0xa0, 0x00, 0x40, 0xa0, + 0xc0, 0x00, 0x40, 0xa0, 0xe0, 0x00, 0x40, 0xc0, 0x00, 0x00, 0x40, 0xc0, 0x20, 0x00, 0x40, 0xc0, + 0x40, 0x00, 0x40, 0xc0, 0x60, 0x00, 0x40, 0xc0, 0x80, 0x00, 0x40, 0xc0, 0xa0, 0x00, 0x40, 0xc0, + 0xc0, 0x00, 0x40, 0xc0, 0xe0, 0x00, 0x40, 0xe0, 0x00, 0x00, 0x40, 0xe0, 0x20, 0x00, 0x40, 0xe0, + 0x40, 0x00, 0x40, 0xe0, 0x60, 0x00, 0x40, 0xe0, 0x80, 0x00, 0x40, 0xe0, 0xa0, 0x00, 0x40, 0xe0, + 0xc0, 0x00, 0x40, 0xe0, 0xe0, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x80, 0x00, + 0x40, 0x00, 0x80, 0x00, 0x60, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xa0, 0x00, 0x80, 0x00, + 0xc0, 0x00, 0x80, 0x00, 0xe0, 0x00, 0x80, 0x20, 0x00, 0x00, 0x80, 0x20, 0x20, 0x00, 0x80, 0x20, + 0x40, 0x00, 0x80, 0x20, 0x60, 0x00, 0x80, 0x20, 0x80, 0x00, 0x80, 0x20, 0xa0, 0x00, 0x80, 0x20, + 0xc0, 0x00, 0x80, 0x20, 0xe0, 0x00, 0x80, 0x40, 0x00, 0x00, 0x80, 0x40, 0x20, 0x00, 0x80, 0x40, + 0x40, 0x00, 0x80, 0x40, 0x60, 0x00, 0x80, 0x40, 0x80, 0x00, 0x80, 0x40, 0xa0, 0x00, 0x80, 0x40, + 0xc0, 0x00, 0x80, 0x40, 0xe0, 0x00, 0x80, 0x60, 0x00, 0x00, 0x80, 0x60, 0x20, 0x00, 0x80, 0x60, + 0x40, 0x00, 0x80, 0x60, 0x60, 0x00, 0x80, 0x60, 0x80, 0x00, 0x80, 0x60, 0xa0, 0x00, 0x80, 0x60, + 0xc0, 0x00, 0x80, 0x60, 0xe0, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x20, 0x00, 0x80, 0x80, + 0x40, 0x00, 0x80, 0x80, 0x60, 0x00, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0xa0, 0x00, 0x80, 0x80, + 0xc0, 0x00, 0x80, 0x80, 0xe0, 0x00, 0x80, 0xa0, 0x00, 0x00, 0x80, 0xa0, 0x20, 0x00, 0x80, 0xa0, + 0x40, 0x00, 0x80, 0xa0, 0x60, 0x00, 0x80, 0xa0, 0x80, 0x00, 0x80, 0xa0, 0xa0, 0x00, 0x80, 0xa0, + 0xc0, 0x00, 0x80, 0xa0, 0xe0, 0x00, 0x80, 0xc0, 0x00, 0x00, 0x80, 0xc0, 0x20, 0x00, 0x80, 0xc0, + 0x40, 0x00, 0x80, 0xc0, 0x60, 0x00, 0x80, 0xc0, 0x80, 0x00, 0x80, 0xc0, 0xa0, 0x00, 0x80, 0xc0, + 0xc0, 0x00, 0x80, 0xc0, 0xe0, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x80, 0xe0, 0x20, 0x00, 0x80, 0xe0, + 0x40, 0x00, 0x80, 0xe0, 0x60, 0x00, 0x80, 0xe0, 0x80, 0x00, 0x80, 0xe0, 0xa0, 0x00, 0x80, 0xe0, + 0xc0, 0x00, 0x80, 0xe0, 0xe0, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x20, 0x00, 0xc0, 0x00, + 0x40, 0x00, 0xc0, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x80, 0x00, 0xc0, 0x00, 0xa0, 0x00, 0xc0, 0x00, + 0xc0, 0x00, 0xc0, 0x00, 0xe0, 0x00, 0xc0, 0x20, 0x00, 0x00, 0xc0, 0x20, 0x20, 0x00, 0xc0, 0x20, + 0x40, 0x00, 0xc0, 0x20, 0x60, 0x00, 0xc0, 0x20, 0x80, 0x00, 0xc0, 0x20, 0xa0, 0x00, 0xc0, 0x20, + 0xc0, 0x00, 0xc0, 0x20, 0xe0, 0x00, 0xc0, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x20, 0x00, 0xc0, 0x40, + 0x40, 0x00, 0xc0, 0x40, 0x60, 0x00, 0xc0, 0x40, 0x80, 0x00, 0xc0, 0x40, 0xa0, 0x00, 0xc0, 0x40, + 0xc0, 0x00, 0xc0, 0x40, 0xe0, 0x00, 0xc0, 0x60, 0x00, 0x00, 0xc0, 0x60, 0x20, 0x00, 0xc0, 0x60, + 0x40, 0x00, 0xc0, 0x60, 0x60, 0x00, 0xc0, 0x60, 0x80, 0x00, 0xc0, 0x60, 0xa0, 0x00, 0xc0, 0x60, + 0xc0, 0x00, 0xc0, 0x60, 0xe0, 0x00, 0xc0, 0x80, 0x00, 0x00, 0xc0, 0x80, 0x20, 0x00, 0xc0, 0x80, + 0x40, 0x00, 0xc0, 0x80, 0x60, 0x00, 0xc0, 0x80, 0x80, 0x00, 0xc0, 0x80, 0xa0, 0x00, 0xc0, 0x80, + 0xc0, 0x00, 0xc0, 0x80, 0xe0, 0x00, 0xc0, 0xa0, 0x00, 0x00, 0xc0, 0xa0, 0x20, 0x00, 0xc0, 0xa0, + 0x40, 0x00, 0xc0, 0xa0, 0x60, 0x00, 0xc0, 0xa0, 0x80, 0x00, 0xc0, 0xa0, 0xa0, 0x00, 0xc0, 0xa0, + 0xc0, 0x00, 0xc0, 0xa0, 0xe0, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0x20, 0x00, 0xc0, 0xc0, + 0x40, 0x00, 0xc0, 0xc0, 0x60, 0x00, 0xc0, 0xc0, 0x80, 0x00, 0xc0, 0xc0, 0xa0, 0x00, 0xf0, 0xfb, + 0xff, 0x00, 0xa4, 0xa0, 0xa0, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, + 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, + 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, + 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, + 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, + 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0xf9, + 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, + 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0xf9, + 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, + 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, + 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, + 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, + 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, + 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, + 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0xf9, 0xf9, 0x00, + 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0xf9, + 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0xf9, + 0xf9, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0xf9, + 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, + 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, + 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, + 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, + 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, + 0xf9, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, + 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, + 0xf9, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, + 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, + 0xf9, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, + 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0xf9, + 0x00, 0x00, 0x00, 0xf9, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, + 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0xf9, + 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, + 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, + 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, + 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, + 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, + 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9 +} ; + +unsigned char systemfont[] = { + 0x42, 0x4d, 0x36, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x04, 0x00, 0x00, 0x28, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x70, 0x0b, 0x00, 0x00, 0x70, 0x0b, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x80, 0x80, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, + 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, + 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, + 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, + 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, + 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, + 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, + 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, + 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, + 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, + 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, + 0x00, 0x01, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, + 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, + 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, + 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, + 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, + 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x02, 0x01, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, + 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, + 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, + 0x00, 0x01, 0x01, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, + 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, + 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, + 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, + 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, + 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02, + 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, + 0x01, 0x02, 0x02, 0x01, 0x00, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, + 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x01, 0x02, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, + 0x02, 0x00, 0x01, 0x02, 0x01, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, + 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, + 0x02, 0x00, 0x01, 0x01, 0x00, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x00, 0x02, 0x00, 0x01, 0x02, 0x00, 0x02, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, + 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02, + 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, + 0x02, 0x01, 0x00, 0x02, 0x01, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x01, 0x02, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, + 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, + 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x00, 0x01, 0x01, 0x00, + 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, + 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, + 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, + 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x00, 0x01, 0x01, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, + 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00, + 0x00, 0x01, 0x02, 0x01, 0x02, 0x01, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, + 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, + 0x00, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x01, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x00, 0x01, 0x02, 0x00, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, + 0x02, 0x02, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x01, + 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x01, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, + 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, + 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, + 0x00, 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, + 0x00, 0x02, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, + 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, + 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, + 0x00, 0x01, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, + 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, + 0x00, 0x02, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, + 0x00, 0x02, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, + 0x02, 0x01, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, + 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, + 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, + 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02, + 0x00, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, + 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 +} ; + + +////////////////////////////////////////////////////////////////////////// +bool CBResources::GetFile(const char *fileName, byte*& buffer, uint32 &size) { + // better! + if (scumm_stricmp(fileName, "invalid.bmp") == 0) { + buffer = invalid; + size = sizeof(invalid); + return true; + } else if (scumm_stricmp(fileName, "invalid_debug.bmp") == 0) { + buffer = invaliddebug; + size = sizeof(invaliddebug); + return true; + } else if (scumm_stricmp(fileName, "system_font.bmp") == 0) { + buffer = systemfont; + size = sizeof(systemfont); + return true; + } + + + return false; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BResources.h b/engines/wintermute/BResources.h new file mode 100644 index 0000000000..ff8c050fa8 --- /dev/null +++ b/engines/wintermute/BResources.h @@ -0,0 +1,41 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BRESOURCES_H +#define WINTERMUTE_BRESOURCES_H + +namespace WinterMute { + +class CBResources { +public: + static bool GetFile(const char *fileName, byte*& buffer, uint32 &size); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BSaveThumbFile.cpp b/engines/wintermute/BSaveThumbFile.cpp new file mode 100644 index 0000000000..aeba924684 --- /dev/null +++ b/engines/wintermute/BSaveThumbFile.cpp @@ -0,0 +1,146 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BGame.h" +#include "BSaveThumbFile.h" +#include "PlatformSDL.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////// +CBSaveThumbFile::CBSaveThumbFile(CBGame *inGame): CBFile(inGame) { + m_Data = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +CBSaveThumbFile::~CBSaveThumbFile() { + Close(); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSaveThumbFile::Open(Common::String Filename) { + Close(); + + if (scumm_strnicmp(Filename.c_str(), "savegame:", 9) != 0) return E_FAIL; + + char *TempFilename = new char[strlen(Filename.c_str()) - 8]; + strcpy(TempFilename, Filename.c_str() + 9); + for (int i = 0; i < strlen(TempFilename); i++) { + if (TempFilename[i] < '0' || TempFilename[i] > '9') { + TempFilename[i] = '\0'; + break; + } + } + + // get slot number from name + int Slot = atoi(TempFilename); + delete [] TempFilename; + + char SlotFilename[MAX_PATH + 1]; + Game->GetSaveSlotFilename(Slot, SlotFilename); + CBPersistMgr *pm = new CBPersistMgr(Game); + if (!pm) return E_FAIL; + + Game->m_DEBUG_AbsolutePathWarning = false; + if (FAILED(pm->InitLoad(SlotFilename))) { + Game->m_DEBUG_AbsolutePathWarning = true; + delete pm; + return E_FAIL; + } + Game->m_DEBUG_AbsolutePathWarning = true; + + HRESULT res; + + if (pm->m_ThumbnailDataSize != 0) { + m_Data = new byte[pm->m_ThumbnailDataSize]; + memcpy(m_Data, pm->m_ThumbnailData, pm->m_ThumbnailDataSize); + m_Size = pm->m_ThumbnailDataSize; + res = S_OK; + } else res = E_FAIL; + delete pm; + + return res; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSaveThumbFile::Close() { + delete[] m_Data; + m_Data = NULL; + + m_Pos = 0; + m_Size = 0; + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSaveThumbFile::Read(void *Buffer, uint32 Size) { + if (!m_Data || m_Pos + Size > m_Size) return E_FAIL; + + memcpy(Buffer, (byte *)m_Data + m_Pos, Size); + m_Pos += Size; + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSaveThumbFile::Seek(uint32 Pos, TSeek Origin) { + if (!m_Data) return E_FAIL; + + uint32 NewPos = 0; + + switch (Origin) { + case SEEK_TO_BEGIN: + NewPos = Pos; + break; + case SEEK_TO_END: + NewPos = m_Size + Pos; + break; + case SEEK_TO_CURRENT: + NewPos = m_Pos + Pos; + break; + } + + if (NewPos < 0 || NewPos > m_Size) return E_FAIL; + else m_Pos = NewPos; + + return S_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BSaveThumbFile.h b/engines/wintermute/BSaveThumbFile.h new file mode 100644 index 0000000000..7c22eda237 --- /dev/null +++ b/engines/wintermute/BSaveThumbFile.h @@ -0,0 +1,51 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BSAVETHUMBFILE_H +#define WINTERMUTE_BSAVETHUMBFILE_H + + +#include "BFile.h" + +namespace WinterMute { + +class CBSaveThumbFile : public CBFile { +public: + CBSaveThumbFile(CBGame *Game); + virtual ~CBSaveThumbFile(); + virtual HRESULT Seek(uint32 Pos, TSeek Origin = SEEK_TO_BEGIN); + virtual HRESULT Read(void *Buffer, uint32 Size); + virtual HRESULT Close(); + virtual HRESULT Open(Common::String Filename); +private: + byte *m_Data; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BSaveThumbHelper.cpp b/engines/wintermute/BSaveThumbHelper.cpp new file mode 100644 index 0000000000..3342f7aa3a --- /dev/null +++ b/engines/wintermute/BSaveThumbHelper.cpp @@ -0,0 +1,79 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BSaveThumbHelper.h" +#include "BImage.h" +#include "BGame.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CBSaveThumbHelper::CBSaveThumbHelper(CBGame *inGame): CBBase(inGame) { + m_Thumbnail = NULL; +} + +////////////////////////////////////////////////////////////////////////// +CBSaveThumbHelper::~CBSaveThumbHelper(void) { + delete m_Thumbnail; + m_Thumbnail = NULL; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSaveThumbHelper::StoreThumbnail(bool DoFlip) { + delete m_Thumbnail; + m_Thumbnail = NULL; + + if (Game->m_ThumbnailWidth > 0 && Game->m_ThumbnailHeight > 0) { + if (DoFlip) { + // when using opengl on windows it seems to be necessary to do this twice + // works normally for direct3d + Game->DisplayContent(false); + Game->m_Renderer->Flip(); + + Game->DisplayContent(false); + Game->m_Renderer->Flip(); + } + + CBImage *Screenshot = Game->m_Renderer->TakeScreenshot(); + if (!Screenshot) return E_FAIL; + + // normal thumbnail + if (Game->m_ThumbnailWidth > 0 && Game->m_ThumbnailHeight > 0) { + m_Thumbnail = new CBImage(Game); + m_Thumbnail->CopyFrom(Screenshot, Game->m_ThumbnailWidth, Game->m_ThumbnailHeight); + } + + + delete Screenshot; + Screenshot = NULL; + } + return S_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BSaveThumbHelper.h b/engines/wintermute/BSaveThumbHelper.h new file mode 100644 index 0000000000..6c1e411f5f --- /dev/null +++ b/engines/wintermute/BSaveThumbHelper.h @@ -0,0 +1,50 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ +#ifndef WINTERMUTE_BSAVETHUMBHELPER_H +#define WINTERMUTE_BSAVETHUMBHELPER_H + + +#include "BBase.h" + +namespace WinterMute { + +class CBImage; + +class CBSaveThumbHelper : public CBBase { +public: + CBSaveThumbHelper(CBGame *inGame); + virtual ~CBSaveThumbHelper(void); + HRESULT StoreThumbnail(bool DoFlip = false); + + CBImage *m_Thumbnail; + CBImage *m_RichThumbnail; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BScriptHolder.cpp b/engines/wintermute/BScriptHolder.cpp new file mode 100644 index 0000000000..96ed14461c --- /dev/null +++ b/engines/wintermute/BScriptHolder.cpp @@ -0,0 +1,470 @@ +/* +This file is part of WME Lite. +http://dead-code.org/redir.php?target=wmelite + +Copyright (c) 2011 Jan Nedoma + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +#include "dcgf.h" +#include "AdGame.h" +#include "BScriptHolder.h" +#include "BParser.h" +#include "ScValue.h" +#include "ScEngine.h" +#include "ScScript.h" +#include "ScStack.h" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CBScriptHolder, false) + +////////////////////////////////////////////////////////////////////// +CBScriptHolder::CBScriptHolder(CBGame *inGame): CBScriptable(inGame) { + SetName(""); + + m_Freezable = true; + m_Filename = NULL; +} + + +////////////////////////////////////////////////////////////////////// +CBScriptHolder::~CBScriptHolder() { + Cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBScriptHolder::Cleanup() { + delete[] m_Filename; + m_Filename = NULL; + + int i; + + for (i = 0; i < m_Scripts.GetSize(); i++) { + m_Scripts[i]->Finish(true); + m_Scripts[i]->m_Owner = NULL; + } + m_Scripts.RemoveAll(); + + return S_OK; +} + +////////////////////////////////////////////////////////////////////// +void CBScriptHolder::SetFilename(char *Filename) { + if (m_Filename != NULL) delete [] m_Filename; + + m_Filename = new char [strlen(Filename) + 1]; + if (m_Filename != NULL) strcpy(m_Filename, Filename); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBScriptHolder::ApplyEvent(const char *EventName, bool Unbreakable) { + int NumHandlers = 0; + + HRESULT ret = E_FAIL; + for (int i = 0; i < m_Scripts.GetSize(); i++) { + if (!m_Scripts[i]->m_Thread) { + CScScript *handler = m_Scripts[i]->InvokeEventHandler(EventName, Unbreakable); + if (handler) { + //m_Scripts.Add(handler); + NumHandlers++; + ret = S_OK; + } + } + } + if (NumHandlers > 0 && Unbreakable) Game->m_ScEngine->TickUnbreakable(); + + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBScriptHolder::Listen(CBScriptHolder *param1, uint32 param2) { + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +HRESULT CBScriptHolder::ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name) { + ////////////////////////////////////////////////////////////////////////// + // DEBUG_CrashMe + ////////////////////////////////////////////////////////////////////////// + if (strcmp(Name, "DEBUG_CrashMe") == 0) { + Stack->CorrectParams(0); + byte *p = 0; + *p = 10; + Stack->PushNULL(); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ApplyEvent + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "ApplyEvent") == 0) { + Stack->CorrectParams(1); + CScValue *val = Stack->Pop(); + HRESULT ret; + ret = ApplyEvent(val->GetString()); + + if (SUCCEEDED(ret)) Stack->PushBool(true); + else Stack->PushBool(false); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // CanHandleEvent + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "CanHandleEvent") == 0) { + Stack->CorrectParams(1); + Stack->PushBool(CanHandleEvent(Stack->Pop()->GetString())); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // CanHandleMethod + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "CanHandleMethod") == 0) { + Stack->CorrectParams(1); + Stack->PushBool(CanHandleMethod(Stack->Pop()->GetString())); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // AttachScript + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "AttachScript") == 0) { + Stack->CorrectParams(1); + Stack->PushBool(SUCCEEDED(AddScript(Stack->Pop()->GetString()))); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // DetachScript + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "DetachScript") == 0) { + Stack->CorrectParams(2); + char *Filename = Stack->Pop()->GetString(); + bool KillThreads = Stack->Pop()->GetBool(false); + bool ret = false; + for (int i = 0; i < m_Scripts.GetSize(); i++) { + if (scumm_stricmp(m_Scripts[i]->m_Filename, Filename) == 0) { + m_Scripts[i]->Finish(KillThreads); + ret = true; + break; + } + } + Stack->PushBool(ret); + + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // IsScriptRunning + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "IsScriptRunning") == 0) { + Stack->CorrectParams(1); + char *Filename = Stack->Pop()->GetString(); + bool ret = false; + for (int i = 0; i < m_Scripts.GetSize(); i++) { + if (scumm_stricmp(m_Scripts[i]->m_Filename, Filename) == 0 && m_Scripts[i]->m_State != SCRIPT_FINISHED && m_Scripts[i]->m_State != SCRIPT_ERROR) { + ret = true; + break; + } + } + Stack->PushBool(ret); + + return S_OK; + } else return CBScriptable::ScCallMethod(Script, Stack, ThisStack, Name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CBScriptHolder::ScGetProperty(char *Name) { + m_ScValue->SetNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type + ////////////////////////////////////////////////////////////////////////// + if (strcmp(Name, "Type") == 0) { + m_ScValue->SetString("script_holder"); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Name + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Name") == 0) { + m_ScValue->SetString(m_Name); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Filename (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Filename") == 0) { + m_ScValue->SetString(m_Filename); + return m_ScValue; + } + + else return CBScriptable::ScGetProperty(Name); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBScriptHolder::ScSetProperty(char *Name, CScValue *Value) { + ////////////////////////////////////////////////////////////////////////// + // Name + ////////////////////////////////////////////////////////////////////////// + if (strcmp(Name, "Name") == 0) { + SetName(Value->GetString()); + return S_OK; + } else return CBScriptable::ScSetProperty(Name, Value); +} + + +////////////////////////////////////////////////////////////////////////// +char *CBScriptHolder::ScToString() { + return "[script_holder]"; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBScriptHolder::SaveAsText(CBDynBuffer *Buffer, int Indent) { + return CBBase::SaveAsText(Buffer, Indent); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBScriptHolder::Persist(CBPersistMgr *PersistMgr) { + CBScriptable::Persist(PersistMgr); + + PersistMgr->Transfer(TMEMBER(m_Filename)); + PersistMgr->Transfer(TMEMBER(m_Freezable)); + PersistMgr->Transfer(TMEMBER(m_Name)); + m_Scripts.Persist(PersistMgr); + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBScriptHolder::AddScript(char *Filename) { + for (int i = 0; i < m_Scripts.GetSize(); i++) { + if (scumm_stricmp(m_Scripts[i]->m_Filename, Filename) == 0) { + if (m_Scripts[i]->m_State != SCRIPT_FINISHED) { + Game->LOG(0, "CBScriptHolder::AddScript - trying to add script '%s' mutiple times (obj: '%s')", Filename, m_Name); + return S_OK; + } + } + } + + CScScript *scr = Game->m_ScEngine->RunScript(Filename, this); + if (!scr) { + if (Game->m_EditorForceScripts) { + // editor hack + scr = new CScScript(Game, Game->m_ScEngine); + scr->m_Filename = new char[strlen(Filename) + 1]; + strcpy(scr->m_Filename, Filename); + scr->m_State = SCRIPT_ERROR; + scr->m_Owner = this; + m_Scripts.Add(scr); + Game->m_ScEngine->m_Scripts.Add(scr); + Game->GetDebugMgr()->OnScriptInit(scr); + + return S_OK; + } + return E_FAIL; + } else { + scr->m_Freezable = m_Freezable; + m_Scripts.Add(scr); + return S_OK; + } +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBScriptHolder::RemoveScript(CScScript *Script) { + for (int i = 0; i < m_Scripts.GetSize(); i++) { + if (m_Scripts[i] == Script) { + m_Scripts.RemoveAt(i); + break; + } + } + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBScriptHolder::CanHandleEvent(char *EventName) { + for (int i = 0; i < m_Scripts.GetSize(); i++) { + if (!m_Scripts[i]->m_Thread && m_Scripts[i]->CanHandleEvent(EventName)) return true; + } + return false; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBScriptHolder::CanHandleMethod(char *MethodName) { + for (int i = 0; i < m_Scripts.GetSize(); i++) { + if (!m_Scripts[i]->m_Thread && m_Scripts[i]->CanHandleMethod(MethodName)) return true; + } + return false; +} + + +TOKEN_DEF_START +TOKEN_DEF(PROPERTY) +TOKEN_DEF(NAME) +TOKEN_DEF(VALUE) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +HRESULT CBScriptHolder::ParseProperty(byte *Buffer, bool Complete) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(PROPERTY) + TOKEN_TABLE(NAME) + TOKEN_TABLE(VALUE) + TOKEN_TABLE_END + + byte *params; + int cmd; + CBParser parser(Game); + + if (Complete) { + if (parser.GetCommand((char **)&Buffer, commands, (char **)¶ms) != TOKEN_PROPERTY) { + Game->LOG(0, "'PROPERTY' keyword expected."); + return E_FAIL; + } + Buffer = params; + } + + char *PropName = NULL; + char *PropValue = NULL; + + while ((cmd = parser.GetCommand((char **)&Buffer, commands, (char **)¶ms)) > 0) { + switch (cmd) { + case TOKEN_NAME: + delete[] PropName; + PropName = new char[strlen((char *)params) + 1]; + if (PropName) strcpy(PropName, (char *)params); + else cmd = PARSERR_GENERIC; + break; + + case TOKEN_VALUE: + delete[] PropValue; + PropValue = new char[strlen((char *)params) + 1]; + if (PropValue) strcpy(PropValue, (char *)params); + else cmd = PARSERR_GENERIC; + break; + } + + } + if (cmd == PARSERR_TOKENNOTFOUND) { + delete[] PropName; + delete[] PropValue; + PropName = NULL; + PropValue = NULL; + Game->LOG(0, "Syntax error in PROPERTY definition"); + return E_FAIL; + } + if (cmd == PARSERR_GENERIC || PropName == NULL || PropValue == NULL) { + delete[] PropName; + delete[] PropValue; + PropName = NULL; + PropValue = NULL; + Game->LOG(0, "Error loading PROPERTY definition"); + return E_FAIL; + } + + + CScValue *val = new CScValue(Game); + val->SetString(PropValue); + ScSetProperty(PropName, val); + + delete val; + delete[] PropName; + delete[] PropValue; + PropName = NULL; + PropValue = NULL; + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void CBScriptHolder::MakeFreezable(bool Freezable) { + m_Freezable = Freezable; + for (int i = 0; i < m_Scripts.GetSize(); i++) + m_Scripts[i]->m_Freezable = Freezable; + +} + + +////////////////////////////////////////////////////////////////////////// +CScScript *CBScriptHolder::InvokeMethodThread(char *MethodName) { + for (int i = m_Scripts.GetSize() - 1; i >= 0; i--) { + if (m_Scripts[i]->CanHandleMethod(MethodName)) { + + CScScript *thread = new CScScript(Game, m_Scripts[i]->m_Engine); + if (thread) { + HRESULT ret = thread->CreateMethodThread(m_Scripts[i], MethodName); + if (SUCCEEDED(ret)) { + m_Scripts[i]->m_Engine->m_Scripts.Add(thread); + Game->GetDebugMgr()->OnScriptMethodThreadInit(thread, m_Scripts[i], MethodName); + + return thread; + } else { + delete thread; + } + } + } + } + return NULL; +} + + +////////////////////////////////////////////////////////////////////////// +void CBScriptHolder::ScDebuggerDesc(char *Buf, int BufSize) { + strcpy(Buf, ScToString()); + if (m_Name && strcmp(m_Name, "") != 0) { + strcat(Buf, " Name: "); + strcat(Buf, m_Name); + } + if (m_Filename) { + strcat(Buf, " File: "); + strcat(Buf, m_Filename); + } +} + + +////////////////////////////////////////////////////////////////////////// +// IWmeObject +////////////////////////////////////////////////////////////////////////// +bool CBScriptHolder::SendEvent(const char *EventName) { + return SUCCEEDED(ApplyEvent((char *)EventName)); +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BSound.cpp b/engines/wintermute/BSound.cpp new file mode 100644 index 0000000000..b6261f8117 --- /dev/null +++ b/engines/wintermute/BSound.cpp @@ -0,0 +1,266 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "BSound.h" +#include "BGame.h" +#include "BSoundMgr.h" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CBSound, false) + +////////////////////////////////////////////////////////////////////////// +CBSound::CBSound(CBGame *inGame): CBBase(inGame) { + m_Sound = NULL; + m_SoundFilename = NULL; + + m_SoundType = SOUND_SFX; + m_SoundStreamed = false; + m_SoundLooping = false; + m_SoundPlaying = false; + m_SoundPaused = false; + m_SoundFreezePaused = false; + m_SoundPosition = 0; + m_SoundPrivateVolume = 0; + m_SoundLoopStart = 0; + + m_SFXType = SFX_NONE; + m_SFXParam1 = m_SFXParam2 = m_SFXParam3 = m_SFXParam4 = 0; +} + + +////////////////////////////////////////////////////////////////////////// +CBSound::~CBSound() { + if (m_Sound) Game->m_SoundMgr->RemoveSound(m_Sound); + m_Sound = NULL; + + delete[] m_SoundFilename; + m_SoundFilename = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSound::SetSound(char *Filename, TSoundType Type, bool Streamed) { + if (m_Sound) { + Game->m_SoundMgr->RemoveSound(m_Sound); + m_Sound = NULL; + } + delete[] m_SoundFilename; + m_SoundFilename = NULL; + + m_Sound = Game->m_SoundMgr->AddSound(Filename, Type, Streamed); + if (m_Sound) { + m_SoundFilename = new char[strlen(Filename) + 1]; + strcpy(m_SoundFilename, Filename); + + m_SoundType = Type; + m_SoundStreamed = Streamed; + + return S_OK; + } else return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSound::SetSoundSimple() { + m_Sound = Game->m_SoundMgr->AddSound(m_SoundFilename, m_SoundType, m_SoundStreamed); + if (m_Sound) { + if (m_SoundPosition) m_Sound->SetPosition(m_SoundPosition); + m_Sound->SetLooping(m_SoundLooping); + m_Sound->SetPrivateVolume(m_SoundPrivateVolume); + m_Sound->SetLoopStart(m_SoundLoopStart); + m_Sound->m_FreezePaused = m_SoundFreezePaused; + if (m_SoundPlaying) return m_Sound->Resume(); + else return S_OK; + } else return E_FAIL; +} + + + +////////////////////////////////////////////////////////////////////////// +uint32 CBSound::GetLength() { + if (m_Sound) return m_Sound->GetLength(); + else return 0; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSound::Play(bool Looping) { + if (m_Sound) { + m_SoundPaused = false; + return m_Sound->Play(Looping, m_SoundPosition); + } else return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSound::Stop() { + if (m_Sound) { + m_SoundPaused = false; + return m_Sound->Stop(); + } else return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSound::Pause(bool FreezePaused) { + if (m_Sound) { + m_SoundPaused = true; + if (FreezePaused) m_Sound->m_FreezePaused = true; + return m_Sound->Pause(); + } else return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSound::Resume() { + if (m_Sound && m_SoundPaused) { + m_SoundPaused = false; + return m_Sound->Resume(); + } else return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSound::Persist(CBPersistMgr *PersistMgr) { + if (PersistMgr->m_Saving && m_Sound) { + m_SoundPlaying = m_Sound->IsPlaying(); + m_SoundLooping = m_Sound->m_Looping; + m_SoundPrivateVolume = m_Sound->m_PrivateVolume; + if (m_SoundPlaying) m_SoundPosition = m_Sound->GetPosition(); + m_SoundLoopStart = m_Sound->m_LoopStart; + m_SoundFreezePaused = m_Sound->m_FreezePaused; + } + + if (PersistMgr->m_Saving) { + m_SFXType = SFX_NONE; + m_SFXParam1 = m_SFXParam2 = m_SFXParam3 = m_SFXParam4 = 0; + } + + PersistMgr->Transfer(TMEMBER(Game)); + + PersistMgr->Transfer(TMEMBER(m_SoundFilename)); + PersistMgr->Transfer(TMEMBER(m_SoundLooping)); + PersistMgr->Transfer(TMEMBER(m_SoundPaused)); + PersistMgr->Transfer(TMEMBER(m_SoundFreezePaused)); + PersistMgr->Transfer(TMEMBER(m_SoundPlaying)); + PersistMgr->Transfer(TMEMBER(m_SoundPosition)); + PersistMgr->Transfer(TMEMBER(m_SoundPrivateVolume)); + PersistMgr->Transfer(TMEMBER(m_SoundStreamed)); + PersistMgr->Transfer(TMEMBER_INT(m_SoundType)); + PersistMgr->Transfer(TMEMBER(m_SoundLoopStart)); + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSound::IsPlaying() { + return m_Sound && m_Sound->IsPlaying(); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSound::IsPaused() { + return m_Sound && m_SoundPaused; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSound::SetPositionTime(uint32 Time) { + if (!m_Sound) return E_FAIL; + m_SoundPosition = Time; + HRESULT ret = m_Sound->SetPosition(m_SoundPosition); + if (m_Sound->IsPlaying()) m_SoundPosition = 0; + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +uint32 CBSound::GetPositionTime() { + if (!m_Sound) return 0; + + if (!m_Sound->IsPlaying()) return 0; + else return m_Sound->GetPosition(); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSound::SetVolume(int Volume) { + if (!m_Sound) return E_FAIL; + else return m_Sound->SetPrivateVolume(Volume); +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSound::SetPrivateVolume(int Volume) { + if (!m_Sound) return E_FAIL; + else return m_Sound->m_PrivateVolume = Volume; +} + + +////////////////////////////////////////////////////////////////////////// +int CBSound::GetVolume() { + if (!m_Sound) return 0; + else return m_Sound->m_PrivateVolume; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSound::SetLoopStart(uint32 Pos) { + if (!m_Sound) return E_FAIL; + else { + m_Sound->SetLoopStart(Pos); + return S_OK; + } +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSound::SetPan(float Pan) { + if (m_Sound) return m_Sound->SetPan(Pan); + else return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSound::ApplyFX(TSFXType Type, float Param1, float Param2, float Param3, float Param4) { + if (!m_Sound) return S_OK; + + if (Type != m_SFXType || Param1 != m_SFXParam1 || Param2 != m_SFXParam2 || Param3 != m_SFXParam3 || Param4 != m_SFXParam4) { + HRESULT Ret = m_Sound->ApplyFX(Type, Param1, Param2, Param3, Param4); + + m_SFXType = Type; + m_SFXParam1 = Param1; + m_SFXParam2 = Param2; + m_SFXParam3 = Param3; + m_SFXParam4 = Param4; + + return Ret; + } + return S_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BSound.h b/engines/wintermute/BSound.h new file mode 100644 index 0000000000..0320030c72 --- /dev/null +++ b/engines/wintermute/BSound.h @@ -0,0 +1,85 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BSOUND_H +#define WINTERMUTE_BSOUND_H + +#include "BBase.h" +#include "dctypes.h" // Added by ClassView +#include "BSoundBuffer.h" +#include "persistent.h" + +namespace WinterMute { + +class CBSound : public CBBase { +public: + HRESULT SetPan(float Pan); + int m_SoundPrivateVolume; + int GetVolume(); + HRESULT SetVolume(int Volume); + HRESULT SetPrivateVolume(int Volume); + HRESULT SetLoopStart(uint32 Pos); + uint32 GetPositionTime(); + HRESULT SetPositionTime(uint32 Time); + bool m_SoundPaused; + bool m_SoundFreezePaused; + bool IsPlaying(); + bool IsPaused(); + bool m_SoundPlaying; + bool m_SoundLooping; + uint32 m_SoundLoopStart; + uint32 m_SoundPosition; + DECLARE_PERSISTENT(CBSound, CBBase) + HRESULT Resume(); + HRESULT Pause(bool FreezePaused = false); + HRESULT Stop(); + HRESULT Play(bool Looping = false); + uint32 GetLength(); + bool m_SoundStreamed; + TSoundType m_SoundType; + char *m_SoundFilename; + HRESULT SetSoundSimple(); + HRESULT SetSound(char *Filename, TSoundType Type = SOUND_SFX, bool Streamed = false); + CBSound(CBGame *inGame); + virtual ~CBSound(); + + HRESULT ApplyFX(TSFXType Type = SFX_NONE, float Param1 = 0, float Param2 = 0, float Param3 = 0, float Param4 = 0); + +private: + TSFXType m_SFXType; + float m_SFXParam1; + float m_SFXParam2; + float m_SFXParam3; + float m_SFXParam4; + CBSoundBuffer *m_Sound; + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BSoundBuffer.cpp b/engines/wintermute/BSoundBuffer.cpp new file mode 100644 index 0000000000..48c63bf4d9 --- /dev/null +++ b/engines/wintermute/BSoundBuffer.cpp @@ -0,0 +1,384 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BFile.h" +#include "BGame.h" +#include "BSoundMgr.h" +#include "BSoundBuffer.h" +#include "BFileManager.h" +#include "utils.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +#define MAX_NONSTREAMED_FILE_SIZE 1024*1024 + +////////////////////////////////////////////////////////////////////////// +CBSoundBuffer::CBSoundBuffer(CBGame *inGame): CBBase(inGame) { +#if 0 + m_Stream = NULL; + m_Sync = NULL; + + m_Streamed = false; + m_Filename = NULL; + m_File = NULL; + m_PrivateVolume = 100; + + m_Looping = false; + m_LoopStart = 0; + + m_Type = SOUND_SFX; + + m_FreezePaused = false; +#endif +} + + +////////////////////////////////////////////////////////////////////////// +CBSoundBuffer::~CBSoundBuffer() { +#if 0 + Stop(); + + if (m_Stream) { + BASS_StreamFree(m_Stream); + m_Stream = NULL; + } + + if (m_File) { + Game->m_FileManager->CloseFile(m_File); + m_File = NULL; + } + + SAFE_DELETE_ARRAY(m_Filename); +#endif +} + + +////////////////////////////////////////////////////////////////////////// +void CBSoundBuffer::SetStreaming(bool Streamed, uint32 NumBlocks, uint32 BlockSize) { + m_Streamed = Streamed; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSoundBuffer::LoadFromFile(const char *Filename, bool ForceReload) { +#if 0 + if (m_Stream) { + BASS_StreamFree(m_Stream); + m_Stream = NULL; + } + + if (m_File) Game->m_FileManager->CloseFile(m_File); + + m_File = Game->m_FileManager->OpenFile(Filename); + if (!m_File) { + Game->LOG(0, "Error opening sound file '%s'", Filename); + return E_FAIL; + } + + BASS_FILEPROCS fileProc; + fileProc.close = CBSoundBuffer::FileCloseProc; + fileProc.read = CBSoundBuffer::FileReadProc; + fileProc.seek = CBSoundBuffer::FileSeekProc; + fileProc.length = CBSoundBuffer::FileLenProc; + + m_Stream = BASS_StreamCreateFileUser(STREAMFILE_NOBUFFER, 0, &fileProc, (void *)m_File); + if (!m_Stream) { + Game->LOG(0, "BASS error: %d while loading '%s'", BASS_ErrorGetCode(), Filename); + return E_FAIL; + } + + CBUtils::SetString(&m_Filename, Filename); + + /* + HRESULT res; + bool NewlyCreated = false; + + if(!m_SoundBuffer || ForceReload || m_Streamed){ + if(!m_File) m_File = Game->m_FileManager->OpenFile(Filename); + if(!m_File){ + Game->LOG(0, "Error opening sound file '%s'", Filename); + return E_FAIL; + } + // switch to streamed for big files + if(!m_Streamed && (m_File->GetSize() > MAX_NONSTREAMED_FILE_SIZE && !Game->m_ForceNonStreamedSounds)) SetStreaming(true); + } + + // create buffer + if(!m_SoundBuffer){ + NewlyCreated = true; + + res = InitializeBuffer(m_File); + if(FAILED(res)){ + Game->LOG(res, "Error creating sound buffer for file '%s'", Filename); + return res; + } + } + + + + // store filename + if(!m_Filename){ + m_Filename = new char[strlen(Filename)+1]; + strcpy(m_Filename, Filename); + } + + // close file (if not streaming) + if(!m_Streamed && m_File){ + Game->m_FileManager->CloseFile(m_File); + m_File = NULL; + } + */ + + return S_OK; +#endif +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSoundBuffer::Play(bool Looping, uint32 StartSample) { +#if 0 + if (m_Stream) { + SetLooping(Looping); + BASS_ChannelPlay(m_Stream, TRUE); + } + return S_OK; +#endif +} + +////////////////////////////////////////////////////////////////////////// +void CBSoundBuffer::SetLooping(bool looping) { +#if 0 + m_Looping = looping; + + if (m_Stream) { + BASS_ChannelFlags(m_Stream, looping ? BASS_SAMPLE_LOOP : 0, BASS_SAMPLE_LOOP); + } +#endif +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSoundBuffer::Resume() { +#if 0 + if (m_Stream) { + BASS_ChannelPlay(m_Stream, FALSE); + } + return S_OK; +#endif +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSoundBuffer::Stop() { +#if 0 + if (m_Stream) { + BASS_ChannelStop(m_Stream); + } +#endif + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSoundBuffer::Pause() { +#if 0 + if (m_Stream) { + BASS_ChannelPause(m_Stream); + } +#endif + return S_OK; + +} + +////////////////////////////////////////////////////////////////////////// +uint32 CBSoundBuffer::GetLength() { +#if 0 + QWORD len = BASS_ChannelGetLength(m_Stream, BASS_POS_BYTE); + return 1000 * BASS_ChannelBytes2Seconds(m_Stream, len); +#endif +} + + +////////////////////////////////////////////////////////////////////////// +void CBSoundBuffer::SetType(TSoundType Type) { + m_Type = Type; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSoundBuffer::SetVolume(int Volume) { +#if 0 + if (m_Stream) { + BASS_ChannelSetAttribute(m_Stream, BASS_ATTRIB_VOL, (float)Volume / 100.0f); + } +#endif + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSoundBuffer::SetPrivateVolume(int Volume) { +#if 0 + m_PrivateVolume = Volume; + + switch (m_Type) { + case SOUND_SFX: + Volume = Game->m_SoundMgr->m_VolumeSFX; + break; + case SOUND_SPEECH: + Volume = Game->m_SoundMgr->m_VolumeSpeech; + break; + case SOUND_MUSIC: + Volume = Game->m_SoundMgr->m_VolumeMusic; + break; + } +#endif + return SetVolume(Volume); +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSoundBuffer::IsPlaying() { +#if 0 + return m_FreezePaused || BASS_ChannelIsActive(m_Stream) == BASS_ACTIVE_PLAYING; +#endif + return false; +} + + +////////////////////////////////////////////////////////////////////////// +uint32 CBSoundBuffer::GetPosition() { +#if 0 + if (m_Stream) { + QWORD len = BASS_ChannelGetPosition(m_Stream, BASS_POS_BYTE); + return 1000 * BASS_ChannelBytes2Seconds(m_Stream, len); + } else return 0; +#endif + return 0; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSoundBuffer::SetPosition(uint32 Pos) { +#if 0 + if (m_Stream) { + QWORD pos = BASS_ChannelSeconds2Bytes(m_Stream, (float)Pos / 1000.0f); + BASS_ChannelSetPosition(m_Stream, pos, BASS_POS_BYTE); + } +#endif + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSoundBuffer::SetLoopStart(uint32 Pos) { + m_LoopStart = Pos; +#if 0 + if (m_Stream) { + if (m_Sync) { + BASS_ChannelRemoveSync(m_Stream, m_Sync); + m_Sync = NULL; + } + if (m_LoopStart > 0) { + QWORD len = BASS_ChannelGetLength(m_Stream, BASS_POS_BYTE); + m_Sync = BASS_ChannelSetSync(m_Stream, BASS_SYNC_POS | BASS_SYNC_MIXTIME, len, CBSoundBuffer::LoopSyncProc, (void *)this); + } + } +#endif + return S_OK; +} +#if 0 +////////////////////////////////////////////////////////////////////////// +void CBSoundBuffer::LoopSyncProc(HSYNC handle, uint32 channel, uint32 data, void *user) { + CBSoundBuffer *soundBuf = static_cast(user); + QWORD pos = BASS_ChannelSeconds2Bytes(channel, (float)soundBuf->GetLoopStart() / 1000.0f); + + if (!BASS_ChannelSetPosition(channel, pos, BASS_POS_BYTE)) + BASS_ChannelSetPosition(channel, 0, BASS_POS_BYTE); +} +#endif +////////////////////////////////////////////////////////////////////////// +HRESULT CBSoundBuffer::SetPan(float Pan) { +#if 0 + if (m_Stream) { + BASS_ChannelSetAttribute(m_Stream, BASS_ATTRIB_PAN, Pan); + } +#endif + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSoundBuffer::ApplyFX(TSFXType Type, float Param1, float Param2, float Param3, float Param4) { +#if 0 + switch (Type) { + case SFX_ECHO: + break; + + case SFX_REVERB: + break; + + default: + break; + } +#endif + return S_OK; +} + +#if 0 +////////////////////////////////////////////////////////////////////////// +void CBSoundBuffer::FileCloseProc(void *user) { + /* + CBFile* file = static_cast(user); + file->Game->m_FileManager->CloseFile(file); + */ +} + +////////////////////////////////////////////////////////////////////////// +QWORD CBSoundBuffer::FileLenProc(void *user) { + CBFile *file = static_cast(user); + return file->GetSize(); +} + +////////////////////////////////////////////////////////////////////////// +uint32 CBSoundBuffer::FileReadProc(void *buffer, uint32 length, void *user) { + CBFile *file = static_cast(user); + uint32 oldPos = file->GetPos(); + file->Read(buffer, length); + return file->GetPos() - oldPos; +} + +////////////////////////////////////////////////////////////////////////// +BOOL CBSoundBuffer::FileSeekProc(QWORD offset, void *user) { + CBFile *file = static_cast(user); + return SUCCEEDED(file->Seek(offset)); +} +#endif +} // end of namespace WinterMute diff --git a/engines/wintermute/BSoundBuffer.h b/engines/wintermute/BSoundBuffer.h new file mode 100644 index 0000000000..4571612122 --- /dev/null +++ b/engines/wintermute/BSoundBuffer.h @@ -0,0 +1,95 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BSOUNDBUFFER_H +#define WINTERMUTE_BSOUNDBUFFER_H + + +#include "BBase.h" +//#include "bass.h" + +namespace WinterMute { + +class CBFile; +class CBSoundBuffer : public CBBase { +public: + + CBSoundBuffer(CBGame *inGame); + virtual ~CBSoundBuffer(); + + + HRESULT Pause(); + HRESULT Play(bool Looping = false, uint32 StartSample = 0); + HRESULT Resume(); + HRESULT Stop(); + bool IsPlaying(); + + void SetLooping(bool looping); + + uint32 GetPosition(); + HRESULT SetPosition(uint32 Pos); + uint32 GetLength(); + + HRESULT SetLoopStart(uint32 Pos); + uint32 GetLoopStart() const { + return m_LoopStart; + } + + HRESULT SetPan(float Pan); + HRESULT SetPrivateVolume(int Volume); + HRESULT SetVolume(int Volume); + + void SetType(TSoundType Type); + + HRESULT LoadFromFile(const char *Filename, bool ForceReload = false); + void SetStreaming(bool Streamed, uint32 NumBlocks = 0, uint32 BlockSize = 0); + HRESULT ApplyFX(TSFXType Type, float Param1, float Param2, float Param3, float Param4); + + //HSTREAM m_Stream; + //HSYNC m_Sync; + + bool m_FreezePaused; + uint32 m_LoopStart; + TSoundType m_Type; + bool m_Looping; + CBFile *m_File; + char *m_Filename; + bool m_Streamed; + int m_PrivateVolume; + + /*static void CALLBACK LoopSyncProc(HSYNC handle, uint32 channel, uint32 data, void *user); + + static void CALLBACK FileCloseProc(void *user); + static QWORD CALLBACK FileLenProc(void *user); + static uint32 CALLBACK FileReadProc(void *buffer, uint32 length, void *user); + static BOOL CALLBACK FileSeekProc(QWORD offset, void *user);*/ +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BSoundMgr.cpp b/engines/wintermute/BSoundMgr.cpp new file mode 100644 index 0000000000..894a586ee4 --- /dev/null +++ b/engines/wintermute/BSoundMgr.cpp @@ -0,0 +1,330 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BSoundMgr.h" +#include "BRegistry.h" +#include "PathUtil.h" +#include "StringUtil.h" +#include "BGame.h" +#include "BFileManager.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +//IMPLEMENT_PERSISTENT(CBSoundMgr, true); + +////////////////////////////////////////////////////////////////////////// +CBSoundMgr::CBSoundMgr(CBGame *inGame): CBBase(inGame) { + m_SoundAvailable = false; + + m_VolumeSFX = m_VolumeSpeech = m_VolumeMusic = m_VolumeMaster = 100; +} + + +////////////////////////////////////////////////////////////////////////// +CBSoundMgr::~CBSoundMgr() { + SaveSettings(); + Cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSoundMgr::Cleanup() { +#if 0 + for (int i = 0; i < m_Sounds.GetSize(); i++) delete m_Sounds[i]; + m_Sounds.RemoveAll(); + + BASS_Free(); +#endif + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +void CBSoundMgr::SaveSettings() { + if (m_SoundAvailable) { + Game->m_Registry->WriteInt("Audio", "MasterVolume", m_VolumeMaster); + + Game->m_Registry->WriteInt("Audio", "SFXVolume", m_VolumeSFX); + Game->m_Registry->WriteInt("Audio", "SpeechVolume", m_VolumeSpeech); + Game->m_Registry->WriteInt("Audio", "MusicVolume", m_VolumeMusic); + } +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSoundMgr::Initialize() { + m_SoundAvailable = false; +#if 0 + +#ifdef __IPHONEOS__ +#define BASS_CONFIG_IOS_MIXAUDIO 34 + BASS_SetConfig(BASS_CONFIG_IOS_MIXAUDIO, 0); +#endif + + + if (HIWORD(BASS_GetVersion()) != BASSVERSION) { + Game->LOG(0, "An incorrect version of BASS was loaded"); + return E_FAIL; + } + + if (!BASS_Init(-1, 44100, 0, 0, NULL)) { + Game->LOG(0, "Can't initialize sound device"); + return E_FAIL; + } +#endif + + m_VolumeMaster = Game->m_Registry->ReadInt("Audio", "MasterVolume", 100); + + m_VolumeSFX = Game->m_Registry->ReadInt("Audio", "SFXVolume", 100); + m_VolumeSpeech = Game->m_Registry->ReadInt("Audio", "SpeechVolume", 100); + m_VolumeMusic = Game->m_Registry->ReadInt("Audio", "MusicVolume", 100); + +#if 0 + m_SoundAvailable = true; + SetMasterVolumePercent(m_VolumeMaster); +#endif + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSoundMgr::InitLoop() { + if (!m_SoundAvailable) return S_OK; +#if 0 + + BASS_Update(500); +#endif + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +CBSoundBuffer *CBSoundMgr::AddSound(const char *Filename, TSoundType Type, bool Streamed) { + if (!m_SoundAvailable) return NULL; +#if 0 + + CBSoundBuffer *sound; + + // try to switch WAV to OGG file (if available) + AnsiString ext = PathUtil::GetExtension(Filename); + if (StringUtil::CompareNoCase(ext, ".wav")) { + AnsiString path = PathUtil::GetDirectoryName(Filename); + AnsiString name = PathUtil::GetFileNameWithoutExtension(Filename); + + AnsiString newFile = PathUtil::Combine(path, name + ".ogg"); + CBFile *file = Game->m_FileManager->OpenFile(newFile.c_str()); + if (file) { + Filename = newFile.c_str(); + Game->m_FileManager->CloseFile(file); + } + } + + sound = new CBSoundBuffer(Game); + if (!sound) return NULL; + + sound->SetStreaming(Streamed); + sound->SetType(Type); + + + HRESULT res = sound->LoadFromFile(Filename); + if (FAILED(res)) { + Game->LOG(res, "Error loading sound '%s'", Filename); + delete sound; + return NULL; + } + + // set volume appropriately + switch (Type) { + case SOUND_SFX: + sound->SetVolume(m_VolumeSFX); + break; + case SOUND_SPEECH: + sound->SetVolume(m_VolumeSpeech); + break; + case SOUND_MUSIC: + sound->SetVolume(m_VolumeMusic); + break; + } + + // register sound + m_Sounds.Add(sound); + + return sound; +#endif + return NULL; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSoundMgr::AddSound(CBSoundBuffer *Sound, TSoundType Type) { + if (!Sound) return E_FAIL; +#if 0 + // set volume appropriately + switch (Type) { + case SOUND_SFX: + Sound->SetVolume(m_VolumeSFX); + break; + case SOUND_SPEECH: + Sound->SetVolume(m_VolumeSpeech); + break; + case SOUND_MUSIC: + Sound->SetVolume(m_VolumeMusic); + break; + } + + // register sound + m_Sounds.Add(Sound); +#endif + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSoundMgr::RemoveSound(CBSoundBuffer *Sound) { +#if 0 + for (int i = 0; i < m_Sounds.GetSize(); i++) { + if (m_Sounds[i] == Sound) { + delete m_Sounds[i]; + m_Sounds.RemoveAt(i); + return S_OK; + } + } +#endif + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSoundMgr::SetVolume(TSoundType Type, int Volume) { + if (!m_SoundAvailable) return S_OK; +#if 0 + switch (Type) { + case SOUND_SFX: + m_VolumeSFX = Volume; + break; + case SOUND_SPEECH: + m_VolumeSpeech = Volume; + break; + case SOUND_MUSIC: + m_VolumeMusic = Volume; + break; + } + + for (int i = 0; i < m_Sounds.GetSize(); i++) { + if (m_Sounds[i]->m_Type == Type) m_Sounds[i]->SetVolume(Volume); + } +#endif + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSoundMgr::SetVolumePercent(TSoundType Type, byte Percent) { + return SetVolume(Type, Percent); +} + + +////////////////////////////////////////////////////////////////////////// +byte CBSoundMgr::GetVolumePercent(TSoundType Type) { + int Volume; + switch (Type) { + case SOUND_SFX: + Volume = m_VolumeSFX; + break; + case SOUND_SPEECH: + Volume = m_VolumeSpeech; + break; + case SOUND_MUSIC: + Volume = m_VolumeMusic; + break; + } + + return (byte )Volume; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSoundMgr::SetMasterVolumePercent(byte Percent) { + m_VolumeMaster = Percent; +#if 0 + BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, (uint32)(10000.0f / 100.0f * (float)Percent)); +#endif + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +byte CBSoundMgr::GetMasterVolumePercent() { +#if 0 + uint32 val = BASS_GetConfig(BASS_CONFIG_GVOL_STREAM); + return (float)val / 10000.0f * 100.0f; +#endif + return 0; +} + + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSoundMgr::PauseAll(bool IncludingMusic) { +#if 0 + for (int i = 0; i < m_Sounds.GetSize(); i++) { + if (m_Sounds[i]->IsPlaying() && (m_Sounds[i]->m_Type != SOUND_MUSIC || IncludingMusic)) { + m_Sounds[i]->Pause(); + m_Sounds[i]->m_FreezePaused = true; + } + } +#endif + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSoundMgr::ResumeAll() { +#if 0 + for (int i = 0; i < m_Sounds.GetSize(); i++) { + if (m_Sounds[i]->m_FreezePaused) { + m_Sounds[i]->Resume(); + m_Sounds[i]->m_FreezePaused = false; + } + } +#endif + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +float CBSoundMgr::PosToPan(int X, int Y) { + float relPos = (float)X / ((float)Game->m_Renderer->m_Width); + + float minPan = -0.7f; + float maxPan = 0.7f; + + return minPan + relPos * (maxPan - minPan); +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BSoundMgr.h b/engines/wintermute/BSoundMgr.h new file mode 100644 index 0000000000..1ffc977211 --- /dev/null +++ b/engines/wintermute/BSoundMgr.h @@ -0,0 +1,70 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BSOUNDMGR_H +#define WINTERMUTE_BSOUNDMGR_H + +#include "coll_templ.h" +#include "BBase.h" +#include "BSoundBuffer.h" +//#include "bass.h" + +namespace WinterMute { + +class CBSoundMgr : public CBBase { +public: + float PosToPan(int X, int Y); + HRESULT ResumeAll(); + HRESULT PauseAll(bool IncludingMusic = true); + HRESULT Cleanup(); + //DECLARE_PERSISTENT(CBSoundMgr, CBBase); + byte GetMasterVolumePercent(); + HRESULT SetMasterVolumePercent(byte Percent); + byte GetVolumePercent(TSoundType Type); + HRESULT SetVolumePercent(TSoundType Type, byte Percent); + HRESULT SetVolume(TSoundType Type, int Volume); + uint32 m_VolumeOriginal; + int m_VolumeMaster; + int m_VolumeMusic; + int m_VolumeSpeech; + int m_VolumeSFX; + HRESULT RemoveSound(CBSoundBuffer *Sound); + CBSoundBuffer *AddSound(const char *Filename, TSoundType Type = SOUND_SFX, bool Streamed = false); + HRESULT AddSound(CBSoundBuffer *Sound, TSoundType Type = SOUND_SFX); + HRESULT InitLoop(); + HRESULT Initialize(); + bool m_SoundAvailable; + CBSoundMgr(CBGame *inGame); + virtual ~CBSoundMgr(); + CBArray m_Sounds; + void SaveSettings(); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BSprite.cpp b/engines/wintermute/BSprite.cpp new file mode 100644 index 0000000000..912fe18f99 --- /dev/null +++ b/engines/wintermute/BSprite.cpp @@ -0,0 +1,753 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BSprite.h" +#include "StringUtil.h" +#include "PathUtil.h" +#include "BParser.h" +#include "BDynBuffer.h" +#include "ScValue.h" +#include "BSurface.h" +#include "BGame.h" +#include "BFrame.h" +#include "BSound.h" +#include "BSubFrame.h" +#include "ScScript.h" +#include "ScStack.h" +#include "BFileManager.h" +#include "PlatformSDL.h" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CBSprite, false) + +////////////////////////////////////////////////////////////////////// +CBSprite::CBSprite(CBGame *inGame, CBObject *Owner): CBScriptHolder(inGame) { + m_EditorAllFrames = false; + m_Owner = Owner; + SetDefaults(); +} + + +////////////////////////////////////////////////////////////////////// +CBSprite::~CBSprite() { + Cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +void CBSprite::SetDefaults() { + m_CurrentFrame = -1; + m_Looping = false; + m_LastFrameTime = 0; + m_Filename = NULL; + m_Finished = false; + m_Changed = false; + m_Paused = false; + m_Continuous = false; + m_MoveX = m_MoveY = 0; + + m_EditorMuted = false; + m_EditorBgFile = NULL; + m_EditorBgOffsetX = m_EditorBgOffsetY = 0; + m_EditorBgAlpha = 0xFF; + m_Streamed = false; + m_StreamedKeepLoaded = false; + + SetName(""); + + m_Precise = true; +} + + +////////////////////////////////////////////////////////////////////////// +void CBSprite::Cleanup() { + CBScriptHolder::Cleanup(); + + for (int i = 0; i < m_Frames.GetSize(); i++) + delete m_Frames[i]; + m_Frames.RemoveAll(); + + SAFE_DELETE_ARRAY(m_EditorBgFile); + + SetDefaults(); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSprite::Draw(int X, int Y, CBObject *Register, float ZoomX, float ZoomY, uint32 Alpha) { + GetCurrentFrame(ZoomX, ZoomY); + if (m_CurrentFrame < 0 || m_CurrentFrame >= m_Frames.GetSize()) return S_OK; + + // move owner if allowed to + if (m_Changed && m_Owner && m_Owner->m_Movable) { + m_Owner->m_PosX += m_MoveX; + m_Owner->m_PosY += m_MoveY; + m_Owner->AfterMove(); + + X = m_Owner->m_PosX; + Y = m_Owner->m_PosY; + } + + // draw frame + return Display(X, Y, Register, ZoomX, ZoomY, Alpha); +} + + +////////////////////////////////////////////////////////////////////// +HRESULT CBSprite::LoadFile(char *Filename, int LifeTime, TSpriteCacheType CacheType) { + CBFile *File = Game->m_FileManager->OpenFile(Filename); + if (!File) { + Game->LOG(0, "CBSprite::LoadFile failed for file '%s'", Filename); + if (Game->m_DEBUG_DebugMode) return LoadFile("invalid_debug.bmp", LifeTime, CacheType); + else return LoadFile("invalid.bmp", LifeTime, CacheType); + } else { + Game->m_FileManager->CloseFile(File); + File = NULL; + } + + HRESULT ret; + + AnsiString ext = PathUtil::GetExtension(Filename); + if (StringUtil::StartsWith(Filename, "savegame:", true) || StringUtil::CompareNoCase(ext, ".bmp") || StringUtil::CompareNoCase(ext, ".tga") || StringUtil::CompareNoCase(ext, ".png") || StringUtil::CompareNoCase(ext, ".jpg")) { + CBFrame *frame = new CBFrame(Game); + CBSubFrame *subframe = new CBSubFrame(Game); + subframe->SetSurface(Filename, true, 0, 0, 0, LifeTime, true); + if (subframe->m_Surface == NULL) { + Game->LOG(0, "Error loading simple sprite '%s'", Filename); + ret = E_FAIL; + delete frame; + delete subframe; + } else { + CBPlatform::SetRect(&subframe->m_Rect, 0, 0, subframe->m_Surface->GetWidth(), subframe->m_Surface->GetHeight()); + frame->m_Subframes.Add(subframe); + m_Frames.Add(frame); + m_CurrentFrame = 0; + ret = S_OK; + } + } else { + byte *Buffer = Game->m_FileManager->ReadWholeFile(Filename); + if (Buffer) { + if (FAILED(ret = LoadBuffer(Buffer, true, LifeTime, CacheType))) Game->LOG(0, "Error parsing SPRITE file '%s'", Filename); + delete [] Buffer; + } + } + + m_Filename = new char [strlen(Filename) + 1]; + strcpy(m_Filename, Filename); + + + return ret; +} + + + +TOKEN_DEF_START +TOKEN_DEF(CONTINUOUS) +TOKEN_DEF(SPRITE) +TOKEN_DEF(LOOPING) +TOKEN_DEF(FRAME) +TOKEN_DEF(NAME) +TOKEN_DEF(PRECISE) +TOKEN_DEF(EDITOR_MUTED) +TOKEN_DEF(STREAMED_KEEP_LOADED) +TOKEN_DEF(STREAMED) +TOKEN_DEF(SCRIPT) +TOKEN_DEF(EDITOR_BG_FILE) +TOKEN_DEF(EDITOR_BG_OFFSET_X) +TOKEN_DEF(EDITOR_BG_OFFSET_Y) +TOKEN_DEF(EDITOR_BG_ALPHA) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////// +HRESULT CBSprite::LoadBuffer(byte *Buffer, bool Complete, int LifeTime, TSpriteCacheType CacheType) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(CONTINUOUS) + TOKEN_TABLE(SPRITE) + TOKEN_TABLE(LOOPING) + TOKEN_TABLE(FRAME) + TOKEN_TABLE(NAME) + TOKEN_TABLE(PRECISE) + TOKEN_TABLE(EDITOR_MUTED) + TOKEN_TABLE(STREAMED_KEEP_LOADED) + TOKEN_TABLE(STREAMED) + TOKEN_TABLE(SCRIPT) + TOKEN_TABLE(EDITOR_BG_FILE) + TOKEN_TABLE(EDITOR_BG_OFFSET_X) + TOKEN_TABLE(EDITOR_BG_OFFSET_Y) + TOKEN_TABLE(EDITOR_BG_ALPHA) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE_END + + byte *params; + int cmd; + CBParser parser(Game); + + Cleanup(); + + + if (Complete) { + if (parser.GetCommand((char **)&Buffer, commands, (char **)¶ms) != TOKEN_SPRITE) { + Game->LOG(0, "'SPRITE' keyword expected."); + return E_FAIL; + } + Buffer = params; + } + + int frame_count = 1; + CBFrame *frame; + while ((cmd = parser.GetCommand((char **)&Buffer, commands, (char **)¶ms)) > 0) { + switch (cmd) { + case TOKEN_CONTINUOUS: + parser.ScanStr((char *)params, "%b", &m_Continuous); + break; + + case TOKEN_EDITOR_MUTED: + parser.ScanStr((char *)params, "%b", &m_EditorMuted); + break; + + case TOKEN_SCRIPT: + AddScript((char *)params); + break; + + case TOKEN_LOOPING: + parser.ScanStr((char *)params, "%b", &m_Looping); + break; + + case TOKEN_PRECISE: + parser.ScanStr((char *)params, "%b", &m_Precise); + break; + + case TOKEN_STREAMED: + parser.ScanStr((char *)params, "%b", &m_Streamed); + if (m_Streamed && LifeTime == -1) { + LifeTime = 500; + CacheType = CACHE_ALL; + } + break; + + case TOKEN_STREAMED_KEEP_LOADED: + parser.ScanStr((char *)params, "%b", &m_StreamedKeepLoaded); + break; + + case TOKEN_NAME: + SetName((char *)params); + break; + + case TOKEN_EDITOR_BG_FILE: + if (Game->m_EditorMode) { + SAFE_DELETE_ARRAY(m_EditorBgFile); + m_EditorBgFile = new char[strlen((char *)params) + 1]; + if (m_EditorBgFile) strcpy(m_EditorBgFile, (char *)params); + } + break; + + case TOKEN_EDITOR_BG_OFFSET_X: + parser.ScanStr((char *)params, "%d", &m_EditorBgOffsetX); + break; + + case TOKEN_EDITOR_BG_OFFSET_Y: + parser.ScanStr((char *)params, "%d", &m_EditorBgOffsetY); + break; + + case TOKEN_EDITOR_BG_ALPHA: + parser.ScanStr((char *)params, "%d", &m_EditorBgAlpha); + m_EditorBgAlpha = std::min(m_EditorBgAlpha, 255); + m_EditorBgAlpha = std::max(m_EditorBgAlpha, 0); + break; + + case TOKEN_FRAME: { + int FrameLifeTime = LifeTime; + if (CacheType == CACHE_HALF && frame_count % 2 != 1) FrameLifeTime = -1; + + frame = new CBFrame(Game); + + if (FAILED(frame->LoadBuffer(params, FrameLifeTime, m_StreamedKeepLoaded))) { + delete frame; + Game->LOG(0, "Error parsing frame %d", frame_count); + return E_FAIL; + } + + m_Frames.Add(frame); + frame_count++; + if (m_CurrentFrame == -1) m_CurrentFrame = 0; + } + break; + + case TOKEN_EDITOR_PROPERTY: + ParseEditorProperty(params, false); + break; + } + } + + if (cmd == PARSERR_TOKENNOTFOUND) { + Game->LOG(0, "Syntax error in SPRITE definition"); + return E_FAIL; + } + m_CanBreak = !m_Continuous; + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////// +void CBSprite::Reset() { + if (m_Frames.GetSize() > 0) m_CurrentFrame = 0; + else m_CurrentFrame = -1; + + KillAllSounds(); + + m_LastFrameTime = 0; + m_Finished = false; + m_MoveX = m_MoveY = 0; +} + + +////////////////////////////////////////////////////////////////////// +bool CBSprite::GetCurrentFrame(float ZoomX, float ZoomY) { + //if(m_Owner && m_Owner->m_Freezable && Game->m_State == GAME_FROZEN) return true; + + if (m_CurrentFrame == -1) return false; + + uint32 timer; + if (m_Owner && m_Owner->m_Freezable) timer = Game->m_Timer; + else timer = Game->m_LiveTimer; + + int LastFrame = m_CurrentFrame; + + // get current frame + if (!m_Paused && !m_Finished && timer >= m_LastFrameTime + m_Frames[m_CurrentFrame]->m_Delay && m_LastFrameTime != 0) { + if (m_CurrentFrame < m_Frames.GetSize() - 1) { + m_CurrentFrame++; + if (m_Continuous) m_CanBreak = (m_CurrentFrame == m_Frames.GetSize() - 1); + } else { + if (m_Looping) { + m_CurrentFrame = 0; + m_CanBreak = true; + } else { + m_Finished = true; + m_CanBreak = true; + } + } + + m_LastFrameTime = timer; + } + + m_Changed = (LastFrame != m_CurrentFrame || (m_Looping && m_Frames.GetSize() == 1)); + + if (m_LastFrameTime == 0) { + m_LastFrameTime = timer; + m_Changed = true; + if (m_Continuous) m_CanBreak = (m_CurrentFrame == m_Frames.GetSize() - 1); + } + + if (m_Changed) { + m_MoveX = m_Frames[m_CurrentFrame]->m_MoveX; + m_MoveY = m_Frames[m_CurrentFrame]->m_MoveY; + + if (ZoomX != 100 || ZoomY != 100) { + m_MoveX = (int)((float)m_MoveX * (float)(ZoomX / 100.0f)); + m_MoveY = (int)((float)m_MoveY * (float)(ZoomY / 100.0f)); + } + } + + return m_Changed; +} + + +////////////////////////////////////////////////////////////////////// +HRESULT CBSprite::Display(int X, int Y, CBObject *Register, float ZoomX, float ZoomY, uint32 Alpha, float Rotate, TSpriteBlendMode BlendMode) { + if (m_CurrentFrame < 0 || m_CurrentFrame >= m_Frames.GetSize()) return S_OK; + + // on change... + if (m_Changed) { + if (m_Frames[m_CurrentFrame]->m_KillSound) { + KillAllSounds(); + } + ApplyEvent("FrameChanged"); + m_Frames[m_CurrentFrame]->OneTimeDisplay(m_Owner, Game->m_EditorMode && m_EditorMuted); + } + + // draw frame + return m_Frames[m_CurrentFrame]->Draw(X - Game->m_OffsetX, Y - Game->m_OffsetY, Register, ZoomX, ZoomY, m_Precise, Alpha, m_EditorAllFrames, Rotate, BlendMode); +} + + +////////////////////////////////////////////////////////////////////////// +CBSurface *CBSprite::GetSurface() { + // only used for animated textures for 3D models + if (m_CurrentFrame < 0 || m_CurrentFrame >= m_Frames.GetSize()) return NULL; + CBFrame *Frame = m_Frames[m_CurrentFrame]; + if (Frame && Frame->m_Subframes.GetSize() > 0) { + CBSubFrame *Subframe = Frame->m_Subframes[0]; + if (Subframe) return Subframe->m_Surface; + else return NULL; + } else return NULL; +} + +////////////////////////////////////////////////////////////////////////// +bool CBSprite::GetBoundingRect(LPRECT Rect, int X, int Y, float ScaleX, float ScaleY) { + if (!Rect) return false; + + CBPlatform::SetRectEmpty(Rect); + for (int i = 0; i < m_Frames.GetSize(); i++) { + RECT frame; + RECT temp; + CBPlatform::CopyRect(&temp, Rect); + m_Frames[i]->GetBoundingRect(&frame, X, Y, ScaleX, ScaleY); + CBPlatform::UnionRect(Rect, &temp, &frame); + } + return true; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSprite::SaveAsText(CBDynBuffer *Buffer, int Indent) { + Buffer->PutTextIndent(Indent, "SPRITE {\n"); + Buffer->PutTextIndent(Indent + 2, "NAME=\"%s\"\n", m_Name); + Buffer->PutTextIndent(Indent + 2, "LOOPING=%s\n", m_Looping ? "TRUE" : "FALSE"); + Buffer->PutTextIndent(Indent + 2, "CONTINUOUS=%s\n", m_Continuous ? "TRUE" : "FALSE"); + Buffer->PutTextIndent(Indent + 2, "PRECISE=%s\n", m_Precise ? "TRUE" : "FALSE"); + if (m_Streamed) { + Buffer->PutTextIndent(Indent + 2, "STREAMED=%s\n", m_Streamed ? "TRUE" : "FALSE"); + + if (m_StreamedKeepLoaded) + Buffer->PutTextIndent(Indent + 2, "STREAMED_KEEP_LOADED=%s\n", m_StreamedKeepLoaded ? "TRUE" : "FALSE"); + } + + if (m_EditorMuted) + Buffer->PutTextIndent(Indent + 2, "EDITOR_MUTED=%s\n", m_EditorMuted ? "TRUE" : "FALSE"); + + if (m_EditorBgFile) { + Buffer->PutTextIndent(Indent + 2, "EDITOR_BG_FILE=\"%s\"\n", m_EditorBgFile); + Buffer->PutTextIndent(Indent + 2, "EDITOR_BG_OFFSET_X=%d\n", m_EditorBgOffsetX); + Buffer->PutTextIndent(Indent + 2, "EDITOR_BG_OFFSET_Y=%d\n", m_EditorBgOffsetY); + Buffer->PutTextIndent(Indent + 2, "EDITOR_BG_ALPHA=%d\n", m_EditorBgAlpha); + } + + CBScriptHolder::SaveAsText(Buffer, Indent + 2); + + int i; + + // scripts + for (i = 0; i < m_Scripts.GetSize(); i++) { + Buffer->PutTextIndent(Indent + 2, "SCRIPT=\"%s\"\n", m_Scripts[i]->m_Filename); + } + + + for (i = 0; i < m_Frames.GetSize(); i++) { + m_Frames[i]->SaveAsText(Buffer, Indent + 2); + } + + Buffer->PutTextIndent(Indent, "}\n\n"); + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSprite::Persist(CBPersistMgr *PersistMgr) { + CBScriptHolder::Persist(PersistMgr); + + PersistMgr->Transfer(TMEMBER(m_CanBreak)); + PersistMgr->Transfer(TMEMBER(m_Changed)); + PersistMgr->Transfer(TMEMBER(m_Paused)); + PersistMgr->Transfer(TMEMBER(m_Continuous)); + PersistMgr->Transfer(TMEMBER(m_CurrentFrame)); + PersistMgr->Transfer(TMEMBER(m_EditorAllFrames)); + PersistMgr->Transfer(TMEMBER(m_EditorBgAlpha)); + PersistMgr->Transfer(TMEMBER(m_EditorBgFile)); + PersistMgr->Transfer(TMEMBER(m_EditorBgOffsetX)); + PersistMgr->Transfer(TMEMBER(m_EditorBgOffsetY)); + PersistMgr->Transfer(TMEMBER(m_EditorMuted)); + PersistMgr->Transfer(TMEMBER(m_Finished)); + + m_Frames.Persist(PersistMgr); + + PersistMgr->Transfer(TMEMBER(m_LastFrameTime)); + PersistMgr->Transfer(TMEMBER(m_Looping)); + PersistMgr->Transfer(TMEMBER(m_MoveX)); + PersistMgr->Transfer(TMEMBER(m_MoveY)); + PersistMgr->Transfer(TMEMBER(m_Owner)); + PersistMgr->Transfer(TMEMBER(m_Precise)); + PersistMgr->Transfer(TMEMBER(m_Streamed)); + PersistMgr->Transfer(TMEMBER(m_StreamedKeepLoaded)); + + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +HRESULT CBSprite::ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name) { + ////////////////////////////////////////////////////////////////////////// + // GetFrame + ////////////////////////////////////////////////////////////////////////// + if (strcmp(Name, "GetFrame") == 0) { + Stack->CorrectParams(1); + int Index = Stack->Pop()->GetInt(-1); + if (Index < 0 || Index >= m_Frames.GetSize()) { + Script->RuntimeError("Sprite.GetFrame: Frame index %d is out of range.", Index); + Stack->PushNULL(); + } else Stack->PushNative(m_Frames[Index], true); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // DeleteFrame + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "DeleteFrame") == 0) { + Stack->CorrectParams(1); + CScValue *Val = Stack->Pop(); + if (Val->IsInt()) { + int Index = Val->GetInt(-1); + if (Index < 0 || Index >= m_Frames.GetSize()) { + Script->RuntimeError("Sprite.DeleteFrame: Frame index %d is out of range.", Index); + } + } else { + CBFrame *Frame = (CBFrame *)Val->GetNative(); + for (int i = 0; i < m_Frames.GetSize(); i++) { + if (m_Frames[i] == Frame) { + if (i == m_CurrentFrame) m_LastFrameTime = 0; + delete m_Frames[i]; + m_Frames.RemoveAt(i); + break; + } + } + } + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Reset + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Reset") == 0) { + Stack->CorrectParams(0); + Reset(); + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // AddFrame + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "AddFrame") == 0) { + Stack->CorrectParams(1); + CScValue *Val = Stack->Pop(); + char *Filename = NULL; + if (!Val->IsNULL()) Filename = Val->GetString(); + + CBFrame *Frame = new CBFrame(Game); + if (Filename != NULL) { + CBSubFrame *Sub = new CBSubFrame(Game); + if (SUCCEEDED(Sub->SetSurface(Filename))) { + Sub->SetDefaultRect(); + Frame->m_Subframes.Add(Sub); + } else delete Sub; + } + m_Frames.Add(Frame); + + Stack->PushNative(Frame, true); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // InsertFrame + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "InsertFrame") == 0) { + Stack->CorrectParams(2); + int Index = Stack->Pop()->GetInt(); + if (Index < 0) Index = 0; + + CScValue *Val = Stack->Pop(); + char *Filename = NULL; + if (!Val->IsNULL()) Filename = Val->GetString(); + + CBFrame *Frame = new CBFrame(Game); + if (Filename != NULL) { + CBSubFrame *Sub = new CBSubFrame(Game); + if (SUCCEEDED(Sub->SetSurface(Filename))) Frame->m_Subframes.Add(Sub); + else delete Sub; + } + + if (Index >= m_Frames.GetSize()) m_Frames.Add(Frame); + else m_Frames.InsertAt(Index, Frame); + + Stack->PushNative(Frame, true); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Pause + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Pause") == 0) { + Stack->CorrectParams(0); + m_Paused = true; + Stack->PushNULL(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Play + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Play") == 0) { + Stack->CorrectParams(0); + m_Paused = false; + Stack->PushNULL(); + return S_OK; + } + + else return CBScriptHolder::ScCallMethod(Script, Stack, ThisStack, Name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CBSprite::ScGetProperty(char *Name) { + m_ScValue->SetNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type + ////////////////////////////////////////////////////////////////////////// + if (strcmp(Name, "Type") == 0) { + m_ScValue->SetString("sprite"); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // NumFrames (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "NumFrames") == 0) { + m_ScValue->SetInt(m_Frames.GetSize()); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // CurrentFrame + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "CurrentFrame") == 0) { + m_ScValue->SetInt(m_CurrentFrame); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // PixelPerfect + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "PixelPerfect") == 0) { + m_ScValue->SetBool(m_Precise); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Looping + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Looping") == 0) { + m_ScValue->SetBool(m_Looping); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Owner (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Owner") == 0) { + if (m_Owner == NULL) m_ScValue->SetNULL(); + else m_ScValue->SetNative(m_Owner, true); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Finished (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Finished") == 0) { + m_ScValue->SetBool(m_Finished); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Paused (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Paused") == 0) { + m_ScValue->SetBool(m_Paused); + return m_ScValue; + } + + else return CBScriptHolder::ScGetProperty(Name); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSprite::ScSetProperty(char *Name, CScValue *Value) { + ////////////////////////////////////////////////////////////////////////// + // CurrentFrame + ////////////////////////////////////////////////////////////////////////// + if (strcmp(Name, "CurrentFrame") == 0) { + m_CurrentFrame = Value->GetInt(0); + if (m_CurrentFrame >= m_Frames.GetSize() || m_CurrentFrame < 0) { + m_CurrentFrame = -1; + } + m_LastFrameTime = 0; + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // PixelPerfect + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "PixelPerfect") == 0) { + m_Precise = Value->GetBool(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Looping + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Looping") == 0) { + m_Looping = Value->GetBool(); + return S_OK; + } + + else return CBScriptHolder::ScSetProperty(Name, Value); +} + + +////////////////////////////////////////////////////////////////////////// +char *CBSprite::ScToString() { + return "[sprite]"; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSprite::KillAllSounds() { + for (int i = 0; i < m_Frames.GetSize(); i++) { + if (m_Frames[i]->m_Sound) m_Frames[i]->m_Sound->Stop(); + } + return S_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BSprite.h b/engines/wintermute/BSprite.h new file mode 100644 index 0000000000..01a89a6931 --- /dev/null +++ b/engines/wintermute/BSprite.h @@ -0,0 +1,90 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BSPRITE_H +#define WINTERMUTE_BSPRITE_H + + +#include "coll_templ.h" +#include "BScriptHolder.h" + +namespace WinterMute { +class CBFrame; +class CBSurface; +class CBObject; +class CBSprite: public CBScriptHolder { +public: + HRESULT KillAllSounds(); + CBSurface *GetSurface(); + char *m_EditorBgFile; + int m_EditorBgOffsetX; + int m_EditorBgOffsetY; + int m_EditorBgAlpha; + bool m_Streamed; + bool m_StreamedKeepLoaded; + void Cleanup(); + void SetDefaults(); + bool m_Precise; + DECLARE_PERSISTENT(CBSprite, CBScriptHolder) + + bool m_EditorAllFrames; + bool GetBoundingRect(LPRECT Rect, int X, int Y, float ScaleX = 100, float ScaleY = 100); + int m_MoveY; + int m_MoveX; + HRESULT Display(int X, int Y, CBObject *Register = NULL, float ZoomX = 100, float ZoomY = 100, uint32 Alpha = 0xFFFFFFFF, float Rotate = 0.0f, TSpriteBlendMode BlendMode = BLEND_NORMAL); + bool GetCurrentFrame(float ZoomX = 100, float ZoomY = 100); + bool m_CanBreak; + bool m_EditorMuted; + bool m_Continuous; + void Reset(); + CBObject *m_Owner; + bool m_Changed; + bool m_Paused; + bool m_Finished; + HRESULT LoadBuffer(byte *Buffer, bool Compete = true, int LifeTime = -1, TSpriteCacheType CacheType = CACHE_ALL); + HRESULT LoadFile(char *Filename, int LifeTime = -1, TSpriteCacheType CacheType = CACHE_ALL); + uint32 m_LastFrameTime; + HRESULT Draw(int X, int Y, CBObject *Register = NULL, float ZoomX = 100, float ZoomY = 100, uint32 Alpha = 0xFFFFFFFF); + bool m_Looping; + int m_CurrentFrame; + HRESULT AddFrame(char *Filename, uint32 Delay = 0, int HotspotX = 0, int HotspotY = 0, RECT *Rect = NULL); + CBSprite(CBGame *inGame, CBObject *Owner = NULL); + virtual ~CBSprite(); + CBArray m_Frames; + HRESULT SaveAsText(CBDynBuffer *Buffer, int Indent); + + // scripting interface + virtual CScValue *ScGetProperty(char *Name); + virtual HRESULT ScSetProperty(char *Name, CScValue *Value); + virtual HRESULT ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name); + virtual char *ScToString(); +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BStringTable.cpp b/engines/wintermute/BStringTable.cpp new file mode 100644 index 0000000000..e3bf2fd89b --- /dev/null +++ b/engines/wintermute/BStringTable.cpp @@ -0,0 +1,229 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "PlatformSDL.h" +#include "BFileManager.h" +#include "BGame.h" +#include "BStringTable.h" +#include "StringUtil.h" +#include "common/str.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CBStringTable::CBStringTable(CBGame *inGame): CBBase(inGame) { + +} + + +////////////////////////////////////////////////////////////////////////// +CBStringTable::~CBStringTable() { + // delete strings + m_Strings.clear(); + +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBStringTable::AddString(const char *Key, const char *Val, bool ReportDuplicities) { + if (Key == NULL || Val == NULL) return E_FAIL; + + if (scumm_stricmp(Key, "@right-to-left") == 0) { + Game->m_TextRTL = true; + return S_OK; + } + + std::string final_key = Key; + StringUtil::ToLowerCase(final_key); + + m_StringsIter = m_Strings.find(final_key); + if (m_StringsIter != m_Strings.end() && ReportDuplicities) Game->LOG(0, " Warning: Duplicate definition of string '%s'.", final_key.c_str()); + + m_Strings[final_key] = Val; + + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +char *CBStringTable::GetKey(const char *Str) { + if (Str == NULL || Str[0] != '/') return NULL; + + char *value = strchr((char *)Str + 1, '/'); + if (value == NULL) return NULL; + + char *key = new char[value - Str]; + strncpy(key, Str + 1, value - Str - 1); + key[value - Str - 1] = '\0'; + CBPlatform::strlwr(key); + + char *new_str; + + m_StringsIter = m_Strings.find(key); + if (m_StringsIter != m_Strings.end()) { + new_str = new char[m_StringsIter->second.length() + 1]; + strcpy(new_str, m_StringsIter->second.c_str()); + if (strlen(new_str) > 0 && new_str[0] == '/' && strchr(new_str + 1, '/')) { + delete [] key; + char *Ret = GetKey(new_str); + delete [] new_str; + return Ret; + } else { + delete [] new_str; + return key; + } + } else { + return key; + } +} + +////////////////////////////////////////////////////////////////////////// +void CBStringTable::Expand(char **Str, bool ForceExpand) { + if (Game->m_DoNotExpandStrings && !ForceExpand) return; + + if (Str == NULL || *Str == NULL || *Str[0] != '/') return; + + char *value = strchr(*Str + 1, '/'); + if (value == NULL) return; + + char *key = new char[value - *Str]; + strncpy(key, *Str + 1, value - *Str - 1); + key[value - *Str - 1] = '\0'; + CBPlatform::strlwr(key); + + value++; + + char *new_str; + + m_StringsIter = m_Strings.find(key); + if (m_StringsIter != m_Strings.end()) { + new_str = new char[m_StringsIter->second.length() + 1]; + strcpy(new_str, m_StringsIter->second.c_str()); + } else { + new_str = new char[strlen(value) + 1]; + strcpy(new_str, value); + } + + delete [] key; + delete [] *Str; + *Str = new_str; + + if (strlen(*Str) > 0 && *Str[0] == '/') Expand(Str, ForceExpand); +} + + +////////////////////////////////////////////////////////////////////////// +const char *CBStringTable::ExpandStatic(const char *String, bool ForceExpand) { + if (Game->m_DoNotExpandStrings && !ForceExpand) return String; + + if (String == NULL || String[0] == '\0' || String[0] != '/') return String; + + const char *value = strchr(String + 1, '/'); + if (value == NULL) return String; + + char *key = new char[value - String]; + strncpy(key, String + 1, value - String - 1); + key[value - String - 1] = '\0'; + CBPlatform::strlwr(key); + + value++; + + const char *new_str; + + m_StringsIter = m_Strings.find(key); + if (m_StringsIter != m_Strings.end()) { + new_str = m_StringsIter->second.c_str(); + } else { + new_str = value; + } + + delete [] key; + + if (strlen(new_str) > 0 && new_str[0] == '/') return ExpandStatic(new_str, ForceExpand); + else return new_str; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBStringTable::LoadFile(char *Filename, bool ClearOld) { + Game->LOG(0, "Loading string table..."); + + if (ClearOld) m_Strings.clear(); + + uint32 Size; + byte *Buffer = Game->m_FileManager->ReadWholeFile(Filename, &Size); + if (Buffer == NULL) { + Game->LOG(0, "CBStringTable::LoadFile failed for file '%s'", Filename); + return E_FAIL; + } + + int Pos = 0; + + if (Size > 3 && Buffer[0] == 0xEF && Buffer[1] == 0xBB && Buffer[2] == 0xBF) { + Pos += 3; + if (Game->m_TextEncoding != TEXT_UTF8) { + Game->m_TextEncoding = TEXT_UTF8; + //Game->m_TextEncoding = TEXT_ANSI; + Game->LOG(0, " UTF8 file detected, switching to UTF8 text encoding"); + } + } else Game->m_TextEncoding = TEXT_ANSI; + + int LineLength = 0; + while (Pos < Size) { + LineLength = 0; + while (Pos + LineLength < Size && Buffer[Pos + LineLength] != '\n' && Buffer[Pos + LineLength] != '\0') LineLength++; + + int RealLength = LineLength - (Pos + LineLength >= Size ? 0 : 1); + char *line = new char[RealLength + 1]; + strncpy(line, (char *)&Buffer[Pos], RealLength); + line[RealLength] = '\0'; + char *value = strchr(line, '\t'); + if (value == NULL) value = strchr(line, ' '); + + if (line[0] != ';') { + if (value != NULL) { + value[0] = '\0'; + value++; + for (int i = 0; i < strlen(value); i++) { + if (value[i] == '|') value[i] = '\n'; + } + AddString(line, value, ClearOld); + } else if (line[0] != '\0') AddString(line, "", ClearOld); + } + + delete [] line; + Pos += LineLength + 1; + } + + delete [] Buffer; + + Game->LOG(0, " %d strings loaded", m_Strings.size()); + + return S_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BStringTable.h b/engines/wintermute/BStringTable.h new file mode 100644 index 0000000000..6b28f5307d --- /dev/null +++ b/engines/wintermute/BStringTable.h @@ -0,0 +1,55 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BSTRINGTABLE_H +#define WINTERMUTE_BSTRINGTABLE_H + + +#include +#include "BBase.h" + +namespace WinterMute { + +class CBStringTable : public CBBase { +public: + const char *ExpandStatic(const char *String, bool ForceExpand = false); + HRESULT LoadFile(char *Filename, bool DeleteAll = true); + void Expand(char **Str, bool ForceExpand = false); + HRESULT AddString(const char *Key, const char *Val, bool ReportDuplicities = true); + CBStringTable(CBGame *inGame); + virtual ~CBStringTable(); + std::map m_Strings; + char *GetKey(const char *Str); +private: + std::map::iterator m_StringsIter; + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BSubFrame.cpp b/engines/wintermute/BSubFrame.cpp new file mode 100644 index 0000000000..415bcc7b52 --- /dev/null +++ b/engines/wintermute/BSubFrame.cpp @@ -0,0 +1,588 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BParser.h" +#include "BSubFrame.h" +#include "BActiveRect.h" +#include "BDynBuffer.h" +#include "BSurface.h" +#include "ScValue.h" +#include "ScStack.h" +#include "BGame.h" +#include "PlatformSDL.h" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CBSubFrame, false) + +////////////////////////////////////////////////////////////////////////// +CBSubFrame::CBSubFrame(CBGame *inGame): CBScriptable(inGame, true) { + m_Surface = NULL; + m_HotspotX = m_HotspotY = 0; + m_Alpha = 0xFFFFFFFF; + m_Transparent = 0xFFFF00FF; + + CBPlatform::SetRectEmpty(&m_Rect); + + m_EditorSelected = false; + + m_SurfaceFilename = NULL; + m_CKDefault = true; + m_CKRed = m_CKBlue = m_CKGreen = 0; + m_LifeTime = -1; + m_KeepLoaded = false; + + m_2DOnly = m_3DOnly = false; + m_Decoration = false; + + m_MirrorX = m_MirrorY = false; +} + + +////////////////////////////////////////////////////////////////////////// +CBSubFrame::~CBSubFrame() { + if (m_Surface) Game->m_SurfaceStorage->RemoveSurface(m_Surface); + delete[] m_SurfaceFilename; + m_SurfaceFilename = NULL; +} + + +TOKEN_DEF_START +TOKEN_DEF(IMAGE) +TOKEN_DEF(TRANSPARENT) +TOKEN_DEF(RECT) +TOKEN_DEF(HOTSPOT) +TOKEN_DEF(2D_ONLY) +TOKEN_DEF(3D_ONLY) +TOKEN_DEF(DECORATION) +TOKEN_DEF(ALPHA_COLOR) +TOKEN_DEF(ALPHA) +TOKEN_DEF(MIRROR_X) +TOKEN_DEF(MIRROR_Y) +TOKEN_DEF(EDITOR_SELECTED) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////// +HRESULT CBSubFrame::LoadBuffer(byte *Buffer, int LifeTime, bool KeepLoaded) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(IMAGE) + TOKEN_TABLE(TRANSPARENT) + TOKEN_TABLE(RECT) + TOKEN_TABLE(HOTSPOT) + TOKEN_TABLE(2D_ONLY) + TOKEN_TABLE(3D_ONLY) + TOKEN_TABLE(DECORATION) + TOKEN_TABLE(ALPHA_COLOR) + TOKEN_TABLE(ALPHA) + TOKEN_TABLE(MIRROR_X) + TOKEN_TABLE(MIRROR_Y) + TOKEN_TABLE(EDITOR_SELECTED) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE_END + + char *params; + int cmd; + CBParser parser(Game); + RECT rect; + int r = 255, g = 255, b = 255; + int ar = 255, ag = 255, ab = 255, alpha = 255; + bool custom_trans = false; + CBPlatform::SetRectEmpty(&rect); + char *surface_file = NULL; + + delete m_Surface; + m_Surface = NULL; + + while ((cmd = parser.GetCommand((char **)&Buffer, commands, ¶ms)) > 0) { + switch (cmd) { + case TOKEN_IMAGE: + surface_file = params; + break; + + case TOKEN_TRANSPARENT: + parser.ScanStr(params, "%d,%d,%d", &r, &g, &b); + custom_trans = true; + break; + + case TOKEN_RECT: + parser.ScanStr(params, "%d,%d,%d,%d", &rect.left, &rect.top, &rect.right, &rect.bottom); + break; + + case TOKEN_HOTSPOT: + parser.ScanStr(params, "%d,%d", &m_HotspotX, &m_HotspotY); + break; + + case TOKEN_2D_ONLY: + parser.ScanStr(params, "%b", &m_2DOnly); + break; + + case TOKEN_3D_ONLY: + parser.ScanStr(params, "%b", &m_3DOnly); + break; + + case TOKEN_MIRROR_X: + parser.ScanStr(params, "%b", &m_MirrorX); + break; + + case TOKEN_MIRROR_Y: + parser.ScanStr(params, "%b", &m_MirrorY); + break; + + case TOKEN_DECORATION: + parser.ScanStr(params, "%b", &m_Decoration); + break; + + case TOKEN_ALPHA_COLOR: + parser.ScanStr(params, "%d,%d,%d", &ar, &ag, &ab); + break; + + case TOKEN_ALPHA: + parser.ScanStr(params, "%d", &alpha); + break; + + case TOKEN_EDITOR_SELECTED: + parser.ScanStr(params, "%b", &m_EditorSelected); + break; + + case TOKEN_EDITOR_PROPERTY: + ParseEditorProperty((byte *)params, false); + break; + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + Game->LOG(0, "Syntax error in SUBFRAME definition"); + return E_FAIL; + } + + if (surface_file != NULL) { + if (custom_trans) SetSurface(surface_file, false, r, g, b, LifeTime, KeepLoaded); + else SetSurface(surface_file, true, 0, 0, 0, LifeTime, KeepLoaded); + } + + m_Alpha = DRGBA(ar, ag, ab, alpha); + if (custom_trans) m_Transparent = DRGBA(r, g, b, 0xFF); + + /* + if(m_Surface == NULL) + { + Game->LOG(0, "Error parsing sub-frame. Image not set."); + return E_FAIL; + } + */ + if (CBPlatform::IsRectEmpty(&rect)) SetDefaultRect(); + else m_Rect = rect; + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////// +HRESULT CBSubFrame::Draw(int X, int Y, CBObject *Register, float ZoomX, float ZoomY, bool Precise, uint32 Alpha, float Rotate, TSpriteBlendMode BlendMode) { + if (!m_Surface) return S_OK; + + if (Register != NULL && !m_Decoration) { + if (ZoomX == 100 && ZoomY == 100) { + Game->m_Renderer->m_RectList.Add(new CBActiveRect(Game, Register, this, X - m_HotspotX + m_Rect.left, Y - m_HotspotY + m_Rect.top, m_Rect.right - m_Rect.left, m_Rect.bottom - m_Rect.top, ZoomX, ZoomY, Precise)); + } else { + Game->m_Renderer->m_RectList.Add(new CBActiveRect(Game, Register, this, (int)(X - (m_HotspotX + m_Rect.left) * (ZoomX / 100)), (int)(Y - (m_HotspotY + m_Rect.top) * (ZoomY / 100)), (int)((m_Rect.right - m_Rect.left) * (ZoomX / 100)), (int)((m_Rect.bottom - m_Rect.top) * (ZoomY / 100)), ZoomX, ZoomY, Precise)); + } + } + if (Game->m_SuspendedRendering) return S_OK; + + HRESULT res; + + //if(Alpha==0xFFFFFFFF) Alpha = m_Alpha; // TODO: better (combine owner's and self alpha) + if (m_Alpha != 0xFFFFFFFF) Alpha = m_Alpha; + + if (Rotate != 0.0f) { + res = m_Surface->DisplayTransform((int)(X - m_HotspotX * (ZoomX / 100)), (int)(Y - m_HotspotY * (ZoomY / 100)), m_HotspotX, m_HotspotY, m_Rect, ZoomX, ZoomY, Alpha, Rotate, BlendMode, m_MirrorX, m_MirrorY); + } else { + if (ZoomX == 100 && ZoomY == 100) res = m_Surface->DisplayTrans(X - m_HotspotX, Y - m_HotspotY, m_Rect, Alpha, BlendMode, m_MirrorX, m_MirrorY); + else res = m_Surface->DisplayTransZoom((int)(X - m_HotspotX * (ZoomX / 100)), (int)(Y - m_HotspotY * (ZoomY / 100)), m_Rect, ZoomX, ZoomY, Alpha, BlendMode, m_MirrorX, m_MirrorY); + } + + return res; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSubFrame::GetBoundingRect(LPRECT Rect, int X, int Y, float ScaleX, float ScaleY) { + if (!Rect) return false; + + float RatioX = ScaleX / 100.0f; + float RatioY = ScaleY / 100.0f; + + CBPlatform::SetRect(Rect, + X - m_HotspotX * RatioX, + Y - m_HotspotY * RatioY, + X - m_HotspotX * RatioX + (m_Rect.right - m_Rect.left)*RatioX, + Y - m_HotspotY * RatioY + (m_Rect.bottom - m_Rect.top)*RatioY); + return true; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSubFrame::SaveAsText(CBDynBuffer *Buffer, int Indent, bool Complete) { + if (Complete) + Buffer->PutTextIndent(Indent, "SUBFRAME {\n"); + + if (m_Surface && m_Surface->m_Filename != NULL) + Buffer->PutTextIndent(Indent + 2, "IMAGE = \"%s\"\n", m_Surface->m_Filename); + + if (m_Transparent != 0xFFFF00FF) + Buffer->PutTextIndent(Indent + 2, "TRANSPARENT { %d,%d,%d }\n", D3DCOLGetR(m_Transparent), D3DCOLGetG(m_Transparent), D3DCOLGetB(m_Transparent)); + + RECT rect; + CBPlatform::SetRectEmpty(&rect); + if (m_Surface) CBPlatform::SetRect(&rect, 0, 0, m_Surface->GetWidth(), m_Surface->GetHeight()); + if (!CBPlatform::EqualRect(&rect, &m_Rect)) + Buffer->PutTextIndent(Indent + 2, "RECT { %d,%d,%d,%d }\n", m_Rect.left, m_Rect.top, m_Rect.right, m_Rect.bottom); + + if (m_HotspotX != 0 || m_HotspotY != 0) + Buffer->PutTextIndent(Indent + 2, "HOTSPOT {%d, %d}\n", m_HotspotX, m_HotspotY); + + if (m_Alpha != 0xFFFFFFFF) { + Buffer->PutTextIndent(Indent + 2, "ALPHA_COLOR { %d,%d,%d }\n", D3DCOLGetR(m_Alpha), D3DCOLGetG(m_Alpha), D3DCOLGetB(m_Alpha)); + Buffer->PutTextIndent(Indent + 2, "ALPHA = %d\n", D3DCOLGetA(m_Alpha)); + } + + if (m_MirrorX) + Buffer->PutTextIndent(Indent + 2, "MIRROR_X=%s\n", m_MirrorX ? "TRUE" : "FALSE"); + + if (m_MirrorY) + Buffer->PutTextIndent(Indent + 2, "MIRROR_Y=%s\n", m_MirrorY ? "TRUE" : "FALSE"); + + if (m_2DOnly) + Buffer->PutTextIndent(Indent + 2, "2D_ONLY=%s\n", m_2DOnly ? "TRUE" : "FALSE"); + + if (m_3DOnly) + Buffer->PutTextIndent(Indent + 2, "3D_ONLY=%s\n", m_3DOnly ? "TRUE" : "FALSE"); + + if (m_Decoration) + Buffer->PutTextIndent(Indent + 2, "DECORATION=%s\n", m_Decoration ? "TRUE" : "FALSE"); + + if (m_EditorSelected) + Buffer->PutTextIndent(Indent + 2, "EDITOR_SELECTED=%s\n", m_EditorSelected ? "TRUE" : "FALSE"); + + CBBase::SaveAsText(Buffer, Indent + 2); + + + if (Complete) + Buffer->PutTextIndent(Indent, "}\n\n"); + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void CBSubFrame::SetDefaultRect() { + if (m_Surface) { + CBPlatform::SetRect(&m_Rect, 0, 0, m_Surface->GetWidth(), m_Surface->GetHeight()); + } else CBPlatform::SetRectEmpty(&m_Rect); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSubFrame::Persist(CBPersistMgr *PersistMgr) { + + CBScriptable::Persist(PersistMgr); + + PersistMgr->Transfer(TMEMBER(m_2DOnly)); + PersistMgr->Transfer(TMEMBER(m_3DOnly)); + PersistMgr->Transfer(TMEMBER(m_Alpha)); + PersistMgr->Transfer(TMEMBER(m_Decoration)); + PersistMgr->Transfer(TMEMBER(m_EditorSelected)); + PersistMgr->Transfer(TMEMBER(m_HotspotX)); + PersistMgr->Transfer(TMEMBER(m_HotspotY)); + PersistMgr->Transfer(TMEMBER(m_Rect)); + + PersistMgr->Transfer(TMEMBER(m_SurfaceFilename)); + PersistMgr->Transfer(TMEMBER(m_CKDefault)); + PersistMgr->Transfer(TMEMBER(m_CKRed)); + PersistMgr->Transfer(TMEMBER(m_CKGreen)); + PersistMgr->Transfer(TMEMBER(m_CKBlue)); + PersistMgr->Transfer(TMEMBER(m_LifeTime)); + + PersistMgr->Transfer(TMEMBER(m_KeepLoaded)); + PersistMgr->Transfer(TMEMBER(m_MirrorX)); + PersistMgr->Transfer(TMEMBER(m_MirrorY)); + PersistMgr->Transfer(TMEMBER(m_Transparent)); + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +HRESULT CBSubFrame::ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name) { + + ////////////////////////////////////////////////////////////////////////// + // GetImage + ////////////////////////////////////////////////////////////////////////// + if (strcmp(Name, "GetImage") == 0) { + Stack->CorrectParams(0); + + if (!m_SurfaceFilename) Stack->PushNULL(); + else Stack->PushString(m_SurfaceFilename); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetImage + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "SetImage") == 0) { + Stack->CorrectParams(1); + CScValue *Val = Stack->Pop(); + + if (Val->IsNULL()) { + if (m_Surface) Game->m_SurfaceStorage->RemoveSurface(m_Surface); + delete[] m_SurfaceFilename; + m_SurfaceFilename = NULL; + Stack->PushBool(true); + } else { + char *Filename = Val->GetString(); + if (SUCCEEDED(SetSurface(Filename))) { + SetDefaultRect(); + Stack->PushBool(true); + } else Stack->PushBool(false); + } + + return S_OK; + } + + else return CBScriptable::ScCallMethod(Script, Stack, ThisStack, Name); +} + + +////////////////////////////////////////////////////////////////////////// +CScValue *CBSubFrame::ScGetProperty(char *Name) { + if (!m_ScValue) m_ScValue = new CScValue(Game); + m_ScValue->SetNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type (RO) + ////////////////////////////////////////////////////////////////////////// + if (strcmp(Name, "Type") == 0) { + m_ScValue->SetString("subframe"); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // AlphaColor + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "AlphaColor") == 0) { + + m_ScValue->SetInt((int)m_Alpha); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // TransparentColor (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "TransparentColor") == 0) { + m_ScValue->SetInt((int)m_Transparent); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Is2DOnly + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Is2DOnly") == 0) { + m_ScValue->SetBool(m_2DOnly); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Is3DOnly + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Is3DOnly") == 0) { + m_ScValue->SetBool(m_3DOnly); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // MirrorX + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "MirrorX") == 0) { + m_ScValue->SetBool(m_MirrorX); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // MirrorY + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "MirrorY") == 0) { + m_ScValue->SetBool(m_MirrorY); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Decoration + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Decoration") == 0) { + m_ScValue->SetBool(m_Decoration); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // HotspotX + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "HotspotX") == 0) { + m_ScValue->SetInt(m_HotspotX); + return m_ScValue; + } + + ////////////////////////////////////////////////////////////////////////// + // HotspotY + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "HotspotY") == 0) { + m_ScValue->SetInt(m_HotspotY); + return m_ScValue; + } + + else return CBScriptable::ScGetProperty(Name); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSubFrame::ScSetProperty(char *Name, CScValue *Value) { + ////////////////////////////////////////////////////////////////////////// + // AlphaColor + ////////////////////////////////////////////////////////////////////////// + if (strcmp(Name, "AlphaColor") == 0) { + m_Alpha = (uint32)Value->GetInt(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Is2DOnly + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Is2DOnly") == 0) { + m_2DOnly = Value->GetBool(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Is3DOnly + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Is3DOnly") == 0) { + m_3DOnly = Value->GetBool(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // MirrorX + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "MirrorX") == 0) { + m_MirrorX = Value->GetBool(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // MirrorY + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "MirrorY") == 0) { + m_MirrorY = Value->GetBool(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Decoration + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "Decoration") == 0) { + m_Decoration = Value->GetBool(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // HotspotX + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "HotspotX") == 0) { + m_HotspotX = Value->GetInt(); + return S_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // HotspotY + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(Name, "HotspotY") == 0) { + m_HotspotY = Value->GetInt(); + return S_OK; + } + + else return CBScriptable::ScSetProperty(Name, Value); +} + + +////////////////////////////////////////////////////////////////////////// +char *CBSubFrame::ScToString() { + return "[subframe]"; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSubFrame::SetSurface(char *Filename, bool default_ck, byte ck_red, byte ck_green, byte ck_blue, int LifeTime, bool KeepLoaded) { + if (m_Surface) { + Game->m_SurfaceStorage->RemoveSurface(m_Surface); + m_Surface = NULL; + } + + delete[] m_SurfaceFilename; + m_SurfaceFilename = NULL; + + m_Surface = Game->m_SurfaceStorage->AddSurface(Filename, default_ck, ck_red, ck_green, ck_blue, LifeTime, KeepLoaded); + if (m_Surface) { + m_SurfaceFilename = new char[strlen(Filename) + 1]; + strcpy(m_SurfaceFilename, Filename); + + m_CKDefault = default_ck; + m_CKRed = ck_red; + m_CKGreen = ck_green; + m_CKBlue = ck_blue; + m_LifeTime = LifeTime; + m_KeepLoaded = KeepLoaded; + + return S_OK; + } else return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSubFrame::SetSurfaceSimple() { + if (!m_SurfaceFilename) { + m_Surface = NULL; + return S_OK; + } + m_Surface = Game->m_SurfaceStorage->AddSurface(m_SurfaceFilename, m_CKDefault, m_CKRed, m_CKGreen, m_CKBlue, m_LifeTime, m_KeepLoaded); + if (m_Surface) return S_OK; + else return E_FAIL; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BSubFrame.h b/engines/wintermute/BSubFrame.h new file mode 100644 index 0000000000..6147b75811 --- /dev/null +++ b/engines/wintermute/BSubFrame.h @@ -0,0 +1,85 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BSUBFRAME_H +#define WINTERMUTE_BSUBFRAME_H + + +#include "BBase.h" +#include "BScriptable.h" + +namespace WinterMute { +class CBObject; +class CBSurface; +class CBSubFrame : public CBScriptable { +public: + bool m_MirrorX; + bool m_MirrorY; + bool m_Decoration; + HRESULT SetSurface(char *Filename, bool default_ck = true, byte ck_red = 0, byte ck_green = 0, byte ck_blue = 0, int LifeTime = -1, bool KeepLoaded = false); + HRESULT SetSurfaceSimple(); + DECLARE_PERSISTENT(CBSubFrame, CBScriptable) + void SetDefaultRect(); + uint32 m_Transparent; + HRESULT SaveAsText(CBDynBuffer *Buffer, int Indent, bool Complete = true); + bool m_EditorSelected; + CBSubFrame(CBGame *inGame); + virtual ~CBSubFrame(); + HRESULT LoadBuffer(byte *Buffer, int LifeTime, bool KeepLoaded); + HRESULT Draw(int X, int Y, CBObject *Register = NULL, float ZoomX = 100, float ZoomY = 100, bool Precise = true, uint32 Alpha = 0xFFFFFFFF, float Rotate = 0.0f, TSpriteBlendMode BlendMode = BLEND_NORMAL); + bool GetBoundingRect(LPRECT Rect, int X, int Y, float ScaleX = 100, float ScaleY = 100); + + int m_HotspotX; + int m_HotspotY; + uint32 m_Alpha; + RECT m_Rect; + + bool m_CKDefault; + byte m_CKRed; + byte m_CKGreen; + byte m_CKBlue; + int m_LifeTime; + bool m_KeepLoaded; + char *m_SurfaceFilename; + + bool m_2DOnly; + bool m_3DOnly; + + CBSurface *m_Surface; + + // scripting interface + virtual CScValue *ScGetProperty(char *Name); + virtual HRESULT ScSetProperty(char *Name, CScValue *Value); + virtual HRESULT ScCallMethod(CScScript *Script, CScStack *Stack, CScStack *ThisStack, char *Name); + virtual char *ScToString(); + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BSurface.cpp b/engines/wintermute/BSurface.cpp new file mode 100644 index 0000000000..16deda3c59 --- /dev/null +++ b/engines/wintermute/BSurface.cpp @@ -0,0 +1,196 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "wintypes.h" +#include "BGame.h" +#include "BSurface.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////// +CBSurface::CBSurface(CBGame *inGame): CBBase(inGame) { + m_ReferenceCount = 0; + + m_Width = m_Height = 0; + + m_Filename = NULL; + + m_PixelOpReady = false; + + m_CKDefault = true; + m_CKRed = m_CKGreen = m_CKBlue = 0; + m_LifeTime = 0; + m_KeepLoaded = false; + + m_LastUsedTime = 0; + m_Valid = false; +} + + +////////////////////////////////////////////////////////////////////// +CBSurface::~CBSurface() { + if (m_PixelOpReady) EndPixelOp(); + if (m_Filename) delete [] m_Filename; +} + + +////////////////////////////////////////////////////////////////////// +HRESULT CBSurface::Create(char *Filename, bool default_ck, byte ck_red, byte ck_green, byte ck_blue, int LifeTime, bool KeepLoaded) { + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////// +HRESULT CBSurface::Restore() { + return E_FAIL; +} + + + + +////////////////////////////////////////////////////////////////////// +bool CBSurface::IsTransparentAt(int X, int Y) { + return false; +} + + +////////////////////////////////////////////////////////////////////// +HRESULT CBSurface::Display(int X, int Y, RECT rect, TSpriteBlendMode BlendMode, bool MirrorX, bool MirrorY) { + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////// +HRESULT CBSurface::DisplayTrans(int X, int Y, RECT rect, uint32 Alpha, TSpriteBlendMode BlendMode, bool MirrorX, bool MirrorY) { + return E_FAIL; +} + +////////////////////////////////////////////////////////////////////// +HRESULT CBSurface::DisplayTransOffset(int X, int Y, RECT rect, uint32 Alpha, TSpriteBlendMode BlendMode, bool MirrorX, bool MirrorY, int offsetX, int offsetY) { + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////// +HRESULT CBSurface::DisplayTransZoom(int X, int Y, RECT rect, float ZoomX, float ZoomY, uint32 Alpha, TSpriteBlendMode BlendMode, bool MirrorX, bool MirrorY) { + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////// +HRESULT CBSurface::DisplayZoom(int X, int Y, RECT rect, float ZoomX, float ZoomY, uint32 Alpha, bool Transparent, TSpriteBlendMode BlendMode, bool MirrorX, bool MirrorY) { + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////// +HRESULT CBSurface::DisplayHalfTrans(int X, int Y, RECT rect) { + return E_FAIL; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSurface::DisplayTransform(int X, int Y, int HotX, int HotY, RECT Rect, float ZoomX, float ZoomY, uint32 Alpha, float Rotate, TSpriteBlendMode BlendMode, bool MirrorX, bool MirrorY) { + return DisplayTransZoom(X, Y, Rect, ZoomX, ZoomY, Alpha, BlendMode, MirrorX, MirrorY); +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSurface::Create(int Width, int Height) { + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSurface::StartPixelOp() { + return E_FAIL; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSurface::EndPixelOp() { + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSurface::GetPixel(int X, int Y, byte *R, byte *G, byte *B, byte *A) { + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSurface::PutPixel(int X, int Y, byte R, byte G, byte B, int A) { + return E_FAIL; +} + + +////////////////////////////////////////////////////////////////////////// +bool CBSurface::ComparePixel(int X, int Y, byte R, byte G, byte B, int A) { + return false; +} + + +////////////////////////////////////////////////////////////////////// +bool CBSurface::IsTransparentAtLite(int X, int Y) { + return false; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSurface::Invalidate() { + return E_FAIL; +} + + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSurface::PrepareToDraw() { + m_LastUsedTime = Game->m_LiveTimer; + + if (!m_Valid) { + //Game->LOG(0, "Reviving: %s", m_Filename); + return Create(m_Filename, m_CKDefault, m_CKRed, m_CKGreen, m_CKBlue, m_LifeTime, m_KeepLoaded); + } else return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void CBSurface::SetFilename(const char *Filename) { + delete[] m_Filename; + m_Filename = NULL; + if (!Filename) return; + + m_Filename = new char[strlen(Filename) + 1]; + if (m_Filename) strcpy(m_Filename, Filename); +} + +////////////////////////////////////////////////////////////////////////// +void CBSurface::SetSize(int Width, int Height) { + m_Width = Width; + m_Height = Height; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BSurface.h b/engines/wintermute/BSurface.h new file mode 100644 index 0000000000..5fa355fcfa --- /dev/null +++ b/engines/wintermute/BSurface.h @@ -0,0 +1,93 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BSURFACE_H +#define WINTERMUTE_BSURFACE_H + +#include "BBase.h" + +namespace WinterMute { + +class CBSurface: public CBBase { +public: + virtual HRESULT Invalidate(); + virtual HRESULT PrepareToDraw(); + bool m_CKDefault; + byte m_CKRed; + byte m_CKGreen; + byte m_CKBlue; + + uint32 m_LastUsedTime; + bool m_Valid; + int m_LifeTime; + bool m_KeepLoaded; + + bool m_PixelOpReady; + CBSurface(CBGame *inGame); + virtual ~CBSurface(); + + virtual HRESULT DisplayHalfTrans(int X, int Y, RECT rect); + virtual bool IsTransparentAt(int X, int Y); + virtual HRESULT DisplayTransZoom(int X, int Y, RECT rect, float ZoomX, float ZoomY, uint32 Alpha = 0xFFFFFFFF, TSpriteBlendMode BlendMode = BLEND_NORMAL, bool MirrorX = false, bool MirrorY = false); + virtual HRESULT DisplayTrans(int X, int Y, RECT rect, uint32 Alpha = 0xFFFFFFFF, TSpriteBlendMode BlendMode = BLEND_NORMAL, bool MirrorX = false, bool MirrorY = false); + virtual HRESULT DisplayTransOffset(int X, int Y, RECT rect, uint32 Alpha = 0xFFFFFFFF, TSpriteBlendMode BlendMode = BLEND_NORMAL, bool MirrorX = false, bool MirrorY = false, int offsetX = 0, int offsetY = 0); + virtual HRESULT Display(int X, int Y, RECT rect, TSpriteBlendMode BlendMode = BLEND_NORMAL, bool MirrorX = false, bool MirrorY = false); + virtual HRESULT DisplayZoom(int X, int Y, RECT rect, float ZoomX, float ZoomY, uint32 Alpha = 0xFFFFFFFF, bool Transparent = false, TSpriteBlendMode BlendMode = BLEND_NORMAL, bool MirrorX = false, bool MirrorY = false); + virtual HRESULT DisplayTransform(int X, int Y, int HotX, int HotY, RECT Rect, float ZoomX, float ZoomY, uint32 Alpha, float Rotate, TSpriteBlendMode BlendMode = BLEND_NORMAL, bool MirrorX = false, bool MirrorY = false); + virtual HRESULT Restore(); + virtual HRESULT Create(char *Filename, bool default_ck, byte ck_red, byte ck_green, byte ck_blue, int LifeTime = -1, bool KeepLoaded = false); + virtual HRESULT Create(int Width, int Height); + virtual HRESULT PutPixel(int X, int Y, byte R, byte G, byte B, int A = -1); + virtual HRESULT GetPixel(int X, int Y, byte *R, byte *G, byte *B, byte *A = NULL); + virtual bool ComparePixel(int X, int Y, byte R, byte G, byte B, int A = -1); + virtual HRESULT StartPixelOp(); + virtual HRESULT EndPixelOp(); + virtual bool IsTransparentAtLite(int X, int Y); + void SetFilename(const char *Filename); + void SetSize(int Width, int Height); + + int m_ReferenceCount; + char *m_Filename; + + int GetWidth() { + return m_Width; + } + int GetHeight() { + return m_Height; + } + //void SetWidth(int Width){ m_Width = Width; } + //void SetHeight(int Height){ m_Height = Height; } +protected: + int m_Height; + int m_Width; + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BSurfaceSDL.cpp b/engines/wintermute/BSurfaceSDL.cpp new file mode 100644 index 0000000000..66c9256cf0 --- /dev/null +++ b/engines/wintermute/BSurfaceSDL.cpp @@ -0,0 +1,402 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BFile.h" +#include "BGame.h" +#include "BSurfaceSDL.h" +#include "BRenderSDL.h" +#include "SdlUtil.h" +#include "graphics/decoders/png.h" +#include "graphics/decoders/bmp.h" +#include "graphics/pixelformat.h" +#include "graphics/surface.h" +#include "stream.h" +#include "BFileManager.h" +#include "PlatformSDL.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CBSurfaceSDL::CBSurfaceSDL(CBGame *inGame) : CBSurface(inGame) { + m_Texture = NULL; + m_AlphaMask = NULL; + + m_LockPixels = NULL; + m_LockPitch = 0; +} + +////////////////////////////////////////////////////////////////////////// +CBSurfaceSDL::~CBSurfaceSDL() { + if (m_Texture) SDL_DestroyTexture(m_Texture); + delete[] m_AlphaMask; + m_AlphaMask = NULL; + + Game->AddMem(-m_Width * m_Height * 4); +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSurfaceSDL::Create(char *Filename, bool default_ck, byte ck_red, byte ck_green, byte ck_blue, int LifeTime, bool KeepLoaded) { + CBRenderSDL *renderer = static_cast(Game->m_Renderer); + Common::String strFileName(Filename); + + Graphics::ImageDecoder *imgDecoder; + + if (strFileName.hasSuffix(".png")) { + imgDecoder = new Graphics::PNGDecoder(); + } else if (strFileName.hasSuffix(".bmp")) { + imgDecoder = new Graphics::BitmapDecoder(); + } else { + error("CBSurfaceSDL::Create : Unsupported fileformat %s", Filename); + } + + CBFile *file = Game->m_FileManager->OpenFile(Filename); + if (!file) return E_FAIL; + + imgDecoder->loadStream(*file->getMemStream()); + const Graphics::Surface *surface = imgDecoder->getSurface(); + Game->m_FileManager->CloseFile(file); + + if (default_ck) { + ck_red = 255; + ck_green = 0; + ck_blue = 255; + } + + m_Width = surface->w; + m_Height = surface->h; + + bool isSaveGameGrayscale = scumm_strnicmp(Filename, "savegame:", 9) == 0 && (Filename[strFileName.size() - 1] == 'g' || Filename[strFileName.size() - 1] == 'G'); + if (isSaveGameGrayscale) { + warning("grayscaleConversion not yet implemented"); +/* FIBITMAP *newImg = FreeImage_ConvertToGreyscale(img); + if (newImg) { + FreeImage_Unload(img); + img = newImg; + }*/ + } + + // convert 32-bit BMPs to 24-bit or they appear totally transparent (does any app actually write alpha in BMP properly?) +/* if (FreeImage_GetBPP(img) != 32 || (imgFormat == FIF_BMP && FreeImage_GetBPP(img) != 24)) { + FIBITMAP *newImg = FreeImage_ConvertTo24Bits(img); + if (newImg) { + FreeImage_Unload(img); + img = newImg; + } else { + FreeImage_Unload(img); + return -1; + } + } + + FreeImage_FlipVertical(img);*/ + + //TODO: This is rather endian-specific, but should be replaced by non-SDL-code anyhow: + uint32 rmask = surface->format.rMax() << surface->format.rShift; + uint32 gmask = surface->format.gMax() << surface->format.gShift; + uint32 bmask = surface->format.bMax() << surface->format.bShift; + uint32 amask = surface->format.aMax(); + + SDL_Surface *surf = SDL_CreateRGBSurfaceFrom(surface->pixels, m_Width, m_Height, surface->format.bytesPerPixel * 8, surface->pitch, rmask, gmask, bmask, amask); + + // no alpha, set color key + if (surface->format.bytesPerPixel != 4) + SDL_SetColorKey(surf, SDL_TRUE, SDL_MapRGB(surf->format, ck_red, ck_green, ck_blue)); + + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best"); + //m_Texture = SdlUtil::CreateTextureFromSurface(renderer->GetSdlRenderer(), surf); + m_Texture = SDL_CreateTextureFromSurface(renderer->GetSdlRenderer(), surf); + if (!m_Texture) { + SDL_FreeSurface(surf); + delete imgDecoder; + return E_FAIL; + } + + GenAlphaMask(surf); + + SDL_FreeSurface(surf); + delete imgDecoder; // TODO: Update this if ImageDecoder doesn't end up owning the surface. + + m_CKDefault = default_ck; + m_CKRed = ck_red; + m_CKGreen = ck_green; + m_CKBlue = ck_blue; + + + if (!m_Filename || scumm_stricmp(m_Filename, Filename) != 0) { + SetFilename(Filename); + } + + if (m_LifeTime == 0 || LifeTime == -1 || LifeTime > m_LifeTime) + m_LifeTime = LifeTime; + + m_KeepLoaded = KeepLoaded; + if (m_KeepLoaded) m_LifeTime = -1; + + m_Valid = true; + + Game->AddMem(m_Width * m_Height * 4); + + + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +void CBSurfaceSDL::GenAlphaMask(SDL_Surface *surface) { + delete[] m_AlphaMask; + m_AlphaMask = NULL; + if (!surface) return; + + SDL_LockSurface(surface); + + bool hasColorKey; + Uint32 colorKey; + Uint8 ckRed, ckGreen, ckBlue; + if (SDL_GetColorKey(surface, &colorKey) == 0) { + hasColorKey = true; + SDL_GetRGB(colorKey, surface->format, &ckRed, &ckGreen, &ckBlue); + } else hasColorKey = false; + + m_AlphaMask = new byte[surface->w * surface->h]; + + bool hasTransparency = false; + for (int y = 0; y < surface->h; y++) { + for (int x = 0; x < surface->w; x++) { + Uint32 pixel = GetPixel(surface, x, y); + + Uint8 r, g, b, a; + SDL_GetRGBA(pixel, surface->format, &r, &g, &b, &a); + + if (hasColorKey && r == ckRed && g == ckGreen && b == ckBlue) + a = 0; + + m_AlphaMask[y * surface->w + x] = a; + if (a < 255) hasTransparency = true; + } + } + + SDL_UnlockSurface(surface); + + if (!hasTransparency) { + delete[] m_AlphaMask; + m_AlphaMask = NULL; + } +} + +////////////////////////////////////////////////////////////////////////// +Uint32 CBSurfaceSDL::GetPixel(SDL_Surface *surface, int x, int y) { + int bpp = surface->format->BytesPerPixel; + /* Here p is the address to the pixel we want to retrieve */ + Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; + + switch (bpp) { + case 1: + return *p; + break; + + case 2: + return *(Uint16 *)p; + break; + + case 3: + if (SDL_BYTEORDER == SDL_BIG_ENDIAN) + return p[0] << 16 | p[1] << 8 | p[2]; + else + return p[0] | p[1] << 8 | p[2] << 16; + break; + + case 4: + return *(Uint32 *)p; + break; + + default: + return 0; /* shouldn't happen, but avoids warnings */ + } +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSurfaceSDL::Create(int Width, int Height) { + CBRenderSDL *renderer = static_cast(Game->m_Renderer); + m_Texture = SDL_CreateTexture(renderer->GetSdlRenderer(), SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, Width, Height); + + m_Width = Width; + m_Height = Height; + + Game->AddMem(m_Width * m_Height * 4); + + m_Valid = true; + + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSurfaceSDL::CreateFromSDLSurface(SDL_Surface *surface) { + CBRenderSDL *renderer = static_cast(Game->m_Renderer); + m_Texture = SDL_CreateTextureFromSurface(renderer->GetSdlRenderer(), surface); + + m_Width = surface->w; + m_Height = surface->h; + + Game->AddMem(m_Width * m_Height * 4); + + m_Valid = true; + + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool CBSurfaceSDL::IsTransparentAt(int X, int Y) { + int access; + int width, height; + SDL_QueryTexture(m_Texture, NULL, &access, &width, &height); + //if (access != SDL_TEXTUREACCESS_STREAMING) return false; + if (X < 0 || X >= width || Y < 0 || Y >= height) return true; + + + StartPixelOp(); + bool ret = IsTransparentAtLite(X, Y); + EndPixelOp(); + + return ret; +} + +////////////////////////////////////////////////////////////////////////// +bool CBSurfaceSDL::IsTransparentAtLite(int X, int Y) { + //if (!m_LockPixels) return false; + + Uint32 format; + int access; + int width, height; + SDL_QueryTexture(m_Texture, &format, &access, &width, &height); + //if (access != SDL_TEXTUREACCESS_STREAMING) return false; + if (X < 0 || X >= width || Y < 0 || Y >= height) return true; + + if (!m_AlphaMask) return false; + else return m_AlphaMask[Y * width + X] <= 128; + + /* + Uint32* dst = (Uint32*)((Uint8*)m_LockPixels + Y * m_LockPitch); + Uint32 pixel = dst[X]; + + SDL_PixelFormat* pixelFormat = SDL_AllocFormat(format); + Uint8 r, g, b, a; + SDL_GetRGBA(pixel, pixelFormat, &r, &g, &b, &a); + SDL_FreeFormat(pixelFormat); + + return a <= 128; + */ +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSurfaceSDL::StartPixelOp() { + //SDL_LockTexture(m_Texture, NULL, &m_LockPixels, &m_LockPitch); + return S_OK; +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSurfaceSDL::EndPixelOp() { + //SDL_UnlockTexture(m_Texture); + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSurfaceSDL::Display(int X, int Y, RECT rect, TSpriteBlendMode BlendMode, bool MirrorX, bool MirrorY) { + return DrawSprite(X, Y, &rect, 100, 100, 0xFFFFFFFF, true, BlendMode, MirrorX, MirrorY); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSurfaceSDL::DisplayTrans(int X, int Y, RECT rect, uint32 Alpha, TSpriteBlendMode BlendMode, bool MirrorX, bool MirrorY) { + return DrawSprite(X, Y, &rect, 100, 100, Alpha, false, BlendMode, MirrorX, MirrorY); +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSurfaceSDL::DisplayTransOffset(int X, int Y, RECT rect, uint32 Alpha, TSpriteBlendMode BlendMode, bool MirrorX, bool MirrorY, int offsetX, int offsetY) { + return DrawSprite(X, Y, &rect, 100, 100, Alpha, false, BlendMode, MirrorX, MirrorY, offsetX, offsetY); +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSurfaceSDL::DisplayTransZoom(int X, int Y, RECT rect, float ZoomX, float ZoomY, uint32 Alpha, TSpriteBlendMode BlendMode, bool MirrorX, bool MirrorY) { + return DrawSprite(X, Y, &rect, ZoomX, ZoomY, Alpha, false, BlendMode, MirrorX, MirrorY); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSurfaceSDL::DisplayZoom(int X, int Y, RECT rect, float ZoomX, float ZoomY, uint32 Alpha, bool Transparent, TSpriteBlendMode BlendMode, bool MirrorX, bool MirrorY) { + return DrawSprite(X, Y, &rect, ZoomX, ZoomY, Alpha, !Transparent, BlendMode, MirrorX, MirrorY); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSurfaceSDL::DisplayTransform(int X, int Y, int HotX, int HotY, RECT Rect, float ZoomX, float ZoomY, uint32 Alpha, float Rotate, TSpriteBlendMode BlendMode, bool MirrorX, bool MirrorY) { + return DrawSprite(X, Y, &Rect, ZoomX, ZoomY, Alpha, false, BlendMode, MirrorX, MirrorY); +} + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSurfaceSDL::DrawSprite(int X, int Y, RECT *Rect, float ZoomX, float ZoomY, uint32 Alpha, bool AlphaDisable, TSpriteBlendMode BlendMode, bool MirrorX, bool MirrorY, int offsetX, int offsetY) { + CBRenderSDL *renderer = static_cast(Game->m_Renderer); + + if (renderer->m_ForceAlphaColor != 0) Alpha = renderer->m_ForceAlphaColor; + + byte r = D3DCOLGetR(Alpha); + byte g = D3DCOLGetG(Alpha); + byte b = D3DCOLGetB(Alpha); + byte a = D3DCOLGetA(Alpha); + + SDL_SetTextureColorMod(m_Texture, r, g, b); + SDL_SetTextureAlphaMod(m_Texture, a); + + if (AlphaDisable) + SDL_SetTextureBlendMode(m_Texture, SDL_BLENDMODE_NONE); + else + SDL_SetTextureBlendMode(m_Texture, SDL_BLENDMODE_BLEND); + + SDL_Rect srcRect; + srcRect.x = Rect->left; + srcRect.y = Rect->top; + srcRect.w = Rect->right - Rect->left; + srcRect.h = Rect->bottom - Rect->top; + + SDL_Rect position; + position.x = X; + position.y = Y; + position.w = (float)srcRect.w * ZoomX / 100.f; + position.h = (float)srcRect.h * ZoomX / 100.f; + + renderer->ModTargetRect(&position); + + position.x += offsetX; + position.y += offsetY; + + SDL_RenderCopy(renderer->GetSdlRenderer(), m_Texture, &srcRect, &position); + + + return S_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BSurfaceSDL.h b/engines/wintermute/BSurfaceSDL.h new file mode 100644 index 0000000000..e32bec90b1 --- /dev/null +++ b/engines/wintermute/BSurfaceSDL.h @@ -0,0 +1,79 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BSURFACESDL_H +#define WINTERMUTE_BSURFACESDL_H + +#include "BSurface.h" +class SDL_Texture; +class SDL_Surface; +namespace WinterMute { + +class CBSurfaceSDL : public CBSurface { +public: + CBSurfaceSDL(CBGame *inGame); + ~CBSurfaceSDL(); + + HRESULT Create(char *Filename, bool default_ck, byte ck_red, byte ck_green, byte ck_blue, int LifeTime = -1, bool KeepLoaded = false); + HRESULT Create(int Width, int Height); + + HRESULT CreateFromSDLSurface(SDL_Surface *surface); + + bool IsTransparentAt(int X, int Y); + bool IsTransparentAtLite(int X, int Y); + + HRESULT StartPixelOp(); + HRESULT EndPixelOp(); + + + HRESULT DisplayTransZoom(int X, int Y, RECT rect, float ZoomX, float ZoomY, uint32 Alpha = 0xFFFFFFFF, TSpriteBlendMode BlendMode = BLEND_NORMAL, bool MirrorX = false, bool MirrorY = false); + HRESULT DisplayTrans(int X, int Y, RECT rect, uint32 Alpha = 0xFFFFFFFF, TSpriteBlendMode BlendMode = BLEND_NORMAL, bool MirrorX = false, bool MirrorY = false); + HRESULT DisplayTransOffset(int X, int Y, RECT rect, uint32 Alpha = 0xFFFFFFFF, TSpriteBlendMode BlendMode = BLEND_NORMAL, bool MirrorX = false, bool MirrorY = false, int offsetX = 0, int offsetY = 0); + HRESULT Display(int X, int Y, RECT rect, TSpriteBlendMode BlendMode = BLEND_NORMAL, bool MirrorX = false, bool MirrorY = false); + HRESULT DisplayZoom(int X, int Y, RECT rect, float ZoomX, float ZoomY, uint32 Alpha = 0xFFFFFFFF, bool Transparent = false, TSpriteBlendMode BlendMode = BLEND_NORMAL, bool MirrorX = false, bool MirrorY = false); + HRESULT DisplayTransform(int X, int Y, int HotX, int HotY, RECT Rect, float ZoomX, float ZoomY, uint32 Alpha, float Rotate, TSpriteBlendMode BlendMode = BLEND_NORMAL, bool MirrorX = false, bool MirrorY = false); + +/* static unsigned DLL_CALLCONV ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle); + static int DLL_CALLCONV SeekProc(fi_handle handle, long offset, int origin); + static long DLL_CALLCONV TellProc(fi_handle handle);*/ + +private: + SDL_Texture *m_Texture; + + HRESULT DrawSprite(int X, int Y, RECT *Rect, float ZoomX, float ZoomY, uint32 Alpha, bool AlphaDisable, TSpriteBlendMode BlendMode, bool MirrorX, bool MirrorY, int offsetX = 0, int offsetY = 0); + void GenAlphaMask(SDL_Surface *surface); + uint32 GetPixel(SDL_Surface *surface, int x, int y); + + void *m_LockPixels; + int m_LockPitch; + byte *m_AlphaMask; +}; + +} // end of namespace WinterMute + +#endif // __WmeBSurfaceSDL_H__ diff --git a/engines/wintermute/BSurfaceStorage.cpp b/engines/wintermute/BSurfaceStorage.cpp new file mode 100644 index 0000000000..45f70db8f6 --- /dev/null +++ b/engines/wintermute/BSurfaceStorage.cpp @@ -0,0 +1,192 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BSurfaceStorage.h" +#include "BSurfaceSDL.h" +#include "BGame.h" +#include "BFileManager.h" +#include "PlatformSDL.h" +#include "common/str.h" + +namespace WinterMute { + +//IMPLEMENT_PERSISTENT(CBSurfaceStorage, true); + +////////////////////////////////////////////////////////////////////// +CBSurfaceStorage::CBSurfaceStorage(CBGame *inGame): CBBase(inGame) { + m_LastCleanupTime = 0; +} + + +////////////////////////////////////////////////////////////////////// +CBSurfaceStorage::~CBSurfaceStorage() { + Cleanup(true); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSurfaceStorage::Cleanup(bool Warn) { + for (int i = 0; i < m_Surfaces.GetSize(); i++) { + if (Warn) Game->LOG(0, "CBSurfaceStorage warning: purging surface '%s', usage:%d", m_Surfaces[i]->m_Filename, m_Surfaces[i]->m_ReferenceCount); + delete m_Surfaces[i]; + } + m_Surfaces.RemoveAll(); + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSurfaceStorage::InitLoop() { + if (Game->m_SmartCache && Game->m_LiveTimer - m_LastCleanupTime >= Game->m_SurfaceGCCycleTime) { + m_LastCleanupTime = Game->m_LiveTimer; + SortSurfaces(); + for (int i = 0; i < m_Surfaces.GetSize(); i++) { + if (m_Surfaces[i]->m_LifeTime <= 0) break; + + if (m_Surfaces[i]->m_LifeTime > 0 && m_Surfaces[i]->m_Valid && Game->m_LiveTimer - m_Surfaces[i]->m_LastUsedTime >= m_Surfaces[i]->m_LifeTime) { + //Game->QuickMessageForm("Invalidating: %s", m_Surfaces[i]->m_Filename); + m_Surfaces[i]->Invalidate(); + } + } + } + return S_OK; +} + + +////////////////////////////////////////////////////////////////////// +HRESULT CBSurfaceStorage::RemoveSurface(CBSurface *surface) { + for (int i = 0; i < m_Surfaces.GetSize(); i++) { + if (m_Surfaces[i] == surface) { + m_Surfaces[i]->m_ReferenceCount--; + if (m_Surfaces[i]->m_ReferenceCount <= 0) { + delete m_Surfaces[i]; + m_Surfaces.RemoveAt(i); + } + break; + } + } + return S_OK; +} + + +////////////////////////////////////////////////////////////////////// +CBSurface *CBSurfaceStorage::AddSurface(char *Filename, bool default_ck, byte ck_red, byte ck_green, byte ck_blue, int LifeTime, bool KeepLoaded) { + for (int i = 0; i < m_Surfaces.GetSize(); i++) { + if (scumm_stricmp(m_Surfaces[i]->m_Filename, Filename) == 0) { + m_Surfaces[i]->m_ReferenceCount++; + return m_Surfaces[i]; + } + } + + CBFile *File = Game->m_FileManager->OpenFile(Filename); + if (!File) { + if (Filename) Game->LOG(0, "Missing image: '%s'", Filename); + if (Game->m_DEBUG_DebugMode) + return AddSurface("invalid_debug.bmp", default_ck, ck_red, ck_green, ck_blue, LifeTime, KeepLoaded); + else + return AddSurface("invalid.bmp", default_ck, ck_red, ck_green, ck_blue, LifeTime, KeepLoaded); + } else Game->m_FileManager->CloseFile(File); + + + CBSurface *surface; + surface = new CBSurfaceSDL(Game); + + + if (!surface) return NULL; + + if (FAILED(surface->Create(Filename, default_ck, ck_red, ck_green, ck_blue, LifeTime, KeepLoaded))) { + delete surface; + return NULL; + } else { + surface->m_ReferenceCount = 1; + m_Surfaces.Add(surface); + return surface; + } +} + + +////////////////////////////////////////////////////////////////////// +HRESULT CBSurfaceStorage::RestoreAll() { + HRESULT ret; + for (int i = 0; i < m_Surfaces.GetSize(); i++) { + ret = m_Surfaces[i]->Restore(); + if (ret != S_OK) { + Game->LOG(0, "CBSurfaceStorage::RestoreAll failed"); + return ret; + } + } + return S_OK; +} + + +/* +////////////////////////////////////////////////////////////////////////// +HRESULT CBSurfaceStorage::Persist(CBPersistMgr *PersistMgr) +{ + + if(!PersistMgr->m_Saving) Cleanup(false); + + PersistMgr->Transfer(TMEMBER(Game)); + + //m_Surfaces.Persist(PersistMgr); + + return S_OK; +} +*/ + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBSurfaceStorage::SortSurfaces() { + qsort(m_Surfaces.GetData(), m_Surfaces.GetSize(), sizeof(CBSurface *), SurfaceSortCB); + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +int CBSurfaceStorage::SurfaceSortCB(const void *arg1, const void *arg2) { + CBSurface *s1 = *((CBSurface **)arg1); + CBSurface *s2 = *((CBSurface **)arg2); + + // sort by life time + if (s1->m_LifeTime <= 0 && s2->m_LifeTime > 0) return 1; + else if (s1->m_LifeTime > 0 && s2->m_LifeTime <= 0) return -1; + + + // sort by validity + if (s1->m_Valid && !s2->m_Valid) return -1; + else if (!s1->m_Valid && s2->m_Valid) return 1; + + // sort by time + else if (s1->m_LastUsedTime > s2->m_LastUsedTime) return 1; + else if (s1->m_LastUsedTime < s2->m_LastUsedTime) return -1; + else return 0; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BSurfaceStorage.h b/engines/wintermute/BSurfaceStorage.h new file mode 100644 index 0000000000..5ebfe3c7d7 --- /dev/null +++ b/engines/wintermute/BSurfaceStorage.h @@ -0,0 +1,58 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BSURFACESTORAGE_H +#define WINTERMUTE_BSURFACESTORAGE_H + + +#include "coll_templ.h" +#include "BBase.h" + +namespace WinterMute { +class CBSurface; +class CBSurfaceStorage : public CBBase { +public: + uint32 m_LastCleanupTime; + HRESULT InitLoop(); + HRESULT SortSurfaces(); + static int SurfaceSortCB(const void *arg1, const void *arg2); + HRESULT Cleanup(bool Warn = false); + //DECLARE_PERSISTENT(CBSurfaceStorage, CBBase); + + HRESULT RestoreAll(); + CBSurface *AddSurface(char *Filename, bool default_ck = true, byte ck_red = 0, byte ck_green = 0, byte ck_blue = 0, int LifeTime = -1, bool KeepLoaded = false); + HRESULT RemoveSurface(CBSurface *surface); + CBSurfaceStorage(CBGame *inGame); + virtual ~CBSurfaceStorage(); + + CBArray m_Surfaces; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BTransitionMgr.cpp b/engines/wintermute/BTransitionMgr.cpp new file mode 100644 index 0000000000..56703b3336 --- /dev/null +++ b/engines/wintermute/BTransitionMgr.cpp @@ -0,0 +1,126 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include "BTransitionMgr.h" +#include "BGame.h" +#include "PlatformSDL.h" + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +CBTransitionMgr::CBTransitionMgr(CBGame *inGame): CBBase(inGame) { + m_State = TRANS_MGR_READY; + m_Type = TRANSITION_NONE; + m_OrigInteractive = false; + m_PreserveInteractive = false; + m_LastTime = 0; + m_Started = false; +} + + + +////////////////////////////////////////////////////////////////////////// +CBTransitionMgr::~CBTransitionMgr() { + +} + + +////////////////////////////////////////////////////////////////////////// +bool CBTransitionMgr::IsReady() { + return (m_State == TRANS_MGR_READY); +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBTransitionMgr::Start(TTransitionType Type, bool NonInteractive) { + if (m_State != TRANS_MGR_READY) return S_OK; + + if (Type == TRANSITION_NONE || Type >= NUM_TRANSITION_TYPES) { + m_State = TRANS_MGR_READY; + return S_OK; + } + + if (NonInteractive) { + m_PreserveInteractive = true; + m_OrigInteractive = Game->m_Interactive; + Game->m_Interactive = false; + } else m_PreserveInteractive; + + m_Type = Type; + m_State = TRANS_MGR_RUNNING; + m_Started = false; + + return S_OK; +} + +#define FADE_DURATION 200 + +////////////////////////////////////////////////////////////////////////// +HRESULT CBTransitionMgr::Update() { + if (IsReady()) return S_OK; + + if (!m_Started) { + m_Started = true; + m_LastTime = CBPlatform::GetTime(); + } + + switch (m_Type) { + case TRANSITION_NONE: + m_State = TRANS_MGR_READY; + break; + + case TRANSITION_FADE_OUT: { + uint32 time = CBPlatform::GetTime() - m_LastTime; + int Alpha = 255 - (float)time / (float)FADE_DURATION * 255; + Alpha = std::min(255, std::max(Alpha, 0)); + Game->m_Renderer->Fade((WORD)Alpha); + + if (time > FADE_DURATION) m_State = TRANS_MGR_READY; + } + break; + + case TRANSITION_FADE_IN: { + uint32 time = CBPlatform::GetTime() - m_LastTime; + int Alpha = (float)time / (float)FADE_DURATION * 255; + Alpha = std::min(255, std::max(Alpha, 0)); + Game->m_Renderer->Fade((WORD)Alpha); + + if (time > FADE_DURATION) m_State = TRANS_MGR_READY; + } + break; + + } + + if (IsReady()) { + if (m_PreserveInteractive) Game->m_Interactive = m_OrigInteractive; + } + return S_OK; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BTransitionMgr.h b/engines/wintermute/BTransitionMgr.h new file mode 100644 index 0000000000..6bcf3ea89b --- /dev/null +++ b/engines/wintermute/BTransitionMgr.h @@ -0,0 +1,54 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BTRANSITIONMGR_H +#define WINTERMUTE_BTRANSITIONMGR_H + +#include "BBase.h" + +namespace WinterMute { + +class CBTransitionMgr : public CBBase { +public: + bool m_Started; + uint32 m_LastTime; + bool m_OrigInteractive; + bool m_PreserveInteractive; + HRESULT Update(); + HRESULT Start(TTransitionType Type, bool NonInteractive = false); + bool IsReady(); + TTransMgrState m_State; + CBTransitionMgr(CBGame *inGame); + virtual ~CBTransitionMgr(); + TTransitionType m_Type; + +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/BViewport.cpp b/engines/wintermute/BViewport.cpp new file mode 100644 index 0000000000..bb2f5b6b29 --- /dev/null +++ b/engines/wintermute/BViewport.cpp @@ -0,0 +1,98 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "BGame.h" +#include "PlatformSDL.h" +#include "BViewport.h" + +namespace WinterMute { + +IMPLEMENT_PERSISTENT(CBViewport, false) + +////////////////////////////////////////////////////////////////////////// +CBViewport::CBViewport(CBGame *inGame): CBBase(inGame) { + CBPlatform::SetRectEmpty(&m_Rect); + m_MainObject = NULL; + m_OffsetX = m_OffsetY = 0; +} + + +////////////////////////////////////////////////////////////////////////// +CBViewport::~CBViewport() { + +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBViewport::Persist(CBPersistMgr *PersistMgr) { + + PersistMgr->Transfer(TMEMBER(Game)); + + PersistMgr->Transfer(TMEMBER(m_MainObject)); + PersistMgr->Transfer(TMEMBER(m_OffsetX)); + PersistMgr->Transfer(TMEMBER(m_OffsetY)); + PersistMgr->Transfer(TMEMBER(m_Rect)); + + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +HRESULT CBViewport::SetRect(int left, int top, int right, int bottom, bool NoCheck) { + if (!NoCheck) { + left = std::max(left, 0); + top = std::max(top, 0); + right = std::min(right, Game->m_Renderer->m_Width); + bottom = std::min(bottom, Game->m_Renderer->m_Height); + } + + CBPlatform::SetRect(&m_Rect, left, top, right, bottom); + m_OffsetX = left; + m_OffsetY = top; + return S_OK; +} + + +////////////////////////////////////////////////////////////////////////// +RECT *CBViewport::GetRect() { + return &m_Rect; +} + + +////////////////////////////////////////////////////////////////////////// +int CBViewport::GetWidth() { + return m_Rect.right - m_Rect.left; +} + + +////////////////////////////////////////////////////////////////////////// +int CBViewport::GetHeight() { + return m_Rect.bottom - m_Rect.top; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/BViewport.h b/engines/wintermute/BViewport.h new file mode 100644 index 0000000000..06a5a1952f --- /dev/null +++ b/engines/wintermute/BViewport.h @@ -0,0 +1,55 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BVIEWPORT_H +#define WINTERMUTE_BVIEWPORT_H + + +#include "BBase.h" + +namespace WinterMute { +class CBObject; +class CBViewport : public CBBase { +public: + int GetHeight(); + int GetWidth(); + RECT *GetRect(); + HRESULT SetRect(int left, int top, int right, int bottom, bool NoCheck = false); + DECLARE_PERSISTENT(CBViewport, CBBase) + int m_OffsetY; + int m_OffsetX; + CBObject *m_MainObject; + CBViewport(CBGame *inGame = NULL); + virtual ~CBViewport(); +private: + RECT m_Rect; +}; + +} // end of namespace WinterMute + +#endif diff --git a/engines/wintermute/PathUtil.cpp b/engines/wintermute/PathUtil.cpp new file mode 100644 index 0000000000..d7d632f398 --- /dev/null +++ b/engines/wintermute/PathUtil.cpp @@ -0,0 +1,196 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#include "dcgf.h" +#include +#include +#include "PathUtil.h" +#include "StringUtil.h" + + +#ifdef __WIN32__ +# include +#endif + +#ifdef __MACOSX__ +# include +#endif + +#ifdef __IPHONEOS__ +# include "ios_utils.h" +#endif + +namespace WinterMute { + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::UnifySeparators(const AnsiString &path) { + AnsiString newPath = path; + + std::replace(newPath.begin(), newPath.end(), L'\\', L'/'); + return newPath; +} + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::NormalizeFileName(const AnsiString &path) { + AnsiString newPath = UnifySeparators(path); + StringUtil::ToLowerCase(newPath); + return newPath; +} + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::Combine(const AnsiString &path1, const AnsiString &path2) { + AnsiString newPath1 = UnifySeparators(path1); + AnsiString newPath2 = UnifySeparators(path2); + + if (!StringUtil::EndsWith(newPath1, "/", true) && !StringUtil::StartsWith(newPath2, "/", true)) + newPath1 += "/"; + + return newPath1 + newPath2; +} + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::GetDirectoryName(const AnsiString &path) { + AnsiString newPath = UnifySeparators(path); + + size_t pos = newPath.find_last_of(L'/'); + + if (pos == AnsiString::npos) return ""; + else return newPath.substr(0, pos + 1); +} + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::GetFileName(const AnsiString &path) { + AnsiString newPath = UnifySeparators(path); + + size_t pos = newPath.find_last_of(L'/'); + + if (pos == AnsiString::npos) return path; + else return newPath.substr(pos + 1); +} + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::GetFileNameWithoutExtension(const AnsiString &path) { + AnsiString fileName = GetFileName(path); + + size_t pos = fileName.find_last_of('.'); + + if (pos == AnsiString::npos) return fileName; + else return fileName.substr(0, pos); +} + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::GetExtension(const AnsiString &path) { + AnsiString fileName = GetFileName(path); + + size_t pos = fileName.find_last_of('.'); + + if (pos == AnsiString::npos) return ""; + else return fileName.substr(pos); +} + + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::GetSafeLogFileName() { + AnsiString logFileName = GetUserDirectory(); + +#ifdef __WIN32__ + char moduleName[MAX_PATH]; + ::GetModuleFileName(NULL, moduleName, MAX_PATH); + + AnsiString fileName = GetFileNameWithoutExtension(moduleName) + ".log"; + fileName = Combine("/Wintermute Engine/Logs/", fileName); + logFileName = Combine(logFileName, fileName); + +#else + // !PORTME + logFileName = Combine(logFileName, "/Wintermute Engine/wme.log"); +#endif + + CreateDirectory(GetDirectoryName(logFileName)); + return logFileName; +} + +////////////////////////////////////////////////////////////////////////// +bool PathUtil::CreateDirectory(const AnsiString &path) { + return false; +} + +////////////////////////////////////////////////////////////////////////// +bool PathUtil::MatchesMask(const AnsiString &fileName, const AnsiString &mask) { + return false; +} + +////////////////////////////////////////////////////////////////////////// +bool PathUtil::FileExists(const AnsiString &fileName) { + std::ifstream stream; + + stream.open(fileName.c_str()); + bool ret = stream.is_open(); + stream.close(); + + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::GetUserDirectory() { + AnsiString userDir = "./"; + +#ifdef __WIN32__ + char buffer[MAX_PATH]; + buffer[0] = '\0'; + LPITEMIDLIST pidl = NULL; + LPMALLOC pMalloc; + if (SUCCEEDED(SHGetMalloc(&pMalloc))) { + SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &pidl); + if (pidl) { + SHGetPathFromIDList(pidl, buffer); + } + pMalloc->Free(pidl); + userDir = AnsiString(buffer); + } +#elif __MACOSX__ + FSRef fileRef; + OSStatus error = FSFindFolder(kUserDomain, kApplicationSupportFolderType, true, &fileRef); + if (error == noErr) { + char buffer[MAX_PATH]; + error = FSRefMakePath(&fileRef, (UInt8 *)buffer, sizeof(buffer)); + if (error == noErr) + userDir = buffer; + + } +#elif __IPHONEOS__ + char path[MAX_PATH]; + IOS_GetDataDir(path); + userDir = AnsiString(path); +#endif + + return userDir; +} + +} // end of namespace WinterMute diff --git a/engines/wintermute/PathUtil.h b/engines/wintermute/PathUtil.h new file mode 100644 index 0000000000..72dcf806b1 --- /dev/null +++ b/engines/wintermute/PathUtil.h @@ -0,0 +1,56 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_BPATHUTILS_H +#define WINTERMUTE_BPATHUTILS_H + +#include "PlatformSDL.h" + +namespace WinterMute { + +class PathUtil { +public: + static AnsiString UnifySeparators(const AnsiString &path); + static AnsiString NormalizeFileName(const AnsiString &path); + static AnsiString Combine(const AnsiString &path1, const AnsiString &path2); + static AnsiString GetDirectoryName(const AnsiString &path); + static AnsiString GetFileName(const AnsiString &path); + static AnsiString GetFileNameWithoutExtension(const AnsiString &path); + static AnsiString GetExtension(const AnsiString &path); + static bool CreateDirectory(const AnsiString &path); + static bool MatchesMask(const AnsiString &fileName, const AnsiString &mask); + + static bool FileExists(const AnsiString &fileName); + + static AnsiString GetSafeLogFileName(); + static AnsiString GetUserDirectory(); +}; + +} // end of namespace WinterMute + +#endif // __WmePathUtils_H__ diff --git a/engines/wintermute/StringUtil.cpp b/engines/wintermute/StringUtil.cpp index 6a42857615..f3b4e0c0db 100644 --- a/engines/wintermute/StringUtil.cpp +++ b/engines/wintermute/StringUtil.cpp @@ -1,27 +1,30 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + /* -This file is part of WME Lite. -http://dead-code.org/redir.php?target=wmelite - -Copyright (c) 2011 Jan Nedoma - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ #include "dcgf.h" #include diff --git a/engines/wintermute/StringUtil.h b/engines/wintermute/StringUtil.h index 20758ed0cd..80c95ced03 100644 --- a/engines/wintermute/StringUtil.h +++ b/engines/wintermute/StringUtil.h @@ -1,30 +1,33 @@ -/* -This file is part of WME Lite. -http://dead-code.org/redir.php?target=wmelite - -Copyright (c) 2011 Jan Nedoma - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ +/* + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ -#ifndef __WmeStringUtil_H__ -#define __WmeStringUtil_H__ +#ifndef WINTERMUTE_STRINGUTIL_H +#define WINTERMUTE_STRINGUTIL_H #include "PlatformSDL.h" diff --git a/engines/wintermute/SysClass.h b/engines/wintermute/SysClass.h index ede3d41c22..48d7a2626e 100644 --- a/engines/wintermute/SysClass.h +++ b/engines/wintermute/SysClass.h @@ -1,27 +1,30 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + /* -This file is part of WME Lite. -http://dead-code.org/redir.php?target=wmelite - -Copyright (c) 2011 Jan Nedoma - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ #ifndef WINTERMUTE_SYSCLASS_H #define WINTERMUTE_SYSCLASS_H diff --git a/engines/wintermute/module.mk b/engines/wintermute/module.mk index 45708e2b84..a33861cd19 100644 --- a/engines/wintermute/module.mk +++ b/engines/wintermute/module.mk @@ -12,6 +12,7 @@ MODULE_OBJS := \ BNamedObject.o \ BParser.o \ BScriptable.o \ + BViewport.o \ detection.o \ SysClass.o \ SysInstance.o \ diff --git a/engines/wintermute/persistent.h b/engines/wintermute/persistent.h index 5d0b7ee5fb..130e080e79 100644 --- a/engines/wintermute/persistent.h +++ b/engines/wintermute/persistent.h @@ -24,7 +24,6 @@ * This file is based on WME Lite. * http://dead-code.org/redir.php?target=wmelite * Copyright (c) 2011 Jan Nedoma - */ #ifndef WINTERMUTE_PERSISTENT_H diff --git a/engines/wintermute/utils.cpp b/engines/wintermute/utils.cpp index dd649d8afd..c69a0068b6 100644 --- a/engines/wintermute/utils.cpp +++ b/engines/wintermute/utils.cpp @@ -1,27 +1,30 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + /* -This file is part of WME Lite. -http://dead-code.org/redir.php?target=wmelite - -Copyright (c) 2011 Jan Nedoma - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ #include "dcgf.h" #include "utils.h" diff --git a/engines/wintermute/utils.h b/engines/wintermute/utils.h index 56d9876c5c..6fdac018ce 100644 --- a/engines/wintermute/utils.h +++ b/engines/wintermute/utils.h @@ -1,30 +1,33 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + /* -This file is part of WME Lite. -http://dead-code.org/redir.php?target=wmelite - -Copyright (c) 2011 Jan Nedoma - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#ifndef __WmeUtils_H__ -#define __WmeUtils_H__ + * This file is based on WME Lite. + * http://dead-code.org/redir.php?target=wmelite + * Copyright (c) 2011 Jan Nedoma + */ + +#ifndef WINTERMUTE_UTILS_H +#define WINTERMUTE_UTILS_H #include "wintypes.h" -- cgit v1.2.3