From dc5dc9f653c03d72066f7e59df8b265bc28cb84a Mon Sep 17 00:00:00 2001 From: g-cont Date: Fri, 8 Jul 2011 00:00:00 +0400 Subject: [PATCH] 08 Jul 2011 --- change.log | 33 +- cl_dll/cl_dll.plg | 16 + cl_dll/parsemsg.cpp | 2 +- common/com_model.h | 3 +- dlls/cbase.h | 1 + dlls/h_export.cpp | 2 +- dlls/hl.plg | 141 ++ dlls/physcallback.h | 28 + dlls/util.h | 5 + dlls/weapons.cpp | 1 + dlls/world.cpp | 110 ++ engine/cdll_int.h | 90 + engine/client/cl_frame.c | 8 +- engine/client/cl_game.c | 4 +- engine/client/cl_main.c | 85 +- engine/client/cl_menu.c | 1 - engine/client/cl_parse.c | 103 +- engine/client/cl_scrn.c | 7 +- engine/client/cl_tent.c | 87 +- engine/client/cl_view.c | 1 + engine/client/client.h | 9 +- engine/client/gl_backend.c | 14 +- engine/client/gl_beams.c | 2 +- engine/client/gl_decals.c | 2 + engine/client/gl_export.h | 4 +- engine/client/gl_image.c | 112 +- engine/client/gl_local.h | 15 +- engine/client/gl_rlight.c | 12 +- engine/client/gl_rmain.c | 14 +- engine/client/gl_rmisc.c | 255 +++ engine/client/gl_rsurf.c | 240 +-- engine/client/gl_rsurf.old | 1217 ++++++++----- engine/client/gl_sprite.c | 14 +- engine/client/gl_studio.c | 28 +- engine/client/gl_vidnt.c | 34 +- engine/client/gl_warp.c | 9 +- engine/client/s_mix.c | 6 + engine/client/sound.h | 1 + engine/common/build.c | 2 +- engine/common/cmd.c | 10 +- engine/common/common.c | 6 +- engine/common/common.h | 4 +- engine/common/console.c | 387 +++-- engine/common/crtlib.h | 5 +- engine/common/cvar.c | 2 +- engine/common/imagelib/img_bmp.c | 51 +- engine/common/imagelib/img_tga.c | 2 +- engine/common/imagelib/img_utils.c | 2 +- engine/common/imagelib/img_wad.c | 12 +- engine/common/keys.c | 12 +- engine/common/library.c | 3 +- engine/common/model.c | 54 +- engine/common/netchan.h | 3 + engine/common/network.c | 2 +- engine/common/protocol.h | 17 +- engine/common/soundlib/mpeg.lib | Bin 143350 -> 62114 bytes engine/common/soundlib/mpeg.old | Bin 0 -> 143350 bytes engine/common/soundlib/snd_mp3.c | 460 ++--- engine/common/soundlib/snd_mp3.old | 480 ++++++ engine/common/soundlib/snd_wav.c | 2 +- engine/eiface.h | 18 +- engine/physint.h | 38 + engine/server/server.h | 12 +- engine/server/sv_client.c | 149 +- engine/server/sv_cmds.c | 46 - engine/server/sv_frame.c | 1 + engine/server/sv_game.c | 335 +++- engine/server/sv_init.c | 9 +- engine/server/sv_main.c | 66 +- engine/server/sv_phys.c | 63 +- engine/server/sv_pmove.c | 2 +- engine/server/sv_world.c | 5 +- mainui/basemenu.cpp | 51 +- mainui/basemenu.h | 3 + mainui/mainui.dsp | 16 +- mainui/menu_advcontrols.cpp | 5 +- mainui/menu_btns.cpp | 14 +- mainui/menu_btnsbmp_table.h | 4 +- mainui/menu_internetgames.cpp | 467 +++++ mainui/menu_langame.cpp | 1 + mainui/menu_main.cpp | 83 +- mainui/menu_multiplayer.cpp | 4 +- mainui/menu_newgame.cpp | 35 +- mainui/menu_strings.cpp | 634 +++++++ mainui/menu_strings.h | 39 + mainui/menu_vidmodes.cpp | 4 +- mainui/menufont.H | 2553 ++++++++++++++++++++++++++++ mainui/utils.cpp | 10 + mainui/utils.h | 3 + 89 files changed, 7466 insertions(+), 1436 deletions(-) create mode 100644 cl_dll/cl_dll.plg create mode 100644 dlls/hl.plg create mode 100644 dlls/physcallback.h create mode 100644 engine/common/soundlib/mpeg.old create mode 100644 engine/common/soundlib/snd_mp3.old create mode 100644 engine/physint.h create mode 100644 mainui/menu_internetgames.cpp create mode 100644 mainui/menu_strings.cpp create mode 100644 mainui/menu_strings.h create mode 100644 mainui/menufont.H diff --git a/change.log b/change.log index 507ee55c..fc5c27fe 100644 --- a/change.log +++ b/change.log @@ -1,8 +1,35 @@ build ???? -Fixed wrong sound angles whe client see in the camera -Fix crash on change gl_texturemode. -Change relationsip for GetLocalPlayer. Now it's always valid. +Client: fix drawing beams for 'solid' mode +Image: fix BMP loader for 4-bit color bmp's +Client: fix lightlevel calculating for local client (remove 'ambient' base from final value) +GameUI: first implementation of custom strings and support 'strings.lst' parsing +GameUI: replace unneeded button 'credits' with button 'previews' +Render: fix sprite interpolation +Render: fix angled sprites offset +Render: implement detail textures like in Steam Half-Life (thx n00b) +Client: rework env_funnel effect + +build 1598 + +Client: fix crosshair drawing +Sound: change libmad mp3 decoder on a mpg123 +Client: fix gibs randomization for TE_BREAKMODEL +Engine: fix modelloader bug (engine crash after not found map) +Video: add resolution 1366x768 +GameUI: fix skill select +Network: change 'svc_setangle' message, include rollangle +Render: fix chrome rendering on a studiomodels +Render: added video memory economy mode - cvar 'gl_luminance_textures' +GameDLL: first implementation of extended engineinterface. Metamod is supported now + +build 1557 + +Sound: fixed wrong sound angles when client see in the camera +Render: fix crash on change gl_texturemode and gl_anisotropy. +Client: change relationsip for GetLocalPlayer. Now it's always valid. +Server: rewrite SV_Multicast for correct work with custom user cameras +Server: rewrite FIND_CLIENT_IN_PVS like in QW build 1540 diff --git a/cl_dll/cl_dll.plg b/cl_dll/cl_dll.plg new file mode 100644 index 00000000..f9d4a2cd --- /dev/null +++ b/cl_dll/cl_dll.plg @@ -0,0 +1,16 @@ + + +
+

Build Log

+

+--------------------Configuration: cl_dll - Win32 Release-------------------- +

+

Command Lines

+ + + +

Results

+client.dll - 0 error(s), 0 warning(s) +
+ + diff --git a/cl_dll/parsemsg.cpp b/cl_dll/parsemsg.cpp index bdfa4136..84f03b8b 100644 --- a/cl_dll/parsemsg.cpp +++ b/cl_dll/parsemsg.cpp @@ -137,7 +137,7 @@ char* READ_STRING( void ) if ( giRead+1 > giSize ) break; // no more characters - c = READ_CHAR(); + c = READ_BYTE(); if (c == -1 || c == 0) break; string[l] = c; diff --git a/common/com_model.h b/common/com_model.h index d4cd4978..4e594c0e 100644 --- a/common/com_model.h +++ b/common/com_model.h @@ -75,7 +75,8 @@ typedef struct texture_s struct texture_s *anim_next; // in the animation sequence struct texture_s *alternate_anims; // bmodels in frmae 1 use these int fb_texturenum; // auto-luma texturenum - unsigned int unused[3]; // reserved + int dt_texturenum; // detail-texture binding + unsigned int unused[2]; // reserved } texture_t; typedef struct diff --git a/dlls/cbase.h b/dlls/cbase.h index d3e13d0c..75ae451e 100644 --- a/dlls/cbase.h +++ b/dlls/cbase.h @@ -59,6 +59,7 @@ CBaseEntity extern "C" EXPORT int GetEntityAPI( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion ); extern "C" EXPORT int GetEntityAPI2( DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion ); +extern "C" EXPORT int Server_GetPhysicsInterface( int iVersion, server_physics_api_t *pfuncsFromEngine, physics_interface_t *pFunctionTable ); extern int DispatchSpawn( edict_t *pent ); extern void DispatchKeyValue( edict_t *pentKeyvalue, KeyValueData *pkvd ); diff --git a/dlls/h_export.cpp b/dlls/h_export.cpp index 96a57fd7..0d56d045 100644 --- a/dlls/h_export.cpp +++ b/dlls/h_export.cpp @@ -28,7 +28,7 @@ // Holds engine functionality callbacks enginefuncs_t g_engfuncs; globalvars_t *gpGlobals; - +server_physics_api_t g_physfuncs; #ifdef _WIN32 diff --git a/dlls/hl.plg b/dlls/hl.plg new file mode 100644 index 00000000..504e743b --- /dev/null +++ b/dlls/hl.plg @@ -0,0 +1,141 @@ + + +
+

Build Log

+

+--------------------Configuration: hl - Win32 Release-------------------- +

+

Command Lines

+Creating temporary file "C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP32FA.tmp" with contents +[ +/nologo /G5 /MT /W3 /O2 /I "..\dlls" /I "..\engine" /I "..\common" /I "..\pm_shared" /I "..\game_shared" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "QUIVER" /D "VOXEL" /D "QUAKE2" /D "VALVE_DLL" /D "CLIENT_WEAPONS" /Fr"..\temp\dlls\!release/" /Fp"..\temp\dlls\!release/hl.pch" /YX /Fo"..\temp\dlls\!release/" /Fd"..\temp\dlls\!release/" /FD /c +"D:\Xash3D\src_main\dlls\client.cpp" +] +Creating command line "cl.exe @"C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP32FA.tmp"" +Creating temporary file "C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP32FB.tmp" with contents +[ +kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /incremental:no /pdb:"..\temp\dlls\!release/hl.pdb" /debug /machine:I386 /def:".\hl.def" /out:"..\temp\dlls\!release/hl.dll" /implib:"..\temp\dlls\!release/hl.lib" +"\Xash3D\src_main\temp\dlls\!release\aflock.obj" +"\Xash3D\src_main\temp\dlls\!release\agrunt.obj" +"\Xash3D\src_main\temp\dlls\!release\airtank.obj" +"\Xash3D\src_main\temp\dlls\!release\animating.obj" +"\Xash3D\src_main\temp\dlls\!release\animation.obj" +"\Xash3D\src_main\temp\dlls\!release\apache.obj" +"\Xash3D\src_main\temp\dlls\!release\barnacle.obj" +"\Xash3D\src_main\temp\dlls\!release\barney.obj" +"\Xash3D\src_main\temp\dlls\!release\bigmomma.obj" +"\Xash3D\src_main\temp\dlls\!release\bloater.obj" +"\Xash3D\src_main\temp\dlls\!release\bmodels.obj" +"\Xash3D\src_main\temp\dlls\!release\bullsquid.obj" +"\Xash3D\src_main\temp\dlls\!release\buttons.obj" +"\Xash3D\src_main\temp\dlls\!release\cbase.obj" +"\Xash3D\src_main\temp\dlls\!release\client.obj" +"\Xash3D\src_main\temp\dlls\!release\combat.obj" +"\Xash3D\src_main\temp\dlls\!release\controller.obj" +"\Xash3D\src_main\temp\dlls\!release\crossbow.obj" +"\Xash3D\src_main\temp\dlls\!release\crowbar.obj" +"\Xash3D\src_main\temp\dlls\!release\defaultai.obj" +"\Xash3D\src_main\temp\dlls\!release\doors.obj" +"\Xash3D\src_main\temp\dlls\!release\effects.obj" +"\Xash3D\src_main\temp\dlls\!release\egon.obj" +"\Xash3D\src_main\temp\dlls\!release\explode.obj" +"\Xash3D\src_main\temp\dlls\!release\flyingmonster.obj" +"\Xash3D\src_main\temp\dlls\!release\func_break.obj" +"\Xash3D\src_main\temp\dlls\!release\func_tank.obj" +"\Xash3D\src_main\temp\dlls\!release\game.obj" +"\Xash3D\src_main\temp\dlls\!release\gamerules.obj" +"\Xash3D\src_main\temp\dlls\!release\gargantua.obj" +"\Xash3D\src_main\temp\dlls\!release\gauss.obj" +"\Xash3D\src_main\temp\dlls\!release\genericmonster.obj" +"\Xash3D\src_main\temp\dlls\!release\ggrenade.obj" +"\Xash3D\src_main\temp\dlls\!release\globals.obj" +"\Xash3D\src_main\temp\dlls\!release\gman.obj" +"\Xash3D\src_main\temp\dlls\!release\h_ai.obj" +"\Xash3D\src_main\temp\dlls\!release\h_battery.obj" +"\Xash3D\src_main\temp\dlls\!release\h_cine.obj" +"\Xash3D\src_main\temp\dlls\!release\h_cycler.obj" +"\Xash3D\src_main\temp\dlls\!release\h_export.obj" +"\Xash3D\src_main\temp\dlls\!release\handgrenade.obj" +"\Xash3D\src_main\temp\dlls\!release\hassassin.obj" +"\Xash3D\src_main\temp\dlls\!release\headcrab.obj" +"\Xash3D\src_main\temp\dlls\!release\healthkit.obj" +"\Xash3D\src_main\temp\dlls\!release\hgrunt.obj" +"\Xash3D\src_main\temp\dlls\!release\hl_wpn_glock.obj" +"\Xash3D\src_main\temp\dlls\!release\hornet.obj" +"\Xash3D\src_main\temp\dlls\!release\hornetgun.obj" +"\Xash3D\src_main\temp\dlls\!release\houndeye.obj" +"\Xash3D\src_main\temp\dlls\!release\ichthyosaur.obj" +"\Xash3D\src_main\temp\dlls\!release\islave.obj" +"\Xash3D\src_main\temp\dlls\!release\items.obj" +"\Xash3D\src_main\temp\dlls\!release\leech.obj" +"\Xash3D\src_main\temp\dlls\!release\lights.obj" +"\Xash3D\src_main\temp\dlls\!release\maprules.obj" +"\Xash3D\src_main\temp\dlls\!release\monstermaker.obj" +"\Xash3D\src_main\temp\dlls\!release\monsters.obj" +"\Xash3D\src_main\temp\dlls\!release\monsterstate.obj" +"\Xash3D\src_main\temp\dlls\!release\mortar.obj" +"\Xash3D\src_main\temp\dlls\!release\mp5.obj" +"\Xash3D\src_main\temp\dlls\!release\multiplay_gamerules.obj" +"\Xash3D\src_main\temp\dlls\!release\nihilanth.obj" +"\Xash3D\src_main\temp\dlls\!release\nodes.obj" +"\Xash3D\src_main\temp\dlls\!release\osprey.obj" +"\Xash3D\src_main\temp\dlls\!release\pathcorner.obj" +"\Xash3D\src_main\temp\dlls\!release\plane.obj" +"\Xash3D\src_main\temp\dlls\!release\plats.obj" +"\Xash3D\src_main\temp\dlls\!release\player.obj" +"\Xash3D\src_main\temp\dlls\!release\pm_debug.obj" +"\Xash3D\src_main\temp\dlls\!release\pm_math.obj" +"\Xash3D\src_main\temp\dlls\!release\pm_shared.obj" +"\Xash3D\src_main\temp\dlls\!release\python.obj" +"\Xash3D\src_main\temp\dlls\!release\rat.obj" +"\Xash3D\src_main\temp\dlls\!release\roach.obj" +"\Xash3D\src_main\temp\dlls\!release\rpg.obj" +"\Xash3D\src_main\temp\dlls\!release\satchel.obj" +"\Xash3D\src_main\temp\dlls\!release\schedule.obj" +"\Xash3D\src_main\temp\dlls\!release\scientist.obj" +"\Xash3D\src_main\temp\dlls\!release\scripted.obj" +"\Xash3D\src_main\temp\dlls\!release\shotgun.obj" +"\Xash3D\src_main\temp\dlls\!release\singleplay_gamerules.obj" +"\Xash3D\src_main\temp\dlls\!release\skill.obj" +"\Xash3D\src_main\temp\dlls\!release\sound.obj" +"\Xash3D\src_main\temp\dlls\!release\soundent.obj" +"\Xash3D\src_main\temp\dlls\!release\spectator.obj" +"\Xash3D\src_main\temp\dlls\!release\squadmonster.obj" +"\Xash3D\src_main\temp\dlls\!release\squeakgrenade.obj" +"\Xash3D\src_main\temp\dlls\!release\subs.obj" +"\Xash3D\src_main\temp\dlls\!release\talkmonster.obj" +"\Xash3D\src_main\temp\dlls\!release\teamplay_gamerules.obj" +"\Xash3D\src_main\temp\dlls\!release\tempmonster.obj" +"\Xash3D\src_main\temp\dlls\!release\tentacle.obj" +"\Xash3D\src_main\temp\dlls\!release\triggers.obj" +"\Xash3D\src_main\temp\dlls\!release\tripmine.obj" +"\Xash3D\src_main\temp\dlls\!release\turret.obj" +"\Xash3D\src_main\temp\dlls\!release\util.obj" +"\Xash3D\src_main\temp\dlls\!release\voice_gamemgr.obj" +"\Xash3D\src_main\temp\dlls\!release\weapons.obj" +"\Xash3D\src_main\temp\dlls\!release\world.obj" +"\Xash3D\src_main\temp\dlls\!release\xen.obj" +"\Xash3D\src_main\temp\dlls\!release\zombie.obj" +] +Creating command line "link.exe @"C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP32FB.tmp"" +Creating temporary file "C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP32FC.bat" with contents +[ +@echo off +copy \Xash3D\src_main\temp\dlls\!release\hl.dll "D:\Xash3D\valve\dlls\hl.dll" +] +Creating command line ""C:\DOCUME~1\ÌÈØÀ\LOCALS~1\Temp\RSP32FC.bat"" +Compiling... +client.cpp +Linking... + Creating library ..\temp\dlls\!release/hl.lib and object ..\temp\dlls\!release/hl.exp +

Output Window

+Performing Custom Build Step on \Xash3D\src_main\temp\dlls\!release\hl.dll +‘ª®¯¨à®¢ ­® ä ©«®¢: 1. + + + +

Results

+hl.dll - 0 error(s), 0 warning(s) +
+ + diff --git a/dlls/physcallback.h b/dlls/physcallback.h new file mode 100644 index 00000000..a4037e18 --- /dev/null +++ b/dlls/physcallback.h @@ -0,0 +1,28 @@ +/*** +* +* Copyright (c) 1996-2002, Valve LLC. All rights reserved. +* +* This product contains software technology licensed from Id +* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc. +* All Rights Reserved. +* +* Use, distribution, and modification of this source code and/or resulting +* object code is restricted to non-commercial enhancements to products from +* Valve LLC. All other use, distribution, or modification is prohibited +* without written permission from Valve LLC. +* +****/ +#ifndef PHYSCALLBACK_H +#define PHYSCALLBACK_H +#pragma once + +#include "physint.h" + +// Must be provided by user of this code +extern server_physics_api_t g_physfuncs; + +// The actual physic callbacks +#define LINK_ENTITY (*g_physfuncs.pfnLinkEdict) +#define PHYSICS_TIME (*g_physfuncs.pfnGetServerTime) + +#endif //PHYSCALLBACK_H \ No newline at end of file diff --git a/dlls/util.h b/dlls/util.h index 48655158..edcbc947 100644 --- a/dlls/util.h +++ b/dlls/util.h @@ -22,6 +22,11 @@ #ifndef ENGINECALLBACK_H #include "enginecallback.h" #endif + +#ifndef PHYSCALLBACK_H +#include "physcallback.h" +#endif + inline void MESSAGE_BEGIN( int msg_dest, int msg_type, const float *pOrigin, entvars_t *ent ); // implementation later in this file extern globalvars_t *gpGlobals; diff --git a/dlls/weapons.cpp b/dlls/weapons.cpp index f8187790..8a8ddc0b 100644 --- a/dlls/weapons.cpp +++ b/dlls/weapons.cpp @@ -767,6 +767,7 @@ void CBasePlayerItem::AttachToPlayer ( CBasePlayer *pPlayer ) pev->owner = pPlayer->edict(); pev->nextthink = gpGlobals->time + .1; SetTouch( NULL ); + SetThink( NULL ); } // CALLED THROUGH the newly-touched weapon's instance. The existing player weapon is pOriginal diff --git a/dlls/world.cpp b/dlls/world.cpp index 4f786597..dfe21e6e 100644 --- a/dlls/world.cpp +++ b/dlls/world.cpp @@ -33,6 +33,7 @@ #include "weapons.h" #include "gamerules.h" #include "teamplay_gamerules.h" +#include "physcallback.h" extern CGraph WorldGraph; extern CSoundEnt *pSoundEnt; @@ -748,3 +749,112 @@ void CWorld :: KeyValue( KeyValueData *pkvd ) else CBaseEntity::KeyValue( pkvd ); } + +// +// Xash3D physics interface +// + +typedef void (__cdecl *LINK_ENTITY_FN)( entvars_t *pev ); + +// +// attempt to create custom entity when default method is failed +// 0 - attempt to create, -1 - reject to create +// +int DispatchCreateEntity( edict_t *pent, const char *szName ) +{ +/* +#ifdef CREATE_ENTITY_TEST + // quake armor entities. we just replaced it with item_battery... + if( !strcmp( szName, "item_armor1" ) || !strcmp( szName, "item_armor2" )) + { + LINK_ENTITY_FN SpawnEdict; + + // ugly method to get acess with himself exports + SpawnEdict = (LINK_ENTITY_FN)GetProcAddress( GetModuleHandle( "hl" ), "item_battery" ); + + if( SpawnEdict != NULL ) // found the valid spawn + { + // BUGBUG: old classname hanging in memory + pent->v.classname = ALLOC_STRING( "item_battery" ); + +// ALERT( at_console, "DispatchCreateEntity: replace %s with %s\n", szName, STRING( pent->v.classname )); + + SpawnEdict( &pent->v ); + return 0; // handled + } + } +#endif +*/ + return -1; +} + +// +// run custom physics for each entity +// return 0 to use built-in engine physic +// +int DispatchPhysicsEntity( edict_t *pEdict ) +{ + CBaseEntity *pEntity = (CBaseEntity *)GET_PRIVATE(pEdict); + + if( !pEntity ) + { +// ALERT( at_console, "skip %s [%i] without private data\n", STRING( pEdict->v.classname ), ENTINDEX( pEdict )); + return 0; // not initialized + } + + // NOTE: at this point pEntity assume to be valid +/* +#ifdef CUSTOM_PHYSICS_TEST + // test alien controller without physics, thinking only + if( FClassnameIs( pEntity->pev, "monster_alien_controller" )) + { + float thinktime; + + thinktime = pEntity->pev->nextthink; + if( thinktime <= 0.0f || thinktime > PHYSICS_TIME() + gpGlobals->frametime ) + return 1; + + if( thinktime < PHYSICS_TIME( )) + thinktime = PHYSICS_TIME(); // don't let things stay in the past. + // it is possible to start that way + // by a trigger with a local time. + pEntity->pev->nextthink = 0.0f; + gpGlobals->time = thinktime; + + DispatchThink( pEdict ); + +#ifdef GRAVITY_TEST + // stupid fake gravity test + pEntity->pev->origin.z -= 1; + LINK_ENTITY( pEdict, true ); +#endif + + return 1; // handled + } +#endif +*/ + return 0; +} + +static physics_interface_t gPhysicsInterface = +{ + SV_PHYSICS_INTERFACE_VERSION, + DispatchCreateEntity, + DispatchPhysicsEntity, +}; + +int Server_GetPhysicsInterface( int iVersion, server_physics_api_t *pfuncsFromEngine, physics_interface_t *pFunctionTable ) +{ + if ( !pFunctionTable || !pfuncsFromEngine || iVersion != SV_PHYSICS_INTERFACE_VERSION ) + { + return FALSE; + } + + // copy new physics interface + memcpy(&g_physfuncs, pfuncsFromEngine, sizeof(server_physics_api_t)); + + // fill engine callbacks + memcpy( pFunctionTable, &gPhysicsInterface, sizeof( physics_interface_t ) ); + + return TRUE; +} \ No newline at end of file diff --git a/engine/cdll_int.h b/engine/cdll_int.h index 81dbf74d..4fb81824 100644 --- a/engine/cdll_int.h +++ b/engine/cdll_int.h @@ -250,6 +250,96 @@ typedef struct cl_enginefuncs_s void (*pfnSetMousePos)( int x, int y ); void (*pfnSetMouseEnable)( qboolean fEnable ); + // Returns pointer to start of registered cvar linked list. Added for VGUI console autocomplete? + void* (*pfnGetCvarList)( void ); + + // Returns pointer to start of registered command linked list. Added for VGUI console autocomplete? + void* (*pfnGetCmdList)( void ); + + // Not sure about this - convert cvar_t pointer to cvar name? Why? + char* (*pfnCvarNameFromPointer)( void *pointer ); + + // Not sure abput this - convert cmd_function_t pointer to command name? Why? + char* (*pfnCmdNameFromPointer)( void *pointer ); + + // Returns current time for this client? Why is this needed when GetClientTime() already exists? + float (*pfnGetCurrentTime)( void ); + + // Unsure - always seems to return 800.0f (no, it's not horizontal resolution) + float (*pfnGetGravityFactor)( void ); + + // Appears to be identical to function in IEngineStudio + void* (*pfnGetModelByIndex)( int index ); + + // Appears to modifies hidden cvar gl_texsort. + void (*pfnSetGL_TexSort)( int value ); + + // Colour scaling values for screen. Only works when gl_texsort is active. + void (*pfnSetGL_TexSort_Colour)( float red, float green, float blue ); + + // Final scaling factor for screen. Only works when gl_texsort is active. + void (*pfnSetGL_TexSort_Scale)( float scale ); + + // Seems to be a client entry point to the pfnSequenceGet function introduced for CS:CZ + void* (*pfnSequenceGet)( const char *fileName, const char *entryName ); + + // Draws a sprite on the screen - parameters are likely incorrect. + void (*pfnDrawSpriteGeneric)( int frame, int x, int y, const wrect_t *prc, int u1, int u2, int u3, int u4 ); + + // Seems to be a client entry point to the pfnSequencePickSentence function introduced for CS:CZ + void* (*pfnSequencePickSentence)( const char *groupName, int pickMethod, int *picked ); + + // Unknown (deals with wchar_t's) + void (*pfnUnknownFunction6)( void *u1, void *u2, void *u3, void *u4, void *u5, void *u6 ); + + // Unknown (deals with wchar_t's) + void (*pfnUnknownFunction7)( void *u1, void *u2 ); + + // Unknown (something to do with players infostring?) + char* (*pfnUnknownFunction8)( char *u1 ); + + // Completely unknown + void (*pfnUnknownFunction9)( void *u1, void *u2 ); + + // Completely unknown + void (*pfnUnknownFunction10)( void *u1, void *u2, void *u3, void *u4, void *u5 ); + + // Seems to be a client entry point to the pfnGetApproxWavePlayLen function introduced for CS:CZ + unsigned int (*pfnGetApproxWavePlayLen)( char *filename ); + + // Completely unknown + int (*pfnUnknownFunction11)( void ); + + // Sets cvar value - why is this needed when Cvar_SetValue already exists? + void (*Cvar_Set)( char *name, char *value ); + + // Seems to be a client entry point to the pfnIsCareerMatch function introduced for CS:CZ + int (*pfnIsCareerMatch)( void ); + + // Starts a local sound - why is this needed? + void (*pfnStartDynamicSound)( char *filename, float volume, float pitch ); + + // MP3 interface - unsure what int parameter is. Just queues the sound up - have to issue command "mp3 play" to start it. */ + void (*pfnMP3_InitStream)( char *filename, int i1 ); + + // Returns unknown, constantly increasing float. Timing? (calls QueryPerformanceCounters) + float (*pfnUnknownFunction12)( void ); + + // Seems to be a client entry point to the pfnProcessTutorMessageDecayBuffer function introduced for CS:CZ + void (*pfnProcessTutorMessageDecayBuffer)( int *buffer, int buflen ); + + // Seems to be a client entry point to the pfnConstructTutorMessageDecayBuffer function introduced for CS:CZ + void (*pfnConstructTutorMessageDecayBuffer)( int *buffer, int buflen ); + + // Seems to be a client entry point to the pfnResetTutorMessageDecayData function introduced for CS:CZ + void (*pfnResetTutorMessageDecayData)( void ); + + // Seems to be an exact copy of the previous StartDynamicSound function??? + void (*pfnStartDynamicSound2)( char *filename, float volume, float pitch ); + + // Seems to be an exact copy of the previous FillRGBA function??? + void (*pfnFillRGBA2)( int x, int y, int width, int height, int r, int g, int b, int a ); + } cl_enginefunc_t; #define CLDLL_INTERFACE_VERSION 7 diff --git a/engine/client/cl_frame.c b/engine/client/cl_frame.c index 401f33c7..dda49763 100644 --- a/engine/client/cl_frame.c +++ b/engine/client/cl_frame.c @@ -110,15 +110,9 @@ void CL_UpdateEntityFields( cl_entity_t *ent ) if( m_pGround && m_pGround->curstate.movetype == MOVETYPE_PUSH ) { - studiohdr_t *phdr; - mstudioseqdesc_t *pseqdesc; - qboolean applyVel, applyAvel; + qboolean applyVel, applyAvel; d = 1.0f - cl.lerpFrac; // use backlerp to interpolate pusher position - phdr = (studiohdr_t *)Mod_Extradata( ent->model ); - ASSERT( phdr != NULL ); - pseqdesc = (mstudioseqdesc_t *)((byte *)phdr + phdr->seqindex) + ent->curstate.sequence; - d = d - 1.0f; applyVel = !VectorCompare( m_pGround->curstate.origin, m_pGround->prevstate.origin ); diff --git a/engine/client/cl_game.c b/engine/client/cl_game.c index 68dd843d..276c5aeb 100644 --- a/engine/client/cl_game.c +++ b/engine/client/cl_game.c @@ -867,7 +867,7 @@ void CL_DrawCrosshair( void ) clgame.ds.pSprite = clgame.ds.pCrosshair; - GL_SetRenderMode( kRenderTransAlpha ); + GL_SetRenderMode( kRenderTransTexture ); *(int *)clgame.ds.spriteColor = *(int *)clgame.ds.rgbaCrosshair; SPR_EnableScissor( x - 0.5f * width, y - 0.5f * height, width, height ); @@ -3685,7 +3685,7 @@ void CL_UnloadProgs( void ) Q_memset( &clgame, 0, sizeof( clgame )); Cvar_Unlink(); - Cmd_Unlink(); + Cmd_Unlink( CMD_CLIENTDLL ); } qboolean CL_LoadProgs( const char *name ) diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index ab914ea1..0c7ce510 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -259,7 +259,7 @@ usercmd_t CL_CreateCmd( void ) active = ( cls.state == ca_active && !cl.refdef.paused && !cl.refdef.intermission ); clgame.dllFuncs.CL_CreateMove( cl.time - cl.oldtime, &cmd, active ); - R_LightForPoint( cl.frame.local.client.origin, &color, false, 128.0f ); + R_LightForPoint( cl.frame.local.client.origin, &color, false, false, 128.0f ); cmd.lightlevel = (color.r + color.g + color.b) / 3; // never let client.dll calc frametime for player @@ -818,6 +818,33 @@ void CL_LocalServers_f( void ) Netchan_OutOfBandPrint( NS_CLIENT, adr, "info %i", PROTOCOL_VERSION ); } +/* +================= +CL_InternetServers_f +================= +*/ +void CL_InternetServers_f( void ) +{ + netadr_t adr; + char part1query[12]; + char part2query[128]; + string fullquery; + + MsgDev( D_INFO, "Scanning for servers on the internet area...\n" ); + NET_Config( true ); // allow remote + + if( !NET_StringToAdr( MASTERSERVER_ADR, &adr ) ) + MsgDev( D_INFO, "Can't resolve adr: %s\n", MASTERSERVER_ADR ); + + Q_snprintf( part1query, sizeof( part1query ), "%c%c0.0.0.0:0", 0x31, 0xFF ); + Q_snprintf( part2query, sizeof( part2query ), "\\gamedir\\%s_xash\\nap\\%d", GI->gamedir, 70 ); + + Q_memcpy( fullquery, part1query, sizeof( part1query )); + Q_memcpy( fullquery + sizeof( part1query ), part2query, Q_strlen( part2query )); + + NET_SendPacket( NS_CLIENT, sizeof( part1query ) + Q_strlen( part2query ) + 1, fullquery, adr ); +} + /* ==================== CL_Packet_f @@ -1116,6 +1143,8 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg ) char *args; char *c, buf[MAX_SYSPATH]; int len = sizeof( buf ); + int dataoffset = 0; + netadr_t servadr; BF_Clear( msg ); BF_ReadLong( msg ); // skip the -1 @@ -1202,6 +1231,33 @@ void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg ) // user out of band message (must be handled in CL_ConnectionlessPacket) if( len > 0 ) Netchan_OutOfBand( NS_SERVER, from, len, buf ); } + else if( msg->pData[0] == 0xFF && msg->pData[1] == 0xFF && msg->pData[2] == 0xFF && msg->pData[3] == 0xFF && msg->pData[4] == 0x66 && msg->pData[5] == 0x0A ) + { + dataoffset = 6; + + while( 1 ) + { + servadr.type = NA_IP; + servadr.ip[0] = msg->pData[dataoffset + 0]; + servadr.ip[1] = msg->pData[dataoffset + 1]; + servadr.ip[2] = msg->pData[dataoffset + 2]; + servadr.ip[3] = msg->pData[dataoffset + 3]; + + servadr.port = *(word *)&msg->pData[dataoffset + 4]; + + if( !servadr.port ) + break; + + MsgDev( D_INFO, "Found server: %s\n", NET_AdrToString( servadr )); + + NET_Config( true ); // allow remote + + Netchan_OutOfBandPrint( NS_CLIENT, servadr, "info %i", PROTOCOL_VERSION ); + + dataoffset += 6; + + } + } else MsgDev( D_ERROR, "bad connectionless packet from %s:\n%s\n", NET_AdrToString( from ), args ); } @@ -1277,8 +1333,8 @@ void CL_ReadNetMessage( void ) if( Netchan_CopyFileFragments( &cls.netchan, &net_message )) { - // Remove from resource request stuff. -// CL_ProcessFile( true, cls.netchan.incomingfilename ); + // remove from resource request stuff. + CL_ProcessFile( true, cls.netchan.incomingfilename ); } } @@ -1315,6 +1371,28 @@ void CL_ReadPackets( void ) } +/* +==================== +CL_ProcessFile + +A file has been received via the fragmentation/reassembly layer, put it in the right spot and + see if we have finished downloading files. +==================== +*/ +void CL_ProcessFile( BOOL successfully_received, const char *filename ) +{ + MsgDev( D_INFO, "Received %s, but file processing is not hooked up!!!\n", filename ); + + if( cls.downloadfileid == cls.downloadcount - 1 ) + { + MsgDev( D_INFO,"All Files downloaded\n" ); + + BF_WriteByte( &cls.netchan.message, clc_stringcmd ); + BF_WriteString( &cls.netchan.message, "continueloading" ); + } + + cls.downloadfileid++; +} //============================================================================= /* @@ -1443,6 +1521,7 @@ void CL_InitLocal( void ) // register our commands Cmd_AddCommand ("pause", NULL, "pause the game (if the server allows pausing)" ); Cmd_AddCommand ("localservers", CL_LocalServers_f, "collect info about local servers" ); + Cmd_AddCommand ("internetservers", CL_InternetServers_f, "collect info about internet servers" ); Cmd_AddCommand ("cd", CL_PlayCDTrack_f, "Play cd-track (not real cd-player of course)" ); Cmd_AddCommand ("userinfo", CL_Userinfo_f, "print current client userinfo" ); diff --git a/engine/client/cl_menu.c b/engine/client/cl_menu.c index 302dc2bb..a2682b58 100644 --- a/engine/client/cl_menu.c +++ b/engine/client/cl_menu.c @@ -38,7 +38,6 @@ void UI_UpdateMenu( float realtime ) if( !menu.hInstance ) return; menu.dllFuncs.pfnRedraw( realtime ); UI_UpdateUserinfo(); - Con_DrawVersion(); } void UI_KeyEvent( int key, qboolean down ) diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index ef1720fe..43380258 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -72,9 +72,9 @@ const char *svc_strings[256] = "svc_packetentities", "svc_deltapacketentities", "svc_chokecount", - "svc_unused43", + "svc_resourcelist", "svc_deltamovevars", - "svc_unused45", + "svc_customization", "svc_unused46", "svc_crosshairangle", "svc_soundfade", @@ -97,8 +97,9 @@ typedef struct qboolean parsing; } msg_debug_t; -static msg_debug_t cls_message_debug; -static int starting_count; +static msg_debug_t cls_message_debug; +static int starting_count; +static resourcelist_t reslist; const char *CL_MsgInfo( int cmd ) { @@ -450,6 +451,11 @@ void CL_ParseEvent( sizebuf_t *msg ) CL_ParseReliableEvent( msg, 0 ); } +void CL_ParseCustomization( sizebuf_t *msg ) +{ + // FIXME: ??? +} + /* ===================================================================== @@ -695,6 +701,7 @@ void CL_ParseSetAngle( sizebuf_t *msg ) { cl.refdef.cl_viewangles[0] = BF_ReadBitAngle( msg, 16 ); cl.refdef.cl_viewangles[1] = BF_ReadBitAngle( msg, 16 ); + cl.refdef.cl_viewangles[2] = BF_ReadBitAngle( msg, 16 ); } /* @@ -893,6 +900,88 @@ void CL_ServerInfo( sizebuf_t *msg ) Info_SetValueForKey( cl.serverinfo, key, value ); } +/* +============== +CL_CheckingResFile + +============== +*/ +void CL_CheckingResFile( char *pResFileName ) +{ + sizebuf_t buf; + byte data[32]; + + if( FS_FileExists( pResFileName, false )) + return; // already existing + + cls.downloadcount++; + + Msg( "Starting downloads file: %s\n", pResFileName ); + + if( cls.state == ca_disconnected ) return; + + BF_Init( &buf, "ClientPacket", data, sizeof( data )); + BF_WriteByte( &buf, clc_resourcelist ); + BF_WriteString( &buf, pResFileName ); + + if( !cls.netchan.remote_address.type ) // download in singleplayer ??? + cls.netchan.remote_address.type = NA_LOOPBACK; + + // make sure message will be delivered + Netchan_Transmit( &cls.netchan, BF_GetNumBytesWritten( &buf ), BF_GetData( &buf )); + +} + +/* +============== +CL_CheckingSoundResFile + +============== +*/ +void CL_CheckingSoundResFile( char *pResFileName ) +{ + string filepath; + + Q_snprintf( filepath, sizeof( filepath ), "sound/%s", pResFileName ); + CL_CheckingResFile( filepath ); +} + +/* +============== +CL_ParseResourceList + +============== +*/ +void CL_ParseResourceList( sizebuf_t *msg ) +{ + int i = 0; + + Q_memset( &reslist, 0, sizeof( resourcelist_t )); + + reslist.rescount = BF_ReadWord( msg ) - 1; + + for( i = 0; i < reslist.rescount; i++ ) + { + reslist.restype[i] = BF_ReadWord( msg ); + Q_strncpy( reslist.resnames[i], BF_ReadString( msg ), CS_SIZE ); + } + + cls.downloadcount = 0; + + for( i = 0; i < reslist.rescount; i++ ) + { + if( reslist.restype[i] == t_sound ) + CL_CheckingSoundResFile( reslist.resnames[i] ); + else CL_CheckingResFile( reslist.resnames[i] ); + } + + if( !cls.downloadcount ) + { + BF_WriteByte( &cls.netchan.message, clc_stringcmd ); + BF_WriteString( &cls.netchan.message, "continueloading" ); + } +} + /* ============== CL_ParseDirector @@ -1229,6 +1318,9 @@ void CL_ParseServerMessage( sizebuf_t *msg ) case svc_deltamovevars: CL_ParseMovevars( msg ); break; + case svc_customization: + CL_ParseCustomization( msg ); + break; case svc_centerprint: CL_CenterPrint( BF_ReadString( msg ), 0.35f ); break; @@ -1293,6 +1385,9 @@ void CL_ParseServerMessage( sizebuf_t *msg ) } } break; + case svc_resourcelist: + CL_ParseResourceList( msg ); + break; case svc_director: CL_ParseDirector( msg ); break; diff --git a/engine/client/cl_scrn.c b/engine/client/cl_scrn.c index 52606b40..5291adc2 100644 --- a/engine/client/cl_scrn.c +++ b/engine/client/cl_scrn.c @@ -47,6 +47,7 @@ void SCR_DrawFPS( void ) static int framecount = 0; double newtime; char fpsstring[32]; + int offset; if( cls.state != ca_active ) return; if( !cl_showfps->integer || cl.background ) return; @@ -75,7 +76,9 @@ void SCR_DrawFPS( void ) Q_snprintf( fpsstring, sizeof( fpsstring ), "%4i fps", (int)(calc + 0.5)); MakeRGBA( color, 255, 255, 255, 255 ); } - Con_DrawString( scr_width->integer - 68, 4, fpsstring, color ); + + Con_DrawStringLen( fpsstring, &offset, NULL ); + Con_DrawString( scr_width->integer - offset - 2, 4, fpsstring, color ); } /* @@ -446,7 +449,7 @@ void SCR_Init( void ) if( host.state != HOST_RESTART && !UI_LoadProgs( )) { - Msg( "^1Error: ^7can't initialize MainUI.dll\n" ); // there is non fatal for us + Msg( "^1Error: ^7can't initialize menu.dll\n" ); // there is non fatal for us if( !host.developer ) host.developer = 1; // we need console, because menu is missing } diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index ba61c874..00759085 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -866,11 +866,12 @@ CL_BreakModel Create a shards ============== */ -void CL_BreakModel( const vec3_t pos, const vec3_t size, const vec3_t dir, float random, float life, int count, int modelIndex, char flags ) +void CL_BreakModel( const vec3_t pos, const vec3_t size, const vec3_t direction, float random, float life, int count, int modelIndex, char flags ) { int i, frameCount; TEMPENTITY *pTemp; char type; + vec3_t dir; if( !modelIndex ) return; type = flags & BREAK_TYPEMASK; @@ -886,13 +887,28 @@ void CL_BreakModel( const vec3_t pos, const vec3_t size, const vec3_t dir, float count = (size[0] * size[1] + size[1] * size[2] + size[2] * size[0]) / (3 * SHARD_VOLUME * SHARD_VOLUME); } + VectorCopy( direction, dir ); + // limit to 100 pieces if( count > 100 ) count = 100; + if( VectorIsNull( direction )) + random *= 10; + for( i = 0; i < count; i++ ) { vec3_t vecSpot; + if( VectorIsNull( direction )) + { + // random direction for each piece + dir[0] = Com_RandomFloat( -1.0f, 1.0f ); + dir[1] = Com_RandomFloat( -1.0f, 1.0f ); + dir[2] = Com_RandomFloat( -1.0f, 1.0f ); + + VectorNormalize( dir ); + } + // fill up the box with stuff vecSpot[0] = pos[0] + Com_RandomFloat( -0.5f, 0.5f ) * size[0]; vecSpot[1] = pos[1] + Com_RandomFloat( -0.5f, 0.5f ) * size[1]; @@ -1287,46 +1303,46 @@ void CL_FunnelSprite( const vec3_t pos, int spriteIndex, int flags ) { for( j = -256; j <= 256; j += 32 ) { - if( pTemp || !spriteIndex ) + if( flags & SF_FUNNEL_REVERSE ) { - pPart = CL_AllocParticle( NULL ); - pTemp = NULL; + VectorCopy( pos, m_vecPos ); + + dest[0] = pos[0] + i; + dest[1] = pos[1] + j; + dest[2] = pos[2] + Com_RandomFloat( 100, 800 ); + + // send particle heading to dest at a random speed + VectorSubtract( dest, m_vecPos, dir ); + + // velocity based on how far particle has to travel away from org + vel = dest[2] / 8; } else + { + m_vecPos[0] = pos[0] + i; + m_vecPos[1] = pos[1] + j; + m_vecPos[2] = pos[2] + Com_RandomFloat( 100, 800 ); + + // send particle heading to org at a random speed + VectorSubtract( pos, m_vecPos, dir ); + + // velocity based on how far particle starts from org + vel = m_vecPos[2] / 8; + } + + if( pPart && spriteIndex && CL_PointContents( m_vecPos ) == CONTENTS_EMPTY ) { pTemp = CL_TempEntAlloc( pos, Mod_Handle( spriteIndex )); pPart = NULL; } + else + { + pPart = CL_AllocParticle( NULL ); + pTemp = NULL; + } if( pTemp || pPart ) { - if( flags & SF_FUNNEL_REVERSE ) - { - VectorCopy( pos, m_vecPos ); - - dest[0] = pos[0] + i; - dest[1] = pos[1] + j; - dest[2] = pos[2] + Com_RandomFloat( 100, 800 ); - - // send particle heading to dest at a random speed - VectorSubtract( dest, m_vecPos, dir ); - - // velocity based on how far particle has to travel away from org - vel = dest[2] / 8; - } - else - { - m_vecPos[0] = pos[0] + i; - m_vecPos[1] = pos[1] + j; - m_vecPos[2] = pos[2] + Com_RandomFloat( 100, 800 ); - - // send particle heading to org at a random speed - VectorSubtract( pos, m_vecPos, dir ); - - // velocity based on how far particle starts from org - vel = m_vecPos[2] / 8; - } - flDist = VectorNormalizeLength( dir ); // save the distance if( vel < 64 ) vel = 64; @@ -1339,9 +1355,10 @@ void CL_FunnelSprite( const vec3_t pos, int spriteIndex, int flags ) VectorScale( dir, vel, pTemp->entity.baseline.origin ); pTemp->entity.curstate.rendermode = kRenderTransAdd; pTemp->flags |= FTENT_FADEOUT; - pTemp->fadeSpeed = 2.0f; - pTemp->die = cl.time + Com_RandomFloat( life * 0.5, life ); + pTemp->fadeSpeed = 3.0f; + pTemp->die = cl.time + life - Com_RandomFloat( 0.5f, 0.6f ); pTemp->entity.curstate.renderamt = pTemp->entity.baseline.renderamt = 255; + pTemp->entity.curstate.scale = 0.75f; } if( pPart ) @@ -1352,7 +1369,7 @@ void CL_FunnelSprite( const vec3_t pos, int spriteIndex, int flags ) VectorScale( dir, vel, pPart->vel ); // die right when you get there - pPart->die += Com_RandomFloat( life * 0.5f, life ); + pPart->die += life; } } } @@ -2394,7 +2411,7 @@ void CL_UpdateFlashlight( cl_entity_t *pEnt ) VectorClear( view_ofs ); if(( pEnt->index - 1 ) == cl.playernum ) - VectorCopy( cl.predicted_viewofs, view_ofs ); + VectorCopy( cl.refdef.viewheight, view_ofs ); VectorAdd( pEnt->origin, view_ofs, vecSrc ); VectorMA( vecSrc, FLASHLIGHT_DISTANCE, forward, vecEnd ); diff --git a/engine/client/cl_view.c b/engine/client/cl_view.c index c5d92f44..e709b4dd 100644 --- a/engine/client/cl_view.c +++ b/engine/client/cl_view.c @@ -182,6 +182,7 @@ void V_PostRender( void ) CL_DrawHUD( CL_CHANGELEVEL ); Con_DrawConsole(); UI_UpdateMenu( host.realtime ); + Con_DrawVersion(); Con_DrawDebug(); // must be last S_ExtraUpdate(); } diff --git a/engine/client/client.h b/engine/client/client.h index 5fd59ca5..62e3d143 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -162,7 +162,8 @@ typedef enum { key_console = 0, key_game, - key_menu + key_menu, + key_message } keydest_t; typedef enum @@ -441,6 +442,10 @@ typedef struct const float *envshot_vieworg; // envshot position string shotname; + // download info + int downloadcount; + int downloadfileid; + // demo loop control int demonum; // -1 = don't play demos string demos[MAX_DEMOS]; // when not playing @@ -531,6 +536,7 @@ void SCR_TimeRefresh_f( void ); void CL_Init( void ); void CL_SendCommand( void ); void CL_Disconnect_f( void ); +void CL_ProcessFile( qboolean successfully_received, const char *filename ); void CL_GetChallengePacket( void ); void CL_PingServers_f( void ); void CL_ClearState( void ); @@ -690,6 +696,7 @@ int Con_DrawString( int x, int y, const char *string, rgba_t setColor ); void Con_DefaultColor( int r, int g, int b ); void Con_CharEvent( int key ); void Key_Console( int key ); +void Key_Message( int key ); void Con_Close( void ); // diff --git a/engine/client/gl_backend.c b/engine/client/gl_backend.c index 292339bb..be6b87c7 100644 --- a/engine/client/gl_backend.c +++ b/engine/client/gl_backend.c @@ -560,19 +560,25 @@ void R_ShowTextures( void ) R_Set2DMode( true ); } + if( gl_showtextures->integer == TEX_DETAIL ) + pglClearColor( 1.0f, 0.0f, 0.5f, 1.0f ); + pglClear( GL_COLOR_BUFFER_BIT ); pglFinish(); - if( gl_showtextures->integer == TEX_LIGHTMAP || gl_showtextures->integer == TEX_VGUI ) + switch( gl_showtextures->integer ) { + case TEX_LIGHTMAP: + case TEX_VGUI: + case TEX_DETAIL: // draw lightmaps as big images base_w = 5; base_h = 4; - } - else - { + break; + default: base_w = 16; base_h = 12; + break; } for( i = j = 0; i < MAX_TEXTURES; i++ ) diff --git a/engine/client/gl_beams.c b/engine/client/gl_beams.c index efd35476..0bdfb902 100644 --- a/engine/client/gl_beams.c +++ b/engine/client/gl_beams.c @@ -1412,7 +1412,7 @@ void CL_DrawBeam( BEAM *pbeam ) } frame = ((int)( pbeam->frame + cl.time * pbeam->frameRate ) % pbeam->frameCount ); - rendermode = ( pbeam->flags & FBEAM_SOLID ) ? kRenderNormal : kRenderTransAdd; + rendermode = ( pbeam->flags & FBEAM_SOLID ) ? kRenderTransColor : kRenderTransAdd; // set color VectorSet( srcColor, pbeam->r, pbeam->g, pbeam->b ); diff --git a/engine/client/gl_decals.c b/engine/client/gl_decals.c index 2346518c..3734e808 100644 --- a/engine/client/gl_decals.c +++ b/engine/client/gl_decals.c @@ -566,6 +566,8 @@ static void R_DecalCreate( decalinfo_t *decalinfo, msurface_t *surf, float x, fl if( count < MAX_OVERLAP_DECALS ) pold = NULL; pdecal = R_DecalAlloc( pold ); + if( !pdecal ) return; // r_decals == 0 ??? + pdecal->flags = decalinfo->m_Flags; VectorCopy( decalinfo->m_Position, pdecal->position ); diff --git a/engine/client/gl_export.h b/engine/client/gl_export.h index 9a97d03a..4bba8854 100644 --- a/engine/client/gl_export.h +++ b/engine/client/gl_export.h @@ -201,7 +201,9 @@ typedef float GLmatrix[16]; #define GL_LUMINANCE8_ALPHA8 0x8045 #define GL_LUMINANCE12_ALPHA4 0x8046 #define GL_LUMINANCE12_ALPHA12 0x8047 -#define GL_LUMINANCE16_ALPHA16 0x8048 +#define GL_LUMINANCE16_ALPHA16 0x8048 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE_ALPHA 0x190A #define GL_DEPTH_COMPONENT 0x1902 #define GL_INTENSITY 0x8049 #define GL_INTENSITY4 0x804A diff --git a/engine/client/gl_image.c b/engine/client/gl_image.c index 7444f30d..58d6b9ee 100644 --- a/engine/client/gl_image.c +++ b/engine/client/gl_image.c @@ -124,6 +124,19 @@ GL_TexFilter */ void GL_TexFilter( gltexture_t *tex, qboolean update ) { + qboolean allowNearest; + + switch( tex->texType ) + { + case TEX_NOMIP: + case TEX_LIGHTMAP: + allowNearest = false; + break; + default: + allowNearest = true; + break; + } + // set texture filter if( tex->flags & TF_DEPTHMAP ) { @@ -142,8 +155,16 @@ void GL_TexFilter( gltexture_t *tex, qboolean update ) } else { - pglTexParameteri( tex->target, GL_TEXTURE_MIN_FILTER, r_textureMagFilter ); - pglTexParameteri( tex->target, GL_TEXTURE_MAG_FILTER, r_textureMagFilter ); + if( r_textureMagFilter == GL_NEAREST && allowNearest ) + { + pglTexParameteri( tex->target, GL_TEXTURE_MIN_FILTER, r_textureMagFilter ); + pglTexParameteri( tex->target, GL_TEXTURE_MAG_FILTER, r_textureMagFilter ); + } + else + { + pglTexParameteri( tex->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + pglTexParameteri( tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + } } } else @@ -345,9 +366,17 @@ void R_TextureList_f( void ) case GL_RGB5: Msg( "RGB5 " ); break; + case GL_LUMINANCE4_ALPHA4: + Msg( "L4A4 " ); + break; + case GL_LUMINANCE_ALPHA: case GL_LUMINANCE8_ALPHA8: Msg( "L8A8 " ); break; + case GL_LUMINANCE4: + Msg( "L4 " ); + break; + case GL_LUMINANCE: case GL_LUMINANCE8: Msg( "L8 " ); break; @@ -469,7 +498,7 @@ void GL_RoundImageDimensions( word *width, word *height, texFlags_t flags, qbool GL_TextureFormat =============== */ -static GLenum GL_TextureFormat( gltexture_t *tex, int samples ) +static GLenum GL_TextureFormat( gltexture_t *tex, int *samples ) { qboolean compress; GLenum format; @@ -487,7 +516,7 @@ static GLenum GL_TextureFormat( gltexture_t *tex, int samples ) } else if( compress ) { - switch( samples ) + switch( *samples ) { case 1: format = GL_COMPRESSED_LUMINANCE_ARB; break; case 2: format = GL_COMPRESSED_LUMINANCE_ALPHA_ARB; break; @@ -503,25 +532,51 @@ static GLenum GL_TextureFormat( gltexture_t *tex, int samples ) { int bits = gl_texturebits->integer; - switch( samples ) + switch( *samples ) { case 1: format = GL_LUMINANCE8; break; case 2: format = GL_LUMINANCE8_ALPHA8; break; case 3: - switch( bits ) + if( gl_luminance_textures->integer ) { - case 16: format = GL_RGB5; break; - case 32: format = GL_RGB8; break; - default: format = GL_RGB; break; + switch( bits ) + { + case 16: format = GL_LUMINANCE4; break; + case 32: format = GL_LUMINANCE8; break; + default: format = GL_LUMINANCE; break; + } + *samples = 1; // merge for right calc statistics + } + else + { + switch( bits ) + { + case 16: format = GL_RGB5; break; + case 32: format = GL_RGB8; break; + default: format = GL_RGB; break; + } } break; case 4: default: - switch( bits ) + if( gl_luminance_textures->integer ) { - case 16: format = GL_RGBA4; break; - case 32: format = GL_RGBA8; break; - default: format = GL_RGBA; break; + switch( bits ) + { + case 16: format = GL_LUMINANCE4_ALPHA4; break; + case 32: format = GL_LUMINANCE8_ALPHA8; break; + default: format = GL_LUMINANCE_ALPHA; break; + } + *samples = 2; // merge for right calc statistics + } + else + { + switch( bits ) + { + case 16: format = GL_RGBA4; break; + case 32: format = GL_RGBA8; break; + default: format = GL_RGBA; break; + } } break; } @@ -809,7 +864,7 @@ static void GL_UploadTexture( rgbdata_t *pic, gltexture_t *tex, qboolean subImag // determine format inFormat = PFDesc[pic->type].glFormat; - outFormat = GL_TextureFormat( tex, samples ); + outFormat = GL_TextureFormat( tex, &samples ); tex->format = outFormat; // determine target @@ -930,6 +985,9 @@ int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags ) pic = FS_LoadImage( name, buf, size ); if( !pic ) return 0; // couldn't loading image + // force upload texture as RGB or RGBA (detail textures requires this) + if( flags & TF_FORCE_COLOR ) pic->flags |= IMAGE_HAS_COLOR; + // find a free texture slot if( r_numTextures == MAX_TEXTURES ) Host_Error( "GL_LoadTexture: MAX_TEXTURES limit exceeds\n" ); @@ -1003,6 +1061,9 @@ int GL_LoadTextureInternal( const char *name, rgbdata_t *pic, texFlags_t flags, Host_Error( "Couldn't find texture %s for update\n", name ); } + // force upload texture as RGB or RGBA (detail textures requires this) + if( flags & TF_FORCE_COLOR ) pic->flags |= IMAGE_HAS_COLOR; + // find a free texture slot if( r_numTextures == MAX_TEXTURES ) Host_Error( "GL_LoadTexture: MAX_TEXTURES limit exceeds\n" ); @@ -1345,17 +1406,18 @@ static void R_InitBuiltinTextures( void ) char *name; int *texnum; rgbdata_t *(*init)( texFlags_t *flags ); + int texType; } textures[] = { - { "*default", &tr.defaultTexture, R_InitDefaultTexture }, - { "*white", &tr.whiteTexture, R_InitWhiteTexture }, - { "*black", &tr.blackTexture, R_InitBlackTexture }, - { "*particle", &tr.particleTexture, R_InitParticleTexture }, - { "*particle2", &tr.particleTexture2, R_InitParticleTexture2 }, - { "*cintexture", &tr.cinTexture, R_InitCinematicTexture }, - { "*dlight", &tr.dlightTexture, R_InitDlightTexture }, - { "*sky", &tr.skyTexture, R_InitSkyTexture }, + { "*default", &tr.defaultTexture, R_InitDefaultTexture, TEX_SYSTEM }, + { "*white", &tr.whiteTexture, R_InitWhiteTexture, TEX_SYSTEM }, + { "*black", &tr.blackTexture, R_InitBlackTexture, TEX_SYSTEM }, + { "*particle", &tr.particleTexture, R_InitParticleTexture, TEX_SYSTEM }, + { "*particle2", &tr.particleTexture2, R_InitParticleTexture2, TEX_SYSTEM }, + { "*cintexture", &tr.cinTexture, R_InitCinematicTexture, TEX_NOMIP }, // force linear filter + { "*dlight", &tr.dlightTexture, R_InitDlightTexture, TEX_LIGHTMAP }, + { "*sky", &tr.skyTexture, R_InitSkyTexture, TEX_SYSTEM }, { NULL, NULL, NULL } }; size_t i, num_builtin_textures = sizeof( textures ) / sizeof( textures[0] ) - 1; @@ -1369,7 +1431,7 @@ static void R_InitBuiltinTextures( void ) if( pic == NULL ) continue; *textures[i].texnum = GL_LoadTextureInternal( textures[i].name, pic, flags, false ); - GL_SetTextureType( *textures[i].texnum, TEX_SYSTEM ); + GL_SetTextureType( *textures[i].texnum, textures[i].texType ); } } @@ -1428,7 +1490,9 @@ void R_ShutdownImages( void ) GL_SelectTexture( i ); pglBindTexture( GL_TEXTURE_2D, 0 ); - pglBindTexture( GL_TEXTURE_CUBE_MAP_ARB, 0 ); + + if( GL_Support( GL_TEXTURECUBEMAP_EXT )) + pglBindTexture( GL_TEXTURE_CUBE_MAP_ARB, 0 ); } for( i = 0, image = r_textures; i < r_numTextures; i++, image++ ) diff --git a/engine/client/gl_local.h b/engine/client/gl_local.h index a7ebbc60..d4c300fb 100644 --- a/engine/client/gl_local.h +++ b/engine/client/gl_local.h @@ -29,6 +29,7 @@ extern byte *r_temppool; #define BLOCK_HEIGHT 128 // lightmap block height #define MAX_TEXTURES 4096 +#define MAX_DETAIL_TEXTURES 256 #define MAX_LIGHTMAPS 128 #define SUBDIVIDE_SIZE 64 @@ -62,7 +63,8 @@ typedef enum TEX_LIGHTMAP, // lightmap textures TEX_DECAL, // decals TEX_VGUI, // vgui fonts or images - TEX_CUBEMAP // cubemap textures (sky) + TEX_CUBEMAP, // cubemap textures (sky) + TEX_DETAIL // detail textures } texType_t; typedef enum @@ -82,6 +84,7 @@ typedef enum TF_MAKELUMA = BIT(12), // create luma from quake texture TF_NORMALMAP = BIT(13), // is a normalmap TF_LIGHTMAP = BIT(14), // is a lightmap + TF_FORCE_COLOR = BIT(15), // force upload monochrome textures as RGB (detail textures) } texFlags_t; typedef struct gltexture_s @@ -103,6 +106,10 @@ typedef struct gltexture_s byte texType; // used for gl_showtextures size_t size; // upload size for debug targets + // detail textures stuff + float xscale; + float yscale; + struct gltexture_s *nextHash; } gltexture_t; @@ -308,7 +315,7 @@ void R_PushDlights( void ); void R_AnimateLight( void ); void R_MarkLights( dlight_t *light, int bit, mnode_t *node ); void R_LightDir( const vec3_t origin, vec3_t lightDir, float radius ); -void R_LightForPoint( const vec3_t point, color24 *ambientLight, qboolean invLight, float radius ); +void R_LightForPoint( const vec3_t point, color24 *ambientLight, qboolean invLight, qboolean useAmbient, float radius ); // // gl_rmain.c @@ -425,7 +432,6 @@ void GL_SetRenderMode( int mode ); void R_RunViewmodelEvents( void ); void R_DrawViewModel( void ); int R_GetSpriteTexture( const struct model_s *m_pSpriteModel, int frame ); -void R_LightForPoint( const vec3_t point, color24 *ambientLight, qboolean invLight, float radius ); void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, vec3_t saxis ); void R_RemoveEfrags( struct cl_entity_s *ent ); void R_AddEfrags( struct cl_entity_s *ent ); @@ -444,6 +450,7 @@ enum { GL_OPENGL_110 = 0, // base GL_WGL_SWAPCONTROL, + GL_WGL_PROCADDRESS, GL_HARDWARE_GAMMA_CONTROL, GL_ARB_VERTEX_BUFFER_OBJECT_EXT, GL_ENV_COMBINE_EXT, @@ -576,6 +583,7 @@ extern convar_t *gl_texturemode; extern convar_t *gl_texture_lodbias; extern convar_t *gl_showtextures; extern convar_t *gl_compress_textures; +extern convar_t *gl_luminance_textures; extern convar_t *gl_wireframe; extern convar_t *gl_allow_static; extern convar_t *gl_picmip; @@ -592,6 +600,7 @@ extern convar_t *r_norefresh; extern convar_t *r_lighting_extended; extern convar_t *r_lighting_modulate; extern convar_t *r_lighting_ambient; +extern convar_t *r_detailtextures; extern convar_t *r_faceplanecull; extern convar_t *r_drawentities; extern convar_t *r_adjust_fov; diff --git a/engine/client/gl_rlight.c b/engine/client/gl_rlight.c index 338c4fe3..e0d8fdc9 100644 --- a/engine/client/gl_rlight.c +++ b/engine/client/gl_rlight.c @@ -125,11 +125,11 @@ void R_MarkLights( dlight_t *light, int bit, mnode_t *node ) } // mark the polygons - surf = cl.worldmodel->surfaces + node->firstsurface; + surf = RI.currentmodel->surfaces + node->firstsurface; for( i = 0; i < node->numsurfaces; i++, surf++ ) { - mextrasurf_t *info = SURF_INFO( surf, cl.worldmodel ); + mextrasurf_t *info = SURF_INFO( surf, RI.currentmodel ); if( !BoundsAndSphereIntersect( info->mins, info->maxs, light->origin, light->radius )) continue; // no intersection @@ -160,6 +160,9 @@ void R_PushDlights( void ) // advanced yet for this frame l = cl_dlights; + RI.currententity = clgame.entities; + RI.currentmodel = RI.currententity->model; + for( i = 0; i < MAX_DLIGHTS; i++, l++ ) { if( l->die < cl.time || !l->radius ) @@ -168,7 +171,7 @@ void R_PushDlights( void ) if( R_CullSphere( l->origin, l->radius, 15 )) continue; - R_MarkLights( l, 1<nodes ); + R_MarkLights( l, 1<nodes ); } } @@ -268,7 +271,7 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, const vec3 R_LightForPoint ================= */ -void R_LightForPoint( const vec3_t point, color24 *ambientLight, qboolean invLight, float radius ) +void R_LightForPoint( const vec3_t point, color24 *ambientLight, qboolean invLight, qboolean useAmbient, float radius ) { dlight_t *dl; pmtrace_t trace; @@ -368,6 +371,7 @@ void R_LightForPoint( const vec3_t point, color24 *ambientLight, qboolean invLig // R_RecursiveLightPoint didn't hit anything, so use default value ambient = bound( 0.1f, r_lighting_ambient->value, 1.0f ); + if( !useAmbient ) ambient = 0.0f; // clear ambient ambientLight->r = 255 * ambient; ambientLight->g = 255 * ambient; ambientLight->b = 255 * ambient; diff --git a/engine/client/gl_rmain.c b/engine/client/gl_rmain.c index ca0c65df..c7a331aa 100644 --- a/engine/client/gl_rmain.c +++ b/engine/client/gl_rmain.c @@ -63,6 +63,9 @@ static qboolean R_StaticEntity( cl_entity_t *ent ) if( ent->curstate.frame || ent->model->flags & MODEL_CONVEYOR ) return false; + if( ent->curstate.scale ) // waveheight specified + return false; + if( !VectorIsNull( ent->origin ) || !VectorIsNull( ent->angles )) return false; @@ -375,7 +378,9 @@ R_Clear */ static void R_Clear( int bitMask ) { - int bits; + int bits; + + pglClearColor( 0.5f, 0.5f, 0.5f, 1.0f ); bits = GL_DEPTH_BUFFER_BIT; @@ -570,8 +575,9 @@ static void R_SetupFrame( void ) R_AnimateLight(); R_RunViewmodelEvents(); - - tr.framecount++; + + // g-cont. keep actual frame for all viewpasses + if( !RI.refdef.nextView ) tr.framecount++; // sort translucents entities by rendermode and distance qsort( tr.trans_entities, tr.num_trans_entities, sizeof( cl_entity_t* ), R_TransEntityCompare ); @@ -828,7 +834,7 @@ void R_DrawEntitiesOnList( void ) pglDepthMask( GL_FALSE ); glState.drawTrans = true; - // then draw translicent entities + // then draw translucent entities for( i = 0; i < tr.num_trans_entities; i++ ) { if( RI.refdef.onlyClientDraw ) diff --git a/engine/client/gl_rmisc.c b/engine/client/gl_rmisc.c index 4bae52d1..07383f50 100644 --- a/engine/client/gl_rmisc.c +++ b/engine/client/gl_rmisc.c @@ -18,6 +18,249 @@ GNU General Public License for more details. #include "gl_local.h" #include "mod_local.h" +typedef struct +{ + const char *texname; + const char *detail; + const char material; + int lMin; + int lMax; +} dmaterial_t; + +// default rules for apply detail textures. +// move this to external script ? +static const dmaterial_t detail_table[] = +{ +{ "crt", "dt_conc", 'C', 0, 0 }, // concrete +{ "rock", "dt_rock", 'C', 0, 0 }, +{ "conc", "dt_conc", 'C', 0, 0 }, +{ "wall", "dt_brick", 'C', 0, 0 }, +{ "crete", "dt_conc", 'C', 0, 0 }, +{ "generic", "dt_brick", 'C', 0, 0 }, +{ "metal", "dt_metal%i", 'M', 1, 2 }, // metal +{ "mtl", "dt_metal%i", 'M', 1, 2 }, +{ "pipe", "dt_metal%i", 'M', 1, 2 }, +{ "elev", "dt_metal%i", 'M', 1, 2 }, +{ "sign", "dt_metal%i", 'M', 1, 2 }, +{ "barrel", "dt_metal%i", 'M', 1, 2 }, +{ "bath", "dt_ssteel1", 'M', 1, 2 }, +{ "refbridge", "dt_metal%i", 'M', 1, 2 }, +{ "panel", "dt_ssteel1", 'M', 0, 0 }, +{ "brass", "dt_ssteel1", 'M', 0, 0 }, +{ "car", "dt_metal%i", 'M', 1, 2 }, +{ "circuit", "dt_metal%i", 'M', 1, 2 }, +{ "steel", "dt_ssteel1", 'M', 0, 0 }, +{ "dirt", "dt_ground%i", 'D', 1, 5 }, // dirt +{ "drt", "dt_ground%i", 'D', 1, 5 }, +{ "out", "dt_ground%i", 'D', 1, 5 }, +{ "grass", "dt_grass1", 'D', 0, 0 }, +{ "mud", "dt_carpet1", 'D', 0, 0 }, // FIXME +{ "vent", "dt_ssteel1", 'V', 1, 4 }, // vent +{ "duct", "dt_ssteel1", 'V', 1, 4 }, +{ "tile", "dt_smooth%i", 'T', 1, 2 }, +{ "labflr", "dt_smooth%i", 'T', 1, 2 }, +{ "bath", "dt_smooth%i", 'T', 1, 2 }, +{ "grate", "dt_stone%i", 'G', 1, 4 }, // vent +{ "stone", "dt_stone%i", 'G', 1, 4 }, +{ "grt", "dt_stone%i", 'G', 1, 4 }, +{ "wood", "dt_wood%i", 'W', 1, 3 }, +{ "wd", "dt_wood%i", 'W', 1, 3 }, +{ "table", "dt_wood%i", 'W', 1, 3 }, +{ "board", "dt_wood%i", 'W', 1, 3 }, +{ "chair", "dt_wood%i", 'W', 1, 3 }, +{ "brd", "dt_wood%i", 'W', 1, 3 }, +{ "carp", "dt_carpet1", 'W', 1, 3 }, +{ "book", "dt_wood%i", 'W', 1, 3 }, +{ "box", "dt_wood%i", 'W', 1, 3 }, +{ "cab", "dt_wood%i", 'W', 1, 3 }, +{ "couch", "dt_wood%i", 'W', 1, 3 }, +{ "crate", "dt_wood%i", 'W', 1, 3 }, +{ "poster", "dt_plaster%i", 'W', 1, 2 }, +{ "sheet", "dt_plaster%i", 'W', 1, 2 }, +{ "stucco", "dt_plaster%i", 'W', 1, 2 }, +{ "comp", "dt_smooth1", 'P', 0, 0 }, +{ "cmp", "dt_smooth1", 'P', 0, 0 }, +{ "elec", "dt_smooth1", 'P', 0, 0 }, +{ "vend", "dt_smooth1", 'P', 0, 0 }, +{ "monitor", "dt_smooth1", 'P', 0, 0 }, +{ "phone", "dt_smooth1", 'P', 0, 0 }, +{ "glass", "dt_ssteel1", 'Y', 0, 0 }, +{ "window", "dt_ssteel1", 'Y', 0, 0 }, +{ "flesh", "dt_rough1", 'F', 0, 0 }, +{ "meat", "dt_rough1", 'F', 0, 0 }, +{ "fls", "dt_rough1", 'F', 0, 0 }, +{ "ground", "dt_ground%i", 'D', 1, 5 }, +{ "gnd", "dt_ground%i", 'D', 1, 5 }, +{ "snow", "dt_snow%i", 'O', 1, 2 }, // snow +{ NULL, NULL, 0, 0, 0 } +}; + +static const char *R_DetailTextureForName( const char *name ) +{ + const dmaterial_t *table; + + if( !name || !*name ) return NULL; + if( !Q_strnicmp( name, "sky", 3 )) + return NULL; // never details for sky + + // never apply details for liquids + if( !Q_strnicmp( name + 1, "!lava", 5 )) + return NULL; + if( !Q_strnicmp( name + 1, "!slime", 6 )) + return NULL; + if( !Q_strnicmp( name, "!cur_90", 7 )) + return NULL; + if( !Q_strnicmp( name, "!cur_0", 6 )) + return NULL; + if( !Q_strnicmp( name, "!cur_270", 8 )) + return NULL; + if( !Q_strnicmp( name, "!cur_180", 8 )) + return NULL; + if( !Q_strnicmp( name, "!cur_up", 7 )) + return NULL; + if( !Q_strnicmp( name, "!cur_dwn", 8 )) + return NULL; + if( name[0] == '!' ) + return NULL; + + // never apply details to the special textures + if( !Q_strnicmp( name, "origin", 6 )) + return NULL; + if( !Q_strnicmp( name, "clip", 4 )) + return NULL; + if( !Q_strnicmp( name, "hint", 4 )) + return NULL; + if( !Q_strnicmp( name, "skip", 4 )) + return NULL; + if( !Q_strnicmp( name, "translucent", 11 )) + return NULL; + if( !Q_strnicmp( name, "3dsky", 5 )) + return NULL; + if( name[0] == '@' ) + return NULL; + + // last check ... + if( !Q_strnicmp( name, "null", 4 )) + return NULL; + + for( table = detail_table; table && table->texname; table++ ) + { + if( Q_stristr( name, table->texname )) + { + if(( table->lMin + table->lMax ) > 0 ) + return va( table->detail, Com_RandomLong( table->lMin, table->lMax )); + return table->detail; + } + } + return "dt_smooth1"; // default +} + +void R_CreateDetailTexturesList( const char *filename ) +{ + file_t *detail_txt = NULL; + const char *detail_name, *texname; + int i; + + for( i = 0; i < cl.worldmodel->numtextures; i++ ) + { + texname = cl.worldmodel->textures[i]->name; + detail_name = R_DetailTextureForName( texname ); + if( !detail_name ) continue; + + // detailtexture detected + if( detail_name ) + { + if( !detail_txt ) detail_txt = FS_Open( filename, "wb", false ); + if( !detail_txt ) + { + MsgDev( D_ERROR, "Can't write %s\n", filename ); + break; + } + + // store detailtexture description + FS_Printf( detail_txt, "%s detail/%s 10.0 10.0\n", texname, detail_name ); + } + } + + if( detail_txt ) FS_Close( detail_txt ); +} + +void R_ParseDetailTextures( const char *filename ) +{ + char *afile, *pfile; + string token, texname, detail_texname; + float xScale, yScale; + texture_t *tex; + int i; + + if( r_detailtextures->integer >= 2 && !FS_FileExists( filename, false )) + { + // use built-in generator for detail textures + R_CreateDetailTexturesList( filename ); + } + + afile = FS_LoadFile( filename, NULL, false ); + if( !afile ) return; + + pfile = afile; + + // format: 'texturename' 'detailtexture' 'xScale' 'yScale' + while(( pfile = COM_ParseFile( pfile, token )) != NULL ) + { + texname[0] = '\0'; + + // read texname + if( token[0] == '{' ) + { + // NOTE: COM_ParseFile handled some symbols seperately + // this code will be fix it + pfile = COM_ParseFile( pfile, token ); + Q_strncat( texname, "{", sizeof( texname )); + Q_strncat( texname, token, sizeof( texname )); + } + else Q_strncpy( texname, token, sizeof( texname )); + + // read detailtexture name + pfile = COM_ParseFile( pfile, token ); + Q_snprintf( detail_texname, sizeof( detail_texname ), "gfx/%s.tga", token ); + + // read scales + pfile = COM_ParseFile( pfile, token ); + xScale = Q_atof( token ); + + pfile = COM_ParseFile( pfile, token ); + yScale = Q_atof( token ); + + if( xScale <= 0.0f || yScale <= 0.0f ) + continue; + + // search for existing texture and uploading detail texture + for( i = 0; i < cl.worldmodel->numtextures; i++ ) + { + tex = cl.worldmodel->textures[i]; + + if( Q_stricmp( tex->name, texname )) + continue; + + tex->dt_texturenum = GL_LoadTexture( detail_texname, NULL, 0, TF_FORCE_COLOR ); + + // texture is loaded + if( tex->dt_texturenum ) + { + gltexture_t *glt; + + GL_SetTextureType( tex->dt_texturenum, TEX_DETAIL ); + glt = R_GetTexture( tex->dt_texturenum ); + glt->xscale = xScale; + glt->yscale = yScale; + } + break; + } + } + + Mem_Free( afile ); +} + void R_NewMap( void ) { int i; @@ -45,4 +288,16 @@ void R_NewMap( void ) cl.worldmodel->textures[i]->texturechain = NULL; } + + // upload detailtextures + if( r_detailtextures->integer ) + { + string mapname, filepath; + + Q_strncpy( mapname, cl.worldmodel->name, sizeof( mapname )); + FS_StripExtension( mapname ); + Q_sprintf( filepath, "%s_detail.txt", mapname ); + + R_ParseDetailTextures( filepath ); + } } \ No newline at end of file diff --git a/engine/client/gl_rsurf.c b/engine/client/gl_rsurf.c index e87c2513..c9d9da87 100644 --- a/engine/client/gl_rsurf.c +++ b/engine/client/gl_rsurf.c @@ -35,6 +35,8 @@ static byte visbytes[MAX_MAP_LEAFS/8]; static uint r_blocklights[BLOCK_WIDTH*BLOCK_HEIGHT*3]; static glpoly_t *fullbright_polys[MAX_TEXTURES]; static qboolean draw_fullbrights = false; +static glpoly_t *detail_polys[MAX_TEXTURES]; +static qboolean draw_details = false; static gllightmapstate_t gl_lms; static msurface_t *skychain = NULL; @@ -163,7 +165,8 @@ static void SubdividePolygon_r( msurface_t *warpface, int numverts, float *verts total_s += s; total_t += t; - if(!( warpface->flags & SURF_DRAWTURB )) + // for speed reasons + if( !( warpface->flags & SURF_DRAWTURB )) { // lightmap texture coordinates s = DotProduct( verts, warpface->texinfo->vecs[0] ) + warpface->texinfo->vecs[0][3]; @@ -191,8 +194,12 @@ static void SubdividePolygon_r( msurface_t *warpface, int numverts, float *verts VectorScale( total, vertsDiv, poly->verts[0] ); poly->verts[0][3] = total_s * vertsDiv; poly->verts[0][4] = total_t * vertsDiv; - poly->verts[0][5] = total_ls * vertsDiv; - poly->verts[0][6] = total_lt * vertsDiv; + + if( !( warpface->flags & SURF_DRAWTURB )) + { + poly->verts[0][5] = total_ls * vertsDiv; + poly->verts[0][6] = total_lt * vertsDiv; + } // copy first vertex to last Q_memcpy( poly->verts[i+1], poly->verts[1], sizeof( poly->verts[0] )); @@ -250,13 +257,6 @@ void GL_BuildPolygonFromSurface( msurface_t *fa ) if( !fa->texinfo || !fa->texinfo->texture ) return; // bad polygon ? - if( fa->texinfo->texture->anim_total < 0 ) - { - // random tileing. subdivide the polygon - GL_SubdivideSurface( fa ); - return; - } - // reconstruct the polygon pedges = loadmodel->edges; lnumverts = fa->numedges; @@ -324,17 +324,17 @@ texture_t *R_TextureAnimation( texture_t *base, int surfacenum ) int reletive; int count, speed; - // random tileng textures + // random tiling textures if( base->anim_total < 0 ) { - reletive = surfacenum % abs( base->anim_total ); + reletive = abs( surfacenum ) % abs( base->anim_total ); count = 0; while( base->anim_min > reletive || base->anim_max <= reletive ) { base = base->anim_next; - if( !base ) Host_Error( "R_TextureAnimation: broken loop\n" ); - if( ++count > 100 ) Host_Error( "R_TextureAnimation: infinite loop\n" ); + if( !base ) Host_Error( "R_TextureRandomTiling: broken loop\n" ); + if( ++count > 100 ) Host_Error( "R_TextureRandomTiling: infinite loop\n" ); } return base; } @@ -618,14 +618,13 @@ static void R_BuildLightMap( msurface_t *surf, byte *dest, int stride ) DrawGLPoly ================ */ -void DrawGLPoly( glpoly_t *p, texture_t *tex ) +void DrawGLPoly( glpoly_t *p, float xScale, float yScale ) { + float *v; float sOffset, sy; float tOffset, cy; cl_entity_t *e = RI.currententity; - qboolean random_tiles = false; - texture_t *t; - glpoly_t *base; + int i, hasScale = false; if( p->flags & SURF_CONVEYOR ) { @@ -657,29 +656,21 @@ void DrawGLPoly( glpoly_t *p, texture_t *tex ) sOffset = tOffset = 0.0f; } - if( p && p->next ) random_tiles = true; + if( xScale != 0.0f && yScale != 0.0f ) + hasScale = true; - for( base = p; p != NULL; p = p->next ) + pglBegin( GL_POLYGON ); + + for( i = 0, v = p->verts[0]; i < p->numverts; i++, v += VERTEXSIZE ) { - float *v; - int i; + if( hasScale ) + pglTexCoord2f(( v[3] + sOffset ) * xScale, ( v[4] + tOffset ) * yScale ); + else pglTexCoord2f( v[3] + sOffset, v[4] + tOffset ); - if( random_tiles && tex ) - { - t = R_TextureAnimation( tex, base - p ); - GL_MBind( t->gl_texturenum ); - } - - pglBegin( GL_POLYGON ); - - for( i = 0, v = p->verts[0]; i < p->numverts; i++, v += VERTEXSIZE ) - { - pglTexCoord2f( v[3] + sOffset, v[4] + tOffset ); - pglVertex3fv( v ); - } - - pglEnd(); + pglVertex3fv( v ); } + + pglEnd(); } /* @@ -698,23 +689,19 @@ void DrawGLPolyChain( glpoly_t *p, float soffset, float toffset ) for( ; p != NULL; p = p->chain ) { - glpoly_t *p2; float *v; int i; - for( p2 = p; p2 != NULL; p2 = p2->next ) - { - pglBegin( GL_POLYGON ); + pglBegin( GL_POLYGON ); - v = p2->verts[0]; - for( i = 0; i < p2->numverts; i++, v += VERTEXSIZE ) - { - if( !dynamic ) pglTexCoord2f( v[5], v[6] ); - else pglTexCoord2f( v[5] - soffset, v[6] - toffset ); - pglVertex3fv( v ); - } - pglEnd (); + v = p->verts[0]; + for( i = 0; i < p->numverts; i++, v += VERTEXSIZE ) + { + if( !dynamic ) pglTexCoord2f( v[5], v[6] ); + else pglTexCoord2f( v[5] - soffset, v[6] - toffset ); + pglVertex3fv( v ); } + pglEnd (); } } @@ -822,7 +809,7 @@ void R_BlendLightmaps( void ) info = SURF_INFO( surf, RI.currentmodel ); // try uploading the block now - if( !LM_AllocBlock( smax, tmax, &info->dlight_s, &info->dlight_t ) ) + if( !LM_AllocBlock( smax, tmax, &info->dlight_s, &info->dlight_t )) Host_Error( "AllocBlock: full\n" ); base = gl_lms.lightmap_buffer; @@ -887,7 +874,7 @@ void R_RenderFullbrights( void ) { if( p->flags & SURF_DRAWTURB ) EmitWaterPolys( p, ( p->flags & SURF_NOCULL )); - else DrawGLPoly( p, NULL ); // disable random tiling (chain is already used) + else DrawGLPoly( p, 0.0f, 0.0f ); } fullbright_polys[i] = NULL; @@ -901,6 +888,50 @@ void R_RenderFullbrights( void ) draw_fullbrights = false; } +/* +================ +R_RenderDetails +================ +*/ +void R_RenderDetails( void ) +{ + gltexture_t *glt; + glpoly_t *p; + int i; + + if( !draw_details ) + return; + + pglEnable( GL_BLEND ); + pglBlendFunc( GL_DST_COLOR, GL_SRC_COLOR ); + pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL ); + + if( RI.currententity->curstate.rendermode == kRenderTransAlpha ) + pglDepthFunc( GL_EQUAL ); + + for( i = 1; i < MAX_TEXTURES; i++ ) + { + if( !detail_polys[i] ) + continue; + + GL_Bind( GL_TEXTURE0, i ); + glt = R_GetTexture( i ); + + for( p = detail_polys[i]; p; p = p->next ) + DrawGLPoly( p, glt->xscale, glt->yscale ); + + detail_polys[i] = NULL; + } + + pglDisable( GL_BLEND ); + pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); + + if( RI.currententity->curstate.rendermode == kRenderTransAlpha ) + pglDepthFunc( GL_LEQUAL ); + + draw_details = false; +} + /* ================ R_RenderBrushPoly @@ -926,7 +957,7 @@ void R_RenderBrushPoly( msurface_t *fa ) return; } - t = R_TextureAnimation( fa->texinfo->texture, 0 ); + t = R_TextureAnimation( fa->texinfo->texture, fa - RI.currententity->model->surfaces ); GL_MBind( t->gl_texturenum ); if( fa->flags & SURF_DRAWTURB ) @@ -943,8 +974,16 @@ void R_RenderBrushPoly( msurface_t *fa ) fullbright_polys[t->fb_texturenum] = fa->polys; draw_fullbrights = true; } + else if( r_detailtextures->integer && t->dt_texturenum ) + { + // HACKHACK: store details in poly->next (only for non-water surfaces) + // can't rendering both luma and detail textures simultaneously + fa->polys->next = detail_polys[t->dt_texturenum]; + detail_polys[t->dt_texturenum] = fa->polys; + draw_details = true; + } - DrawGLPoly( fa->polys, fa->texinfo->texture ); + DrawGLPoly( fa->polys, 0.0f, 0.0f ); DrawSurfaceDecals( fa ); // check for lightmap modification @@ -1214,10 +1253,12 @@ void R_DrawBrushModel( cl_entity_t *e ) { int i, k, num_sorted; qboolean need_sort = false; + vec3_t origin_l, oldorigin; vec3_t mins, maxs; msurface_t *psurf; model_t *clmodel; qboolean rotated; + matrix4x4 imatrix; dlight_t *l; clmodel = e->model; @@ -1258,25 +1299,18 @@ void R_DrawBrushModel( cl_entity_t *e ) Matrix4x4_VectorITransform( RI.objectMatrix, temp, modelorg ); } - // calculate dynamic lighting for bmodel if it's not an - // instanced model - if( clmodel->firstmodelsurface != 0 ) + // calculate dynamic lighting for bmodel + for( k = 0, l = cl_dlights; k < MAX_DLIGHTS; k++, l++ ) { - vec3_t origin_l, oldorigin; - matrix4x4 imatrix; + if( l->die < cl.time || !l->radius ) + continue; - for( k = 0, l = cl_dlights; k < MAX_DLIGHTS; k++, l++ ) - { - if( l->die < cl.time || !l->radius ) - continue; - - VectorCopy( l->origin, oldorigin ); // save oldorigin - Matrix4x4_Invert_Simple( imatrix, RI.objectMatrix ); - Matrix4x4_VectorTransform( imatrix, l->origin, origin_l ); - VectorCopy( origin_l, l->origin ); // move light in bmodel space - R_MarkLights( l, 1<nodes + clmodel->hulls[0].firstclipnode ); - VectorCopy( oldorigin, l->origin ); // restore lightorigin - } + VectorCopy( l->origin, oldorigin ); // save oldorigin + Matrix4x4_Invert_Simple( imatrix, RI.objectMatrix ); + Matrix4x4_VectorTransform( imatrix, l->origin, origin_l ); + VectorCopy( origin_l, l->origin ); // move light in bmodel space + R_MarkLights( l, 1<nodes + clmodel->hulls[0].firstclipnode ); + VectorCopy( oldorigin, l->origin ); // restore lightorigin } // setup the rendermode @@ -1349,6 +1383,8 @@ void R_DrawBrushModel( cl_entity_t *e ) R_BlendLightmaps(); R_RenderFullbrights(); + R_RenderDetails(); + R_LoadIdentity(); // restore worldmatrix } @@ -1370,16 +1406,12 @@ void R_DrawStaticModel( cl_entity_t *e ) if( R_CullBox( clmodel->mins, clmodel->maxs, RI.clipFlags )) return; - // calculate dynamic lighting for bmodel if it's not an - // instanced model - if( clmodel->firstmodelsurface != 0 ) + // calculate dynamic lighting for bmodel + for( k = 0, l = cl_dlights; k < MAX_DLIGHTS; k++, l++ ) { - for( k = 0, l = cl_dlights; k < MAX_DLIGHTS; k++, l++ ) - { - if( l->die < cl.time || !l->radius ) - continue; - R_MarkLights( l, 1<nodes + clmodel->hulls[0].firstclipnode ); - } + if( l->die < cl.time || !l->radius ) + continue; + R_MarkLights( l, 1<nodes + clmodel->hulls[0].firstclipnode ); } psurf = &clmodel->surfaces[clmodel->firstmodelsurface]; @@ -1463,13 +1495,12 @@ void R_PlaneForMirror( msurface_t *surf, mplane_t *out ) R_RotateForEntity( ent ); else R_TranslateForEntity( ent ); - // tranform mirror plane by entity matrix + // transform mirror plane by entity matrix if( !tr.modelviewIdentity ) { mplane_t tmp; tmp = *out; - Matrix4x4_TransformPositivePlane( RI.objectMatrix, tmp.normal, tmp.dist, out->normal, &out->dist ); } } @@ -1663,9 +1694,11 @@ R_DrawTriangleOutlines */ void R_DrawTriangleOutlines( void ) { - int i, j; - glpoly_t *p, *p2; - + int i, j; + msurface_t *surf; + glpoly_t *p; + float *v; + if( !gl_wireframe->integer ) return; @@ -1674,30 +1707,38 @@ void R_DrawTriangleOutlines( void ) pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); pglPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); + // render static surfaces first for( i = 0; i < MAX_LIGHTMAPS; i++ ) { - msurface_t *surf; - float *v; - for( surf = gl_lms.lightmap_surfaces[i]; surf != NULL; surf = surf->lightmapchain ) { p = surf->polys; - -// for( ; p != NULL; p = p->chain ) + for( ; p != NULL; p = p->chain ) { - p2 = p; - - for( p2 = p; p2; p2 = p2->next ) - { - pglBegin( GL_POLYGON ); - for( j = 0, v = p2->verts[0]; j < p2->numverts; j++, v += VERTEXSIZE ) - pglVertex3fv( v ); - pglEnd (); - } + pglBegin( GL_POLYGON ); + v = p->verts[0]; + for( j = 0; j < p->numverts; j++, v += VERTEXSIZE ) + pglVertex3fv( v ); + pglEnd (); } } } + // render surfaces with dynamic lightmaps + for( surf = gl_lms.dynamic_surfaces; surf != NULL; surf = surf->lightmapchain ) + { + p = surf->polys; + + for( ; p != NULL; p = p->chain ) + { + pglBegin( GL_POLYGON ); + v = p->verts[0]; + for( j = 0; j < p->numverts; j++, v += VERTEXSIZE ) + pglVertex3fv( v ); + pglEnd (); + } + } + pglPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); pglEnable( GL_DEPTH_TEST ); pglEnable( GL_TEXTURE_2D ); @@ -1719,6 +1760,8 @@ void R_DrawWorld( void ) VectorCopy( RI.cullorigin, modelorg ); Q_memset( gl_lms.lightmap_surfaces, 0, sizeof( gl_lms.lightmap_surfaces )); Q_memset( fullbright_polys, 0, sizeof( fullbright_polys )); + Q_memset( detail_polys, 0, sizeof( detail_polys )); + RI.currentWaveHeight = RI.waveHeight; GL_SetRenderMode( kRenderNormal ); gl_lms.dynamic_surfaces = NULL; @@ -1735,6 +1778,7 @@ void R_DrawWorld( void ) R_BlendLightmaps(); R_RenderFullbrights(); + R_RenderDetails(); if( skychain ) R_DrawSkyBox(); diff --git a/engine/client/gl_rsurf.old b/engine/client/gl_rsurf.old index e760b490..7e13d814 100644 --- a/engine/client/gl_rsurf.old +++ b/engine/client/gl_rsurf.old @@ -21,34 +21,23 @@ GNU General Public License for more details. typedef struct { - qboolean lightmap_modified[MAX_LIGHTMAPS]; - wrect_t lightmap_rectchange[MAX_LIGHTMAPS]; - uint allocated[MAX_LIGHTMAPS][BLOCK_WIDTH]; - byte lightmaps[MAX_LIGHTMAPS*BLOCK_WIDTH*BLOCK_HEIGHT*4]; -} lightmap_state_t; - -typedef struct gl_light_s -{ - int local[2]; - int minlight; // rad - minlight - int rad; -} gl_light_t; + int allocated[BLOCK_WIDTH]; + int current_lightmap_texture; + msurface_t *dynamic_surfaces; + msurface_t *lightmap_surfaces[MAX_LIGHTMAPS]; + byte lightmap_buffer[BLOCK_WIDTH*BLOCK_HEIGHT*4]; +} gllightmapstate_t; static vec3_t modelorg; // relative to viewpoint static vec3_t modelmins; static vec3_t modelmaxs; static byte visbytes[MAX_MAP_LEAFS/8]; -static uint r_blockLights[BLOCK_WIDTH*BLOCK_HEIGHT*3]; -static glpoly_t *lightmap_polys[MAX_LIGHTMAPS]; +static uint r_blocklights[BLOCK_WIDTH*BLOCK_HEIGHT*3]; static glpoly_t *fullbright_polys[MAX_TEXTURES]; static qboolean draw_fullbrights = false; -static lightmap_state_t r_lmState; +static gllightmapstate_t gl_lms; static msurface_t *skychain = NULL; -static gl_light_t r_dlights[MAX_DLIGHTS]; -static int r_numdlights; - -static void R_BuildLightMap( msurface_t *surf, byte *dest, int stride ); static void LM_UploadBlock( int lightmapnum ); byte *Mod_GetCurrentVis( void ) @@ -78,9 +67,9 @@ static void SubdividePolygon_r( msurface_t *warpface, int numverts, float *verts { int i, j, k, f, b; vec3_t mins, maxs; - float m, frac, s, t, *v; + float m, frac, s, t, *v, vertsDiv; vec3_t front[SUBDIVIDE_SIZE], back[SUBDIVIDE_SIZE], total; - float dist[SUBDIVIDE_SIZE], total_s, total_t; + float dist[SUBDIVIDE_SIZE], total_s, total_t, total_ls, total_lt; glpoly_t *poly; if( numverts > ( SUBDIVIDE_SIZE - 4 )) @@ -147,26 +136,63 @@ static void SubdividePolygon_r( msurface_t *warpface, int numverts, float *verts warpface->polys = poly; poly->numverts = numverts + 2; VectorClear( total ); - total_s = 0; - total_t = 0; + total_s = total_ls = 0.0f; + total_t = total_lt = 0.0f; for( i = 0; i < numverts; i++, verts += 3 ) { VectorCopy( verts, poly->verts[i+1] ); - s = DotProduct( verts, warpface->texinfo->vecs[0] ); - t = DotProduct( verts, warpface->texinfo->vecs[1] ); - - total_s += s; - total_t += t; VectorAdd( total, verts, total ); + if( warpface->flags & SURF_DRAWTURB ) + { + s = DotProduct( verts, warpface->texinfo->vecs[0] ); + t = DotProduct( verts, warpface->texinfo->vecs[1] ); + } + else + { + s = DotProduct( verts, warpface->texinfo->vecs[0] ) + warpface->texinfo->vecs[0][3]; + t = DotProduct( verts, warpface->texinfo->vecs[1] ) + warpface->texinfo->vecs[1][3]; + s /= warpface->texinfo->texture->width; + t /= warpface->texinfo->texture->height; + } + poly->verts[i+1][3] = s; poly->verts[i+1][4] = t; + + total_s += s; + total_t += t; + + if(!( warpface->flags & SURF_DRAWTURB )) + { + // lightmap texture coordinates + s = DotProduct( verts, warpface->texinfo->vecs[0] ) + warpface->texinfo->vecs[0][3]; + s -= warpface->texturemins[0]; + s += warpface->light_s * LM_SAMPLE_SIZE; + s += 8; + s /= BLOCK_WIDTH * LM_SAMPLE_SIZE; //fa->texinfo->texture->width; + + t = DotProduct( verts, warpface->texinfo->vecs[1] ) + warpface->texinfo->vecs[1][3]; + t -= warpface->texturemins[1]; + t += warpface->light_t * LM_SAMPLE_SIZE; + t += 8; + t /= BLOCK_HEIGHT * LM_SAMPLE_SIZE; //fa->texinfo->texture->height; + + poly->verts[i+1][5] = s; + poly->verts[i+1][6] = t; + + total_ls += s; + total_lt += t; + } } - VectorScale( total, ( 1.0f / numverts ), poly->verts[0] ); - poly->verts[0][3] = total_s / numverts; - poly->verts[0][4] = total_t / numverts; + vertsDiv = ( 1.0f / (float)numverts ); + + VectorScale( total, vertsDiv, poly->verts[0] ); + poly->verts[0][3] = total_s * vertsDiv; + poly->verts[0][4] = total_t * vertsDiv; + poly->verts[0][5] = total_ls * vertsDiv; + poly->verts[0][6] = total_lt * vertsDiv; // copy first vertex to last Q_memcpy( poly->verts[i+1], poly->verts[1], sizeof( poly->verts[0] )); @@ -196,7 +222,7 @@ void GL_SubdivideSurface( msurface_t *fa ) if( lindex > 0 ) vec = loadmodel->vertexes[loadmodel->edges[lindex].v[0]].position; else vec = loadmodel->vertexes[loadmodel->edges[-lindex].v[1]].position; - VectorCopy (vec, verts[numverts]); + VectorCopy( vec, verts[numverts] ); numverts++; } @@ -223,7 +249,15 @@ void GL_BuildPolygonFromSurface( msurface_t *fa ) if( !fa->texinfo || !fa->texinfo->texture ) return; // bad polygon ? - +#if 0 + // this causes problem with decals. disabled until done + if( fa->texinfo->texture->anim_total < 0 ) + { + // random tileing. subdivide the polygon + GL_SubdivideSurface( fa ); + return; + } +#endif // reconstruct the polygon pedges = loadmodel->edges; lnumverts = fa->numedges; @@ -264,15 +298,15 @@ void GL_BuildPolygonFromSurface( msurface_t *fa ) // lightmap texture coordinates s = DotProduct( vec, fa->texinfo->vecs[0] ) + fa->texinfo->vecs[0][3]; s -= fa->texturemins[0]; - s += fa->light_s * 16; + s += fa->light_s * LM_SAMPLE_SIZE; s += 8; - s /= BLOCK_WIDTH * 16; //fa->texinfo->texture->width; + s /= BLOCK_WIDTH * LM_SAMPLE_SIZE; //fa->texinfo->texture->width; t = DotProduct( vec, fa->texinfo->vecs[1] ) + fa->texinfo->vecs[1][3]; t -= fa->texturemins[1]; - t += fa->light_t * 16; + t += fa->light_t * LM_SAMPLE_SIZE; t += 8; - t /= BLOCK_HEIGHT * 16; //fa->texinfo->texture->height; + t /= BLOCK_HEIGHT * LM_SAMPLE_SIZE; //fa->texinfo->texture->height; poly->verts[i][5] = s; poly->verts[i][6] = t; @@ -286,11 +320,26 @@ R_TextureAnimation Returns the proper texture for a given time and base texture =============== */ -texture_t *R_TextureAnimation( texture_t *base ) +texture_t *R_TextureAnimation( texture_t *base, int surfacenum ) { int reletive; int count, speed; + // random tileng textures + if( base->anim_total < 0 ) + { + reletive = surfacenum % abs( base->anim_total ); + + count = 0; + while( base->anim_min > reletive || base->anim_max <= reletive ) + { + base = base->anim_next; + if( !base ) Host_Error( "R_TextureAnimation: broken loop\n" ); + if( ++count > 100 ) Host_Error( "R_TextureAnimation: infinite loop\n" ); + } + return base; + } + if( RI.currententity->curstate.frame ) { if( base->alternate_anims ) @@ -317,18 +366,267 @@ texture_t *R_TextureAnimation( texture_t *base ) return base; } +/* +=============== +R_AddDynamicLights +=============== +*/ +void R_AddDynamicLights( msurface_t *surf ) +{ + float dist, rad, minlight; + int lnum, s, t, sd, td, smax, tmax; + float sl, tl, sacc, tacc; + vec3_t impact, origin_l; + mtexinfo_t *tex; + dlight_t *dl; + uint *bl; + + smax = (surf->extents[0] >> 4) + 1; + tmax = (surf->extents[1] >> 4) + 1; + tex = surf->texinfo; + + for( lnum = 0; lnum < MAX_DLIGHTS; lnum++ ) + { + if(!( surf->dlightbits & BIT( lnum ))) + continue; // not lit by this light + + dl = &cl_dlights[lnum]; + + if( !tr.modelviewIdentity ) + { + matrix4x4 imatrix; + + // transform light origin to local bmodel space + Matrix4x4_Invert_Simple( imatrix, RI.objectMatrix ); + Matrix4x4_VectorTransform( imatrix, dl->origin, origin_l ); + } + else VectorCopy( dl->origin, origin_l ); + + rad = dl->radius; + dist = PlaneDiff( origin_l, surf->plane ); + rad -= fabs( dist ); + + // rad is now the highest intensity on the plane + minlight = dl->minlight; + if( rad < minlight ) + continue; + + minlight = rad - minlight; + + if( surf->plane->type < 3 ) + { + VectorCopy( origin_l, impact ); + impact[surf->plane->type] -= dist; + } + else VectorMA( origin_l, -dist, surf->plane->normal, impact ); + + sl = DotProduct( impact, tex->vecs[0] ) + tex->vecs[0][3] - surf->texturemins[0]; + tl = DotProduct( impact, tex->vecs[1] ) + tex->vecs[1][3] - surf->texturemins[1]; + + bl = r_blocklights; + for( t = 0, tacc = 0; t < tmax; t++, tacc += LM_SAMPLE_SIZE ) + { + td = tl - tacc; + if( td < 0 ) td = -td; + + for( s = 0, sacc = 0; s < smax; s++, sacc += LM_SAMPLE_SIZE, bl += 3 ) + { + sd = sl - sacc; + if( sd < 0 ) sd = -sd; + + if( sd > td ) dist = sd + (td >> 1); + else dist = td + (sd >> 1); + + if( dist < minlight ) + { + bl[0] += ( rad - dist ) * dl->color.r; + bl[1] += ( rad - dist ) * dl->color.g; + bl[2] += ( rad - dist ) * dl->color.b; + } + } + } + } +} + +/* +================ +R_SetCacheState +================ +*/ +void R_SetCacheState( msurface_t *surf ) +{ + int maps; + + for( maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; maps++ ) + { + surf->cached_light[maps] = RI.lightstylevalue[surf->styles[maps]]; + } +} + +/* +============================================================================= + + LIGHTMAP ALLOCATION + +============================================================================= +*/ +static void LM_InitBlock( void ) +{ + Q_memset( gl_lms.allocated, 0, sizeof( gl_lms.allocated )); +} + +static int LM_AllocBlock( int w, int h, int *x, int *y ) +{ + int i, j; + int best, best2; + + best = BLOCK_HEIGHT; + + for( i = 0; i < BLOCK_WIDTH - w; i++ ) + { + best2 = 0; + + for( j = 0; j < w; j++ ) + { + if( gl_lms.allocated[i+j] >= best ) + break; + if( gl_lms.allocated[i+j] > best2 ) + best2 = gl_lms.allocated[i+j]; + } + + if( j == w ) + { + // this is a valid spot + *x = i; + *y = best = best2; + } + } + + if( best + h > BLOCK_HEIGHT ) + return false; + + for( i = 0; i < w; i++ ) + gl_lms.allocated[*x + i] = best + h; + + return true; +} + +static void LM_UploadBlock( qboolean dynamic ) +{ + int i; + + if( dynamic ) + { + int height = 0; + + for( i = 0; i < BLOCK_WIDTH; i++ ) + { + if( gl_lms.allocated[i] > height ) + height = gl_lms.allocated[i]; + } + + GL_MBind( tr.dlightTexture ); + + pglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, BLOCK_WIDTH, height, GL_RGBA, GL_UNSIGNED_BYTE, + gl_lms.lightmap_buffer ); + } + else + { + rgbdata_t r_lightmap; + char lmName[16]; + + i = gl_lms.current_lightmap_texture; + + // upload static lightmaps only during loading + Q_memset( &r_lightmap, 0, sizeof( r_lightmap )); + Q_snprintf( lmName, sizeof( lmName ), "*lightmap%i", i ); + + r_lightmap.width = BLOCK_WIDTH; + r_lightmap.height = BLOCK_HEIGHT; + r_lightmap.type = PF_RGBA_32; + r_lightmap.size = r_lightmap.width * r_lightmap.height * 4; + r_lightmap.flags = ( world.version == Q1BSP_VERSION ) ? 0 : IMAGE_HAS_COLOR; + r_lightmap.buffer = gl_lms.lightmap_buffer; + tr.lightmapTextures[i] = GL_LoadTextureInternal( lmName, &r_lightmap, TF_FONT|TF_LIGHTMAP, false ); + GL_SetTextureType( tr.lightmapTextures[i], TEX_LIGHTMAP ); + + if( ++gl_lms.current_lightmap_texture == MAX_LIGHTMAPS ) + Host_Error( "AllocBlock: full\n" ); + } +} + +/* +================= +R_BuildLightmap + +Combine and scale multiple lightmaps into the floating +format in r_blocklights +================= +*/ +static void R_BuildLightMap( msurface_t *surf, byte *dest, int stride ) +{ + int smax, tmax; + uint *bl, scale; + int i, map, size, s, t; + color24 *lm; + + smax = ( surf->extents[0] >> 4 ) + 1; + tmax = ( surf->extents[1] >> 4 ) + 1; + size = smax * tmax; + + lm = surf->samples; + + Q_memset( r_blocklights, 0, sizeof( uint ) * size * 3 ); + + // add all the lightmaps + for( map = 0; map < MAXLIGHTMAPS && surf->styles[map] != 255 && lm; map++ ) + { + scale = RI.lightstylevalue[surf->styles[map]]; + + for( i = 0, bl = r_blocklights; i < size; i++, bl += 3, lm++ ) + { + bl[0] += lm->r * scale; + bl[1] += lm->g * scale; + bl[2] += lm->b * scale; + } + } + + // add all the dynamic lights + if( surf->dlightframe == tr.framecount ) + R_AddDynamicLights( surf ); + + // Put into texture format + stride -= (smax << 2); + bl = r_blocklights; + + for( t = 0; t < tmax; t++, dest += stride ) + { + for( s = 0; s < smax; s++ ) + { + dest[0] = min((bl[0] >> 7), 255 ); + dest[1] = min((bl[1] >> 7), 255 ); + dest[2] = min((bl[2] >> 7), 255 ); + dest[3] = 255; + + bl += 3; + dest += 4; + } + } +} + /* ================ DrawGLPoly ================ */ -void DrawGLPoly( glpoly_t *p ) +void DrawGLPoly( glpoly_t *p, texture_t *tex ) { - float *v; float sOffset, sy; float tOffset, cy; cl_entity_t *e = RI.currententity; - int i; + qboolean random_tiles = false; + texture_t *t; + glpoly_t *base; if( p->flags & SURF_CONVEYOR ) { @@ -360,16 +658,65 @@ void DrawGLPoly( glpoly_t *p ) sOffset = tOffset = 0.0f; } - pglBegin( GL_POLYGON ); + if( p && p->next ) random_tiles = true; - v = p->verts[0]; - for( i = 0; i < p->numverts; i++, v += VERTEXSIZE ) + for( base = p; p != NULL; p = p->next ) { - pglTexCoord2f( v[3] + sOffset, v[4] + tOffset ); - pglVertex3fv( v ); - } + float *v; + int i; - pglEnd(); + if( random_tiles && tex ) + { + t = R_TextureAnimation( tex, base - p ); + GL_MBind( t->gl_texturenum ); + } + + pglBegin( GL_POLYGON ); + + for( i = 0, v = p->verts[0]; i < p->numverts; i++, v += VERTEXSIZE ) + { + pglTexCoord2f( v[3] + sOffset, v[4] + tOffset ); + pglVertex3fv( v ); + } + + pglEnd(); + } +} + +/* +================ +DrawGLPolyChain + +Render lightmaps +================ +*/ +void DrawGLPolyChain( glpoly_t *p, float soffset, float toffset ) +{ + qboolean dynamic = true; + + if( soffset == 0.0f && toffset == 0.0f ) + dynamic = false; + + for( ; p != NULL; p = p->chain ) + { + glpoly_t *p2; + float *v; + int i; + + for( p2 = p; p2 != NULL; p2 = p2->next ) + { + pglBegin( GL_POLYGON ); + + v = p2->verts[0]; + for( i = 0; i < p2->numverts; i++, v += VERTEXSIZE ) + { + if( !dynamic ) pglTexCoord2f( v[5], v[6] ); + else pglTexCoord2f( v[5] - soffset, v[6] - toffset ); + pglVertex3fv( v ); + } + pglEnd (); + } + } } /* @@ -379,9 +726,9 @@ R_BlendLightmaps */ void R_BlendLightmaps( void ) { - int i, j; - glpoly_t *p; - float *v; + msurface_t *surf, *newsurf = NULL; + mextrasurf_t *info; + int i; if( r_fullbright->integer || !cl.worldmodel->lightdata ) return; @@ -409,26 +756,96 @@ void R_BlendLightmaps( void ) pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); } + // render static lightmaps first for( i = 0; i < MAX_LIGHTMAPS; i++ ) { - p = lightmap_polys[i]; - if( !p ) continue; - - GL_Bind( GL_TEXTURE0, tr.lightmapTextures[i] ); - if( r_lmState.lightmap_modified[i] ) - LM_UploadBlock( i ); - - for( ; p; p = p->chain ) + if( gl_lms.lightmap_surfaces[i] ) { - pglBegin( GL_POLYGON ); + GL_MBind( tr.lightmapTextures[i] ); - v = p->verts[0]; - for( j = 0; j < p->numverts; j++, v += VERTEXSIZE ) + for( surf = gl_lms.lightmap_surfaces[i]; surf != NULL; surf = surf->lightmapchain ) { - pglTexCoord2f( v[5], v[6] ); - pglVertex3fv( v ); + if( surf->polys ) DrawGLPolyChain( surf->polys, 0.0f, 0.0f ); + } + } + } + + // render dynamic lightmaps + if( r_dynamic->integer ) + { + LM_InitBlock(); + + GL_MBind( tr.dlightTexture ); + + newsurf = gl_lms.dynamic_surfaces; + + for( surf = gl_lms.dynamic_surfaces; surf != NULL; surf = surf->lightmapchain ) + { + int smax, tmax; + byte *base; + + smax = ( surf->extents[0] >> 4 ) + 1; + tmax = ( surf->extents[1] >> 4 ) + 1; + info = SURF_INFO( surf, RI.currentmodel ); + + if( LM_AllocBlock( smax, tmax, &info->dlight_s, &info->dlight_t )) + { + base = gl_lms.lightmap_buffer; + base += ( info->dlight_t * BLOCK_WIDTH + info->dlight_s ) * 4; + + R_BuildLightMap( surf, base, BLOCK_WIDTH * 4 ); + } + else + { + msurface_t *drawsurf; + + // upload what we have so far + LM_UploadBlock( true ); + + // draw all surfaces that use this lightmap + for( drawsurf = newsurf; drawsurf != surf; drawsurf = drawsurf->lightmapchain ) + { + if( drawsurf->polys ) + { + info = SURF_INFO( drawsurf, RI.currentmodel ); + + DrawGLPolyChain( drawsurf->polys, + ( drawsurf->light_s - info->dlight_s ) * ( 1.0f / 128.0f ), + ( drawsurf->light_t - info->dlight_t ) * ( 1.0f / 128.0f )); + } + } + + newsurf = drawsurf; + + // clear the block + LM_InitBlock(); + + info = SURF_INFO( surf, RI.currentmodel ); + + // try uploading the block now + if( !LM_AllocBlock( smax, tmax, &info->dlight_s, &info->dlight_t ) ) + Host_Error( "AllocBlock: full\n" ); + + base = gl_lms.lightmap_buffer; + base += ( info->dlight_t * BLOCK_WIDTH + info->dlight_s ) * 4; + + R_BuildLightMap( surf, base, BLOCK_WIDTH * 4 ); + } + } + + // draw remainder of dynamic lightmaps that haven't been uploaded yet + if( newsurf ) LM_UploadBlock( true ); + + for( surf = newsurf; surf != NULL; surf = surf->lightmapchain ) + { + if( surf->polys ) + { + info = SURF_INFO( surf, RI.currentmodel ); + + DrawGLPolyChain( surf->polys, + ( surf->light_s - info->dlight_s ) * ( 1.0f / 128.0f ), + ( surf->light_t - info->dlight_t ) * ( 1.0f / 128.0f )); } - pglEnd(); } } @@ -471,7 +888,7 @@ void R_RenderFullbrights( void ) { if( p->flags & SURF_DRAWTURB ) EmitWaterPolys( p, ( p->flags & SURF_NOCULL )); - else DrawGLPoly( p ); + else DrawGLPoly( p, NULL ); // disable random tiling (chain is already used) } fullbright_polys[i] = NULL; @@ -485,166 +902,6 @@ void R_RenderFullbrights( void ) draw_fullbrights = false; } -/* -=============== -R_BuildDlights -=============== -*/ -void R_BuildDlights( msurface_t *surf ) -{ - float dist; - vec3_t impact; - int lnum, smax, tmax; - int tdmin, sdmin, distmin; - int irad, iminlight, local[2]; - vec3_t origin_l; - matrix4x4 imatrix; - gl_light_t *light; - mtexinfo_t *tex; - dlight_t *dl; - - r_numdlights = 0; - - smax = ( surf->extents[0] >> 4 ) + 1; - tmax = ( surf->extents[1] >> 4 ) + 1; - tex = surf->texinfo; - - for( lnum = 0; lnum < MAX_DLIGHTS; lnum++ ) - { - if(!( surf->dlightbits & ( 1<origin, origin_l ); - } - else VectorCopy( dl->origin, origin_l ); - - dist = PlaneDiff( origin_l, surf->plane ); - irad = ( dl->radius - fabs( dist )) * 256; - iminlight = dl->minlight * 256; - if( irad < iminlight ) continue; - - iminlight = irad - iminlight; - - VectorMA( origin_l, -dist, surf->plane->normal, impact ); - - local[0] = DotProduct( impact, tex->vecs[0] ) + tex->vecs[0][3] - surf->texturemins[0]; - local[1] = DotProduct( impact, tex->vecs[1] ) + tex->vecs[1][3] - surf->texturemins[1]; - - // check if this dlight will touch the surface - if( local[1] > 0 ) - { - tdmin = local[1] - (tmax << 4); - if( tdmin < 0 ) tdmin = 0; - } - else - { - tdmin = -local[1]; - } - - if( local[0] > 0 ) - { - sdmin = local[0] - (smax << 4); - if( sdmin < 0 ) sdmin = 0; - } - else - { - sdmin = -local[0]; - } - - distmin = (sdmin > tdmin) ? (sdmin << 8) + (tdmin << 7) : (tdmin << 8) + (sdmin << 7); - - if( distmin < iminlight ) - { - // save dlight info - light = &r_dlights[r_numdlights]; - light->minlight = iminlight; - light->local[0] = local[0]; - light->local[1] = local[1]; - light->rad = irad; - r_numdlights++; - } - } -} - -/* -================ -R_RenderDynamicLightmaps -================ -*/ -void R_RenderDynamicLightmaps( msurface_t *fa ) -{ - byte *base; - wrect_t *rect; - uint scale; - qboolean lightstyle_modified = false; - int maps, smax, tmax; - - if( !cl.worldmodel->lightdata ) return; - if( fa->flags & SURF_DRAWTILED ) - return; - - fa->polys->chain = lightmap_polys[fa->lightmaptexturenum]; - lightmap_polys[fa->lightmaptexturenum] = fa->polys; - - if( !r_dynamic->integer ) - return; - - // check for lightmap modification - for( maps = 0; maps < MAXLIGHTMAPS && fa->styles[maps] != 255; maps++ ) - { - scale = RI.lightstylevalue[fa->styles[maps]]; - - if( scale != fa->cached_light[maps] ) - { - lightstyle_modified = true; - break; - } - } - - if( fa->dlightframe == tr.framecount ) - R_BuildDlights( fa ); - else r_numdlights = 0; - - if( !r_numdlights && !fa->cached_dlight && !lightstyle_modified ) - return; - - r_lmState.lightmap_modified[fa->lightmaptexturenum] = true; - rect = &r_lmState.lightmap_rectchange[fa->lightmaptexturenum]; - - if( fa->light_t < rect->right ) - { - if( rect->bottom ) - rect->bottom += rect->right - fa->light_t; - rect->right = fa->light_t; - } - - if( fa->light_s < rect->left ) - { - if( rect->top ) - rect->top += rect->left - fa->light_s; - rect->left = fa->light_s; - } - - smax = ( fa->extents[0] >> 4 ) + 1; - tmax = ( fa->extents[1] >> 4 ) + 1; - - if(( rect->top + rect->left ) < ( fa->light_s + smax )) - rect->top = ( fa->light_s - rect->left ) + smax; - - if(( rect->bottom + rect->right ) < ( fa->light_t + tmax )) - rect->bottom = ( fa->light_t - rect->right ) + tmax; - - base = r_lmState.lightmaps + fa->lightmaptexturenum * BLOCK_WIDTH * BLOCK_HEIGHT * 4; - base += fa->light_t * BLOCK_WIDTH * 4 + fa->light_s * 4; - R_BuildLightMap( fa, base, BLOCK_WIDTH * 4 ); -} - /* ================ R_RenderBrushPoly @@ -653,7 +910,9 @@ R_RenderBrushPoly void R_RenderBrushPoly( msurface_t *fa ) { texture_t *t; - + int maps; + qboolean is_dynamic = false; + if( RI.currententity == clgame.entities ) r_stats.c_world_polys++; else r_stats.c_brush_polys++; @@ -668,8 +927,8 @@ void R_RenderBrushPoly( msurface_t *fa ) return; } - t = R_TextureAnimation( fa->texinfo->texture ); - GL_Bind( GL_TEXTURE0, t->gl_texturenum ); + t = R_TextureAnimation( fa->texinfo->texture, 0 ); + GL_MBind( t->gl_texturenum ); if( fa->flags & SURF_DRAWTURB ) { @@ -686,72 +945,55 @@ void R_RenderBrushPoly( msurface_t *fa ) draw_fullbrights = true; } - DrawGLPoly( fa->polys ); + DrawGLPoly( fa->polys, fa->texinfo->texture ); DrawSurfaceDecals( fa ); - // add the poly to the proper lightmap chain - R_RenderDynamicLightmaps( fa ); -} - -/* -=============== -R_AddDynamicLights -=============== -*/ -void R_AddDynamicLights( msurface_t *surf ) -{ - color24 color; - int local[2]; - int i, sd, td, s, t, val; - int irad, idist, iminlight; - int smax, tmax, tmp; - gl_light_t *light; - uint *bl; - - smax = (surf->extents[0] >> 4) + 1; - tmax = (surf->extents[1] >> 4) + 1; - - for( i = 0, light = r_dlights; i < r_numdlights; i++, light++ ) + // check for lightmap modification + for( maps = 0; maps < MAXLIGHTMAPS && fa->styles[maps] != 255; maps++ ) { - color = cl_dlights[i].color; - iminlight = light->minlight; - irad = light->rad; + if( RI.lightstylevalue[fa->styles[maps]] != fa->cached_light[maps] ) + goto dynamic; + } - local[1] = light->local[1]; - bl = r_blockLights; + // dynamic this frame or dynamic previously + if(( fa->dlightframe == tr.framecount )) + { +dynamic: + // NOTE: at this point we have only valid textures + if( r_dynamic->integer ) is_dynamic = true; + } - for( t = 0; t < tmax; t++ ) + if( is_dynamic ) + { + if(( fa->styles[maps] >= 32 || fa->styles[maps] == 0 ) && ( fa->dlightframe != tr.framecount )) { - td = (local[1] < 0) ? -local[1] : local[1]; - local[1] -= LM_SAMPLE_SIZE; - local[0] = light->local[0]; + byte temp[34*34*4]; + int smax, tmax; - for( s = 0; s < smax; s++ ) - { - sd = (local[0] < 0) ? -local[0] : local[0]; - local[0] -= LM_SAMPLE_SIZE; - idist = (sd > td) ? (sd << 8) + (td << 7) : (td << 8) + (sd << 7); + smax = ( fa->extents[0] >> 4 ) + 1; + tmax = ( fa->extents[1] >> 4 ) + 1; - if( idist < iminlight ) - { - // g-cont. probably GoldSrc not used 'dark' mode - if( 0 )//cl_dlights[i].dark ) - tmp = (idist - irad) >> 7; - else tmp = (irad - idist) >> 7; + R_BuildLightMap( fa, temp, smax * 4 ); + R_SetCacheState( fa ); + + GL_MBind( tr.lightmapTextures[fa->lightmaptexturenum] ); - // catch negative lights (for dark mode) - val = bl[0] + tmp * color.r; - bl[0] = max( 0, val ); + pglTexSubImage2D( GL_TEXTURE_2D, 0, fa->light_s, fa->light_t, smax, tmax, + GL_RGBA, GL_UNSIGNED_BYTE, temp ); - val = bl[1] + tmp * color.g; - bl[1] = max( 0, val ); - - val = bl[2] + tmp * color.b; - bl[2] = max( 0, val ); - } - bl += 3; - } + fa->lightmapchain = gl_lms.lightmap_surfaces[fa->lightmaptexturenum]; + gl_lms.lightmap_surfaces[fa->lightmaptexturenum] = fa; } + else + { + fa->lightmapchain = gl_lms.dynamic_surfaces; + gl_lms.dynamic_surfaces = fa; + } + } + else + { + fa->lightmapchain = gl_lms.lightmap_surfaces[fa->lightmaptexturenum]; + gl_lms.lightmap_surfaces[fa->lightmaptexturenum] = fa; } } @@ -774,6 +1016,13 @@ void R_DrawTextureChains( void ) RI.currententity = clgame.entities; RI.currentmodel = RI.currententity->model; + // world has mirrors! + if( RP_NORMALPASS() && tr.mirror_entities[0].chain != NULL ) + { + tr.mirror_entities[0].ent = clgame.entities; + tr.num_mirror_entities++; + } + // clip skybox surfaces for( s = skychain; s != NULL; s = s->texturechain ) R_AddSkyBoxSurface( s ); @@ -994,7 +1243,8 @@ void R_DrawBrushModel( cl_entity_t *e ) if( R_CullBox( mins, maxs, RI.clipFlags )) return; - Q_memset( lightmap_polys, 0, sizeof( lightmap_polys )); + Q_memset( gl_lms.lightmap_surfaces, 0, sizeof( gl_lms.lightmap_surfaces )); + gl_lms.dynamic_surfaces = NULL; if( rotated ) R_RotateForEntity( e ); else R_TranslateForEntity( e ); @@ -1063,7 +1313,12 @@ void R_DrawBrushModel( cl_entity_t *e ) if( R_CullSurface( psurf, 0 )) continue; - if( need_sort ) + if( RP_NORMALPASS() && psurf->flags & SURF_MIRROR ) + { + psurf->texturechain = tr.mirror_entities[tr.num_mirror_entities].chain; + tr.mirror_entities[tr.num_mirror_entities].chain = psurf; + } + else if( need_sort ) { world.draw_surfaces[num_sorted] = psurf; num_sorted++; @@ -1076,6 +1331,13 @@ void R_DrawBrushModel( cl_entity_t *e ) } } + // store new mirror entity + if( RP_NORMALPASS() && tr.mirror_entities[tr.num_mirror_entities].chain != NULL ) + { + tr.mirror_entities[tr.num_mirror_entities].ent = RI.currententity; + tr.num_mirror_entities++; + } + if( need_sort ) qsort( world.draw_surfaces, num_sorted, sizeof( msurface_t* ), R_SurfaceCompare ); @@ -1127,8 +1389,16 @@ void R_DrawStaticModel( cl_entity_t *e ) if( R_CullSurface( psurf, 0 )) continue; - psurf->texturechain = psurf->texinfo->texture->texturechain; - psurf->texinfo->texture->texturechain = psurf; + if( RP_NORMALPASS() && psurf->flags & SURF_MIRROR ) + { + psurf->texturechain = tr.mirror_entities[0].chain; + tr.mirror_entities[0].chain = psurf; + } + else + { + psurf->texturechain = psurf->texinfo->texture->texturechain; + psurf->texinfo->texture->texturechain = psurf; + } } } @@ -1167,6 +1437,124 @@ void R_DrawStaticBrushes( void ) } } +/* +============================================================= + + MIRROR RENDERING + +============================================================= +*/ +void R_PlaneForMirror( msurface_t *surf, mplane_t *out ) +{ + cl_entity_t *ent; + + ASSERT( out != NULL ); + + ent = RI.currententity; + + // setup mirror plane + *out = *surf->plane; + + if( surf->flags & SURF_PLANEBACK ) + { + VectorNegate( out->normal, out->normal ); + } + + if( !VectorIsNull( ent->angles )) + R_RotateForEntity( ent ); + else R_TranslateForEntity( ent ); + + // tranform mirror plane by entity matrix + if( !tr.modelviewIdentity ) + { + mplane_t tmp; + + tmp = *out; + + Matrix4x4_TransformPositivePlane( RI.objectMatrix, tmp.normal, tmp.dist, out->normal, &out->dist ); + } +} + +void R_DrawMirrors( void ) +{ + ref_instance_t oldRI; + mplane_t plane; + msurface_t *surf, *mirrorchain; + vec3_t forward, right, up; + vec3_t origin, angles; + int i; + float d; + + if( !tr.num_mirror_entities ) return; // mo mirrors for this frame + + oldRI = RI; // make refinst backup + + for( i = 0; i < tr.num_mirror_entities; i++ ) + { + mirrorchain = tr.mirror_entities[i].chain; + + for( surf = mirrorchain; surf != NULL; surf = surf->texturechain ) + { + RI.currententity = tr.mirror_entities[i].ent; + RI.currentmodel = RI.currententity->model; + + ASSERT( RI.currententity != NULL ); + ASSERT( RI.currentmodel != NULL ); + + R_PlaneForMirror( surf, &plane ); + + d = -2.0f * ( DotProduct( RI.vieworg, plane.normal ) - plane.dist ); + VectorMA( RI.vieworg, d, plane.normal, origin ); + + d = -2.0f * DotProduct( RI.vforward, plane.normal ); + VectorMA( RI.vforward, d, plane.normal, forward ); + VectorNormalize( forward ); + + d = -2.0f * DotProduct( RI.vright, plane.normal ); + VectorMA( RI.vright, d, plane.normal, right ); + VectorNormalize( right ); + + d = -2.0f * DotProduct( RI.vup, plane.normal ); + VectorMA( RI.vup, d, plane.normal, up ); + VectorNormalize( up ); + + VectorsAngles( forward, right, up, angles ); + angles[ROLL] = -angles[ROLL]; + + RI.params = RP_MIRRORVIEW|RP_FLIPFRONTFACE|RP_CLIPPLANE; + if( r_viewleaf ) RI.params |= RP_OLDVIEWLEAF; + + RI.clipPlane = plane; + RI.clipFlags |= ( 1<<5 ); + + RI.frustum[5] = plane; + RI.frustum[5].signbits = SignbitsForPlane( RI.frustum[5].normal ); + RI.frustum[5].type = PLANE_NONAXIAL; + + RI.refdef.viewangles[0] = anglemod( angles[0] ); + RI.refdef.viewangles[1] = anglemod( angles[1] ); + RI.refdef.viewangles[2] = anglemod( angles[2] ); + VectorCopy( origin, RI.refdef.vieworg ); + VectorCopy( origin, RI.pvsorigin ); + VectorCopy( origin, RI.cullorigin ); + + R_RenderScene( &RI.refdef ); + + if( !( RI.params & RP_OLDVIEWLEAF )) + r_oldviewleaf = r_viewleaf = NULL; // force markleafs next frame + + RI = oldRI; // restore ref instance + + // FIXME: draw mirror surface here + } + + tr.mirror_entities[i].chain = NULL; // done + tr.mirror_entities[i].ent = NULL; + } + + tr.num_mirror_entities = 0; +} + /* ============================================================= @@ -1253,13 +1641,15 @@ void R_RecursiveWorldNode( mnode_t *node, uint clipflags ) surf->texturechain = skychain; skychain = surf; } + else if( RP_NORMALPASS() && surf->flags & SURF_MIRROR ) + { + surf->texturechain = tr.mirror_entities[0].chain; + tr.mirror_entities[0].chain = surf; + } else { - if( surf->texinfo && surf->texinfo->texture ) - { - surf->texturechain = surf->texinfo->texture->texturechain; - surf->texinfo->texture->texturechain = surf; - } + surf->texturechain = surf->texinfo->texture->texturechain; + surf->texinfo->texture->texturechain = surf; } } @@ -1267,6 +1657,53 @@ void R_RecursiveWorldNode( mnode_t *node, uint clipflags ) R_RecursiveWorldNode( node->children[!side], clipflags ); } +/* +============= +R_DrawTriangleOutlines +============= +*/ +void R_DrawTriangleOutlines( void ) +{ + int i, j; + glpoly_t *p, *p2; + + if( !gl_wireframe->integer ) + return; + + pglDisable( GL_TEXTURE_2D ); + pglDisable( GL_DEPTH_TEST ); + pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); + pglPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); + + for( i = 0; i < MAX_LIGHTMAPS; i++ ) + { + msurface_t *surf; + float *v; + + for( surf = gl_lms.lightmap_surfaces[i]; surf != NULL; surf = surf->lightmapchain ) + { + p = surf->polys; + +// for( ; p != NULL; p = p->chain ) + { + p2 = p; + + for( p2 = p; p2; p2 = p2->next ) + { + pglBegin( GL_POLYGON ); + for( j = 0, v = p2->verts[0]; j < p2->numverts; j++, v += VERTEXSIZE ) + pglVertex3fv( v ); + pglEnd (); + } + } + } + } + + pglPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + pglEnable( GL_DEPTH_TEST ); + pglEnable( GL_TEXTURE_2D ); +} + /* ============= R_DrawWorld @@ -1281,10 +1718,11 @@ void R_DrawWorld( void ) RI.currentmodel = RI.currententity->model; VectorCopy( RI.cullorigin, modelorg ); - Q_memset( lightmap_polys, 0, sizeof( lightmap_polys )); + Q_memset( gl_lms.lightmap_surfaces, 0, sizeof( gl_lms.lightmap_surfaces )); Q_memset( fullbright_polys, 0, sizeof( fullbright_polys )); RI.currentWaveHeight = RI.waveHeight; GL_SetRenderMode( kRenderNormal ); + gl_lms.dynamic_surfaces = NULL; R_ClearSkyBox (); @@ -1302,6 +1740,8 @@ void R_DrawWorld( void ) if( skychain ) R_DrawSkyBox(); skychain = NULL; + + R_DrawTriangleOutlines (); } /* @@ -1371,138 +1811,6 @@ void R_MarkLeaves( void ) } } -/* -============================================================================= - - LIGHTMAP ALLOCATION - -============================================================================= -*/ -static void LM_InitBlock( void ) -{ - Q_memset( r_lmState.allocated, 0, sizeof( r_lmState.allocated )); -} - -static int LM_AllocBlock( int w, int h, int *x, int *y ) -{ - int i, j, best, best2, texnum; - - for( texnum = 0; texnum < MAX_LIGHTMAPS; texnum++ ) - { - best = BLOCK_HEIGHT; - - for( i = 0; i < BLOCK_WIDTH - w; i++ ) - { - best2 = 0; - - for( j = 0; j < w; j++ ) - { - if( r_lmState.allocated[texnum][i+j] >= best ) - break; - if( r_lmState.allocated[texnum][i+j] > best2 ) - best2 = r_lmState.allocated[texnum][i+j]; - } - if( j == w ) - { - // this is a valid spot - *x = i; - *y = best = best2; - } - } - - if( best + h > BLOCK_HEIGHT ) - continue; - - for( i = 0; i < w; i++ ) - r_lmState.allocated[texnum][*x+i] = best + h; - - return texnum; - } - - Host_Error( "AllocBlock: full\n" ); - - return 0; -} - -/* -=============== -R_BuildLightMap - -Combine and scale multiple lightmaps into the 8.8 format in blocklights -=============== -*/ -static void R_BuildLightMap( msurface_t *surf, byte *dest, int stride ) -{ - int smax, tmax, t, s, i; - int size, map, blocksize; - uint scale; - uint *bl; - color24 *lm; - - surf->cached_dlight = (r_numdlights > 0) ? true : false; - - smax = (surf->extents[0] >> 4) + 1; - tmax = (surf->extents[1] >> 4) + 1; - size = smax * tmax; - blocksize = size * 3; - lm = surf->samples; - - Q_memset( r_blockLights, 0, sizeof( uint ) * blocksize ); - - // add all the lightmaps - for( map = 0; map < MAXLIGHTMAPS && surf->styles[map] != 255 && lm; map++ ) - { - scale = RI.lightstylevalue[surf->styles[map]]; - surf->cached_light[map] = scale; - - for( i = 0, bl = r_blockLights; i < size; i++, bl += 3, lm++ ) - { - bl[0] += lm->r * scale; - bl[1] += lm->g * scale; - bl[2] += lm->b * scale; - } - } - - // add all the dynamic lights - if( r_numdlights ) - R_AddDynamicLights( surf ); - - // put into texture format - stride -= (smax << 2); - bl = r_blockLights; - - for( t = 0; t < tmax; t++, dest += stride ) - { - for( s = 0; s < smax; s++ ) - { - dest[0] = min((bl[0] >> 7), 255 ); - dest[1] = min((bl[1] >> 7), 255 ); - dest[2] = min((bl[2] >> 7), 255 ); - dest[3] = 255; - - bl += 3; - dest += 4; - } - } -} - -static void LM_UploadBlock( int lightmapnum ) -{ - wrect_t *rect; - - r_lmState.lightmap_modified[lightmapnum] = false; - rect = &r_lmState.lightmap_rectchange[lightmapnum]; - - pglTexSubImage2D( GL_TEXTURE_2D, 0, 0, rect->right, BLOCK_WIDTH, rect->bottom, GL_RGBA, GL_UNSIGNED_BYTE, - &r_lmState.lightmaps[(lightmapnum * BLOCK_HEIGHT + rect->right) * BLOCK_WIDTH * 4] ); - - // reset rectangle - rect->left = BLOCK_WIDTH; - rect->right = BLOCK_HEIGHT; - rect->top = 0; - rect->bottom = 0; -} - /* ======================== GL_CreateSurfaceLightmap @@ -1512,7 +1820,6 @@ void GL_CreateSurfaceLightmap( msurface_t *surf ) { int smax, tmax; byte *base; - texture_t *tex; if( !cl.worldmodel->lightdata ) return; if( surf->flags & SURF_DRAWTILED ) @@ -1520,20 +1827,22 @@ void GL_CreateSurfaceLightmap( msurface_t *surf ) smax = ( surf->extents[0] >> 4 ) + 1; tmax = ( surf->extents[1] >> 4 ) + 1; - tex = surf->texinfo->texture; - if( smax > BLOCK_WIDTH ) - Host_Error( "GL_CreateLightmap: lightmap width %d > %d, %s\n", smax, BLOCK_WIDTH, tex->name ); - if( tmax > BLOCK_HEIGHT ) - Host_Error( "GL_CreateLightmap: lightmap height %d > %d, %s\n", tmax, BLOCK_HEIGHT, tex->name ); - if( smax * tmax > BLOCK_WIDTH * BLOCK_HEIGHT ) - Host_Error( "GL_CreateLightmap: lightmap size too big\n" ); + if( !LM_AllocBlock( smax, tmax, &surf->light_s, &surf->light_t )) + { + LM_UploadBlock( false ); + LM_InitBlock(); - surf->lightmaptexturenum = LM_AllocBlock( smax, tmax, &surf->light_s, &surf->light_t ); - base = r_lmState.lightmaps + surf->lightmaptexturenum * BLOCK_WIDTH * BLOCK_HEIGHT * 4; - base += (surf->light_t * BLOCK_WIDTH + surf->light_s) * 4; - r_numdlights = 0; + if( !LM_AllocBlock( smax, tmax, &surf->light_s, &surf->light_t )) + Host_Error( "AllocBlock: full\n" ); + } + surf->lightmaptexturenum = gl_lms.current_lightmap_texture; + + base = gl_lms.lightmap_buffer; + base += ( surf->light_t * BLOCK_WIDTH + surf->light_s ) * 4; + + R_SetCacheState( surf ); R_BuildLightMap( surf, base, BLOCK_WIDTH * 4 ); } @@ -1548,8 +1857,6 @@ with all the surfaces from all brush models void GL_BuildLightmaps( void ) { int i, j; - rgbdata_t r_lightmap; - char lmName[16]; model_t *m; // release old lightmaps @@ -1560,11 +1867,14 @@ void GL_BuildLightmaps( void ) } Q_memset( tr.lightmapTextures, 0, sizeof( tr.lightmapTextures )); + Q_memset( tr.mirror_entities, 0, sizeof( tr.mirror_entities )); Q_memset( visbytes, 0x00, sizeof( visbytes )); - Q_memset( &r_lmState, 0, sizeof( r_lmState )); - + skychain = NULL; + tr.framecount = 1; // no dlight cache + gl_lms.current_lightmap_texture = 0; + // setup all the lightstyles R_AnimateLight(); @@ -1599,26 +1909,5 @@ void GL_BuildLightmaps( void ) loadmodel = NULL; - // upload all lightmaps that were filled - for( i = 0; i < MAX_LIGHTMAPS; i++ ) - { - if( !r_lmState.allocated[i][0] ) break; // no more used - r_lmState.lightmap_modified[i] = false; - r_lmState.lightmap_rectchange[i].left = BLOCK_WIDTH; - r_lmState.lightmap_rectchange[i].right = BLOCK_HEIGHT; - r_lmState.lightmap_rectchange[i].top = 0; - r_lmState.lightmap_rectchange[i].bottom = 0; - - Q_memset( &r_lightmap, 0, sizeof( r_lightmap )); - - Q_snprintf( lmName, sizeof( lmName ), "*lightmap%i", i ); - r_lightmap.width = BLOCK_WIDTH; - r_lightmap.height = BLOCK_HEIGHT; - r_lightmap.type = PF_RGBA_32; - r_lightmap.size = r_lightmap.width * r_lightmap.height * 4; - r_lightmap.flags = ( world.version == Q1BSP_VERSION ) ? 0 : IMAGE_HAS_COLOR; - r_lightmap.buffer = (byte *)&r_lmState.lightmaps[r_lightmap.size*i]; - tr.lightmapTextures[i] = GL_LoadTextureInternal( lmName, &r_lightmap, TF_FONT|TF_LIGHTMAP, false ); - GL_SetTextureType( tr.lightmapTextures[i], TEX_LIGHTMAP ); - } + LM_UploadBlock( false ); } \ No newline at end of file diff --git a/engine/client/gl_sprite.c b/engine/client/gl_sprite.c index 053a438f..98725650 100644 --- a/engine/client/gl_sprite.c +++ b/engine/client/gl_sprite.c @@ -26,6 +26,7 @@ GNU General Public License for more details. #define MAPSPRITE_SIZE 128 convar_t *r_sprite_lerping; +convar_t *r_sprite_lighting; char group_suffix[8]; static vec3_t sprite_mins, sprite_maxs; static float sprite_radius; @@ -39,6 +40,7 @@ R_SpriteInit void R_SpriteInit( void ) { r_sprite_lerping = Cvar_Get( "r_sprite_lerping", "1", CVAR_ARCHIVE, "enables sprite animation lerping" ); + r_sprite_lighting = Cvar_Get( "r_sprite_lighting", "1", CVAR_ARCHIVE, "enables sprite lighting (blood etc)" ); } /* @@ -459,7 +461,7 @@ mspriteframe_t *R_GetSpriteFrame( const model_t *pModel, int frame, float yaw ) } else if( psprite->frames[frame].type == FRAME_ANGLED ) { - int angleframe = (int)(( RI.refdef.viewangles[1] - yaw ) / 360 * 8 + 0.5 - 4) & 7; + int angleframe = (int)(Q_rint(( RI.refdef.viewangles[1] - yaw + 45.0f ) / 360 * 8) - 4) & 7; // e.g. doom-style sprite monsters pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr; @@ -590,7 +592,7 @@ float R_GetSpriteFrameInterpolant( cl_entity_t *ent, mspriteframe_t **oldframe, { // e.g. doom-style sprite monsters float yaw = ent->angles[YAW]; - int angleframe = (int)(( RI.refdef.viewangles[1] - yaw ) / 360 * 8 + 0.5 - 4) & 7; + int angleframe = (int)(Q_rint(( RI.refdef.viewangles[1] - yaw + 45.0f ) / 360 * 8) - 4) & 7; if( m_fDoInterp ) { @@ -732,6 +734,8 @@ static float R_SpriteGlowBlend( vec3_t origin, int rendermode, int renderfx, int if( renderfx == kRenderFxNoDissipation ) return (float)alpha * (1.0f / 255.0f); + *pscale = 0.0f; // variable sized glow + // UNDONE: Tweak these magic numbers (19000 - falloff & 200 - sprite size) brightness = 19000.0 / ( dist * dist ); brightness = bound( 0.01f, brightness, 1.0f ); @@ -811,7 +815,7 @@ static void R_DrawSpriteQuad( mspriteframe_t *frame, vec3_t org, vec3_t v_right, static _inline qboolean R_SpriteHasLightmap( cl_entity_t *e, int texFormat ) { - if( !r_lighting_extended->integer ) + if( !r_sprite_lighting->integer ) return false; if( texFormat != SPR_ALPHTEST ) @@ -930,7 +934,7 @@ void R_DrawSpriteModel( cl_entity_t *e ) qboolean invLight; invLight = (e->curstate.effects & EF_INVLIGHT) ? true : false; - R_LightForPoint( origin, &lightColor, invLight, sprite_radius ); + R_LightForPoint( origin, &lightColor, invLight, true, sprite_radius ); color2[0] = (float)lightColor.r * ( 1.0f / 255.0f ); color2[1] = (float)lightColor.g * ( 1.0f / 255.0f ); color2[2] = (float)lightColor.b * ( 1.0f / 255.0f ); @@ -1013,7 +1017,7 @@ void R_DrawSpriteModel( cl_entity_t *e ) if( ilerp != 0 ) { pglColor4f( color[0], color[1], color[2], flAlpha * ilerp ); - GL_Bind( GL_TEXTURE0, frame->gl_texturenum ); + GL_Bind( GL_TEXTURE0, oldframe->gl_texturenum ); R_DrawSpriteQuad( oldframe, origin, v_right, v_up, scale ); } diff --git a/engine/client/gl_studio.c b/engine/client/gl_studio.c index 2392d59e..6450a0fa 100644 --- a/engine/client/gl_studio.c +++ b/engine/client/gl_studio.c @@ -57,10 +57,11 @@ typedef struct studiolight_s convar_t *r_studio_lerping; convar_t *r_studio_lambert; +convar_t *r_studio_lighting; convar_t *r_drawviewmodel; convar_t *r_customdraw_playermodel; convar_t *cl_himodels; -cvar_t r_shadows = { "r_shadows", "0", 0, 0 }; +cvar_t r_shadows = { "r_shadows", "0", 0, 0 }; // dead cvar. especially disabled cvar_t r_shadowalpha = { "r_shadowalpha", "0.5", 0, 0 }; static r_studio_interface_t *pStudioDraw; static float aliasXscale, aliasYscale; // software renderer scale @@ -110,6 +111,7 @@ void R_StudioInit( void ) r_studio_lerping = Cvar_Get( "r_studio_lerping", "1", CVAR_ARCHIVE, "enables studio animation lerping" ); r_drawviewmodel = Cvar_Get( "r_drawviewmodel", "1", 0, "draw firstperson weapon model" ); cl_himodels = Cvar_Get( "cl_himodels", "1", CVAR_ARCHIVE, "draw high-resolution player models in multiplayer" ); + r_studio_lighting = Cvar_Get( "r_studio_lighting", "1", CVAR_ARCHIVE, "studio lighting models ( 0 - normal, 1 - extended, 2 - experimental )" ); // NOTE: some mods with custom studiomodel renderer may cause error when menu trying draw player model out of the loaded game r_customdraw_playermodel = Cvar_Get( "r_customdraw_playermodel", "0", CVAR_ARCHIVE, "allow to drawing playermodel in menu with client renderer" ); @@ -1230,7 +1232,7 @@ void R_StudioSetupChrome( float *pchrome, int bone, vec3_t normal ) vec3_t chromerightvec; // g_chrome s vector in world reference frame vec3_t tmp; // vector pointing at bone in world reference frame - VectorScale( RI.currententity->origin, -1.0f, tmp ); + VectorScale( cl.refdef.vieworg, -1.0f, tmp ); tmp[0] += g_bonestransform[bone][0][3]; tmp[1] += g_bonestransform[bone][1][3]; tmp[2] += g_bonestransform[bone][2][3]; @@ -1363,7 +1365,7 @@ void R_StudioDynamicLight( cl_entity_t *ent, alight_t *lightinfo ) plight = &g_studiolight; plight->numdlights = 0; // clear previous dlights - if( r_lighting_extended->integer == 2 ) + if( r_studio_lighting->integer == 2 ) Matrix3x4_OriginFromMatrix( g_lighttransform[0], origin ); else Matrix3x4_OriginFromMatrix( g_rotationmatrix, origin ); @@ -1373,7 +1375,7 @@ void R_StudioDynamicLight( cl_entity_t *ent, alight_t *lightinfo ) // setup ambient lighting invLight = (ent->curstate.effects & EF_INVLIGHT) ? true : false; - R_LightForPoint( origin, &ambient, invLight, 0.0f ); // ignore dlights + R_LightForPoint( origin, &ambient, invLight, true, 0.0f ); // ignore dlights plight->lightcolor[0] = ambient.r * (1.0f / 255.0f); plight->lightcolor[1] = ambient.g * (1.0f / 255.0f); @@ -1452,7 +1454,7 @@ void R_StudioEntityLight( alight_t *lightinfo ) plight = &g_studiolight; plight->numelights = 0; // clear previous elights - if( r_lighting_extended->integer == 2 ) + if( r_studio_lighting->integer == 2 ) Matrix3x4_OriginFromMatrix( g_lighttransform[0], origin ); else Matrix3x4_OriginFromMatrix( g_rotationmatrix, origin ); @@ -2257,12 +2259,12 @@ static int pfnIsHardware( void ) return true; } -static void StudioDrawShadow( studiohdr_t *pstudiohdr, matrix3x4 transform[MAXSTUDIOBONES] ) +static void StudioDrawShadow( void ) { // in GoldSrc shadow call is dsiabled with 'return' at start of the function // some mods used a hack with calling DrawShadow ahead of 'return' // this code is for HL compatibility. - MsgDev( D_INFO, "GL_StudioDrawShadow()\n" ); // just a debug +// MsgDev( D_INFO, "GL_StudioDrawShadow()\n" ); // just a debug } /* @@ -2273,11 +2275,11 @@ GL_StudioDrawShadow */ void _cdecl GL_StudioDrawShadow( void ) { - int rendermode; // ecx@3 - float shadow_alpha; // ST18_4@4 - float shadow_alpha2; // ST14_4@4 - GLenum depthmode; // [sp+14h] [bp-8h]@6 - GLenum depthmode2; // [sp+14h] [bp-8h]@10 + int rendermode; + float shadow_alpha; + float shadow_alpha2; + GLenum depthmode; + GLenum depthmode2; pglDepthMask( GL_TRUE ); @@ -2303,7 +2305,7 @@ void _cdecl GL_StudioDrawShadow( void ) depthmode = GL_GREATER; pglDepthFunc( depthmode ); - MsgDev( D_INFO, "GL_StudioDrawShadow()\n" ); // just a debug + StudioDrawShadow(); // if( flt_100DB994 == 0.0 || flt_107BA8A8 < 0.5 ) depthmode2 = GL_LEQUAL; diff --git a/engine/client/gl_vidnt.c b/engine/client/gl_vidnt.c index cf2ffd4e..6b21515d 100644 --- a/engine/client/gl_vidnt.c +++ b/engine/client/gl_vidnt.c @@ -35,6 +35,7 @@ convar_t *gl_texturebits; convar_t *gl_ignorehwgamma; convar_t *gl_texture_anisotropy; convar_t *gl_compress_textures; +convar_t *gl_luminance_textures; convar_t *gl_texture_lodbias; convar_t *gl_showtextures; convar_t *gl_swapInterval; @@ -60,6 +61,7 @@ convar_t *r_norefresh; convar_t *r_lighting_extended; convar_t *r_lighting_modulate; convar_t *r_lighting_ambient; +convar_t *r_detailtextures; convar_t *r_faceplanecull; convar_t *r_drawentities; convar_t *r_adjust_fov; @@ -121,10 +123,11 @@ vidmode_t vidmode[] = { "Mode 13: 16x9", 1024, 600, true }, { "Mode 14: 16x9", 1280, 720, true }, { "Mode 15: 16x9", 1360, 768, true }, -{ "Mode 16: 16x9", 1440, 900, true }, -{ "Mode 17: 16x9", 1680, 1050, true }, -{ "Mode 18: 16x9", 1920, 1200, true }, -{ "Mode 19: 16x9", 2560, 1600, true }, +{ "Mode 16: 16x9", 1366, 768, true }, +{ "Mode 17: 16x9", 1440, 900, true }, +{ "Mode 18: 16x9", 1680, 1050, true }, +{ "Mode 19: 16x9", 1920, 1200, true }, +{ "Mode 20: 16x9", 2560, 1600, true }, { NULL, 0, 0, 0 }, }; @@ -432,13 +435,18 @@ static dllfunc_t wgl_funcs[] = { "wglSwapBuffers" , (void **)&pwglSwapBuffers }, { "wglCreateContext" , (void **)&pwglCreateContext }, { "wglDeleteContext" , (void **)&pwglDeleteContext }, -{ "wglGetProcAddress" , (void **)&pwglGetProcAddress }, { "wglMakeCurrent" , (void **)&pwglMakeCurrent }, { "wglGetCurrentContext" , (void **)&pwglGetCurrentContext }, { "wglGetCurrentDC" , (void **)&pwglGetCurrentDC }, { NULL, NULL } }; +static dllfunc_t wglproc_funcs[] = +{ +{ "wglGetProcAddress" , (void **)&pwglGetProcAddress }, +{ NULL, NULL } +}; + static dllfunc_t wglswapintervalfuncs[] = { { "wglSwapIntervalEXT" , (void **)&pwglSwapIntervalEXT }, @@ -524,7 +532,7 @@ void GL_CheckExtension( const char *name, const dllfunc_t *funcs, const char *cv if(( name[2] == '_' || name[3] == '_' ) && !Q_strstr( glConfig.extensions_string, name )) { GL_SetExtension( r_ext, false ); // update render info - MsgDev( D_NOTE, "- failed\n" ); + MsgDev( D_NOTE, "- ^1failed\n" ); return; } @@ -541,7 +549,7 @@ void GL_CheckExtension( const char *name, const dllfunc_t *funcs, const char *cv } if( GL_Support( r_ext )) - MsgDev( D_NOTE, "- enabled\n" ); + MsgDev( D_NOTE, "- ^2enabled\n" ); } /* @@ -1405,13 +1413,14 @@ void GL_InitCommands( void ) r_speeds = Cvar_Get( "r_speeds", "0", CVAR_ARCHIVE, "shows renderer speeds" ); r_fullbright = Cvar_Get( "r_fullbright", "0", CVAR_CHEAT, "disable lightmaps, get fullbright for entities" ); r_norefresh = Cvar_Get( "r_norefresh", "0", 0, "disable 3D rendering (use with caution)" ); - r_lighting_extended = Cvar_Get( "r_lighting_extended", "1", CVAR_ARCHIVE, "allow to get lighting from bmodels" ); + r_lighting_extended = Cvar_Get( "r_lighting_extended", "1", CVAR_ARCHIVE, "allow to get lighting from world and bmodels" ); r_lighting_modulate = Cvar_Get( "r_lighting_modulate", "0.6", CVAR_ARCHIVE, "lightstyles modulate scale" ); r_lighting_ambient = Cvar_Get( "r_lighting_ambient", "0.3", 0, "map ambient lighting scale" ); r_adjust_fov = Cvar_Get( "r_adjust_fov", "1", CVAR_ARCHIVE, "making FOV adjustment for wide-screens" ); r_novis = Cvar_Get( "r_novis", "0", 0, "ignore vis information (perfomance test)" ); r_nocull = Cvar_Get( "r_nocull", "0", 0, "ignore frustrum culling (perfomance test)" ); r_faceplanecull = Cvar_Get( "r_faceplanecull", "1", 0, "ignore face plane culling (perfomance test)" ); + r_detailtextures = Cvar_Get( "r_detailtextures", "1", CVAR_ARCHIVE, "enable detail textures support, use \"2\" for auto-generate mapname_detail.txt" ); r_lockpvs = Cvar_Get( "r_lockpvs", "0", CVAR_CHEAT, "lockpvs area at current point (pvs test)" ); r_lockcull = Cvar_Get( "r_lockcull", "0", CVAR_CHEAT, "lock frustrum area at current point (cull test)" ); r_wateralpha = Cvar_Get( "r_wateralpha", "1", CVAR_ARCHIVE, "world water transparency factor" ); @@ -1440,7 +1449,8 @@ void GL_InitCommands( void ) gl_extensions = Cvar_Get( "gl_extensions", "1", CVAR_GLCONFIG, "allow gl_extensions" ); gl_texture_anisotropy = Cvar_Get( "r_anisotropy", "2.0", CVAR_ARCHIVE, "textures anisotropic filter" ); gl_texture_lodbias = Cvar_Get( "gl_texture_lodbias", "0.0", CVAR_ARCHIVE, "LOD bias for mipmapped textures" ); - gl_compress_textures = Cvar_Get( "gl_compress_textures", "0", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "compress textures to safe video memory" ); + gl_compress_textures = Cvar_Get( "gl_compress_textures", "0", CVAR_GLCONFIG, "compress textures to safe video memory" ); + gl_luminance_textures = Cvar_Get( "gl_luminance_textures", "0", CVAR_GLCONFIG, "force all textures to luminance" ); gl_allow_static = Cvar_Get( "gl_allow_static", "1", CVAR_ARCHIVE, "force to drawing non-moveable brushes as part of world (save FPS)" ); gl_showtextures = Cvar_Get( "r_showtextures", "0", CVAR_CHEAT, "show all uploaded textures (type values from 1 to 9)" ); gl_finish = Cvar_Get( "gl_finish", "0", CVAR_ARCHIVE, "use glFinish instead of glFlush" ); @@ -1480,9 +1490,13 @@ void GL_InitExtensions( void ) glConfig.version_string = pglGetString( GL_VERSION ); glConfig.extensions_string = pglGetString( GL_EXTENSIONS ); MsgDev( D_INFO, "Video: %s\n", glConfig.renderer_string ); - + + // initalize until base opengl functions loaded + GL_CheckExtension( "OpenGL Internal ProcAddress", wglproc_funcs, NULL, GL_WGL_PROCADDRESS ); + GL_CheckExtension( "WGL_3DFX_gamma_control", wgl3DFXgammacontrolfuncs, NULL, GL_WGL_3DFX_GAMMA_CONTROL ); GL_CheckExtension( "WGL_EXT_swap_control", wglswapintervalfuncs, NULL, GL_WGL_SWAPCONTROL ); + GL_CheckExtension( "glDrawRangeElements", drawrangeelementsfuncs, "gl_drawrangeelments", GL_DRAW_RANGEELEMENTS_EXT ); if( !GL_Support( GL_DRAW_RANGEELEMENTS_EXT )) diff --git a/engine/client/gl_warp.c b/engine/client/gl_warp.c index 78d18edf..8fffb0e3 100644 --- a/engine/client/gl_warp.c +++ b/engine/client/gl_warp.c @@ -65,7 +65,7 @@ float r_turbsin[] = static qboolean CheckSkybox( const char *name ) { - const char *skybox_ext[3] = { "tga", "bmp", "jpg" }; + const char *skybox_ext[3] = { "jpg", "tga", "bmp" }; int i, j, num_checked_sides; const char *sidename; @@ -448,6 +448,9 @@ void R_InitSky( mip_t *mt, texture_t *tx ) uint transpix; int r, g, b; int i, j, p; + char texname[32]; + + Q_snprintf( texname, sizeof( texname ), "%s%s.mip", ( mt->offsets[0] > 0 ) ? "#" : "", tx->name ); if( mt->offsets[0] > 0 ) { @@ -456,12 +459,12 @@ void R_InitSky( mip_t *mt, texture_t *tx ) int size = (int)sizeof( mip_t ) + ((mt->width * mt->height * 85)>>6); if( world.version == HLBSP_VERSION ) size += sizeof( short ) + 768; - r_sky = FS_LoadImage( tx->name, (byte *)mt, size ); + r_sky = FS_LoadImage( texname, (byte *)mt, size ); } else { // okay, loading it from wad - r_sky = FS_LoadImage( tx->name, NULL, 0 ); + r_sky = FS_LoadImage( texname, NULL, 0 ); } // make sure what sky image is valid diff --git a/engine/client/s_mix.c b/engine/client/s_mix.c index cb067a2e..5a39d514 100644 --- a/engine/client/s_mix.c +++ b/engine/client/s_mix.c @@ -601,6 +601,7 @@ void MIX_MixChannelsToPaintbuffer( int endtime, int rate, int outputRate ) { case SOUND_11k: case SOUND_22k: + case SOUND_32k: case SOUND_44k: if( rate != pSource->rate ) continue; @@ -1004,6 +1005,11 @@ void MIX_UpsampleAllPaintbuffers( int end, int count ) MIX_SetCurrentPaintbuffer( IROOMBUFFER ); S_MixUpsample( count / ( SOUND_DMA_SPEED / SOUND_22k ), FILTERTYPE_LINEAR ); #endif + +#if (SOUND_DMA_SPEED >= SOUND_32k) + // mix 32khz sounds: + MIX_MixChannelsToPaintbuffer( end, SOUND_32k, SOUND_DMA_SPEED ); +#endif // mix all 44khz sounds to all active paintbuffers MIX_MixChannelsToPaintbuffer( end, SOUND_44k, SOUND_DMA_SPEED ); diff --git a/engine/client/sound.h b/engine/client/sound.h index 1ba2365a..27dc3102 100644 --- a/engine/client/sound.h +++ b/engine/client/sound.h @@ -28,6 +28,7 @@ extern byte *sndpool; #define SOUND_DMA_SPEED 44100 // hardware playback rate #define SOUND_11k 11025 // 11khz sample rate #define SOUND_22k 22050 // 22khz sample rate +#define SOUND_32k 32000 // 32khz sample rate #define SOUND_44k 44100 // 44khz sample rate // fixed point stuff for real-time resampling diff --git a/engine/common/build.c b/engine/common/build.c index 4b750850..343c0480 100644 --- a/engine/common/build.c +++ b/engine/common/build.c @@ -23,7 +23,7 @@ static char mond[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; int Q_buildnum( void ) { // do not touch this! Only author of Xash3D can increase buildnumbers! -#if 0 +#if 1 int m = 0, d = 0, y = 0; static int b = 0; diff --git a/engine/common/cmd.c b/engine/common/cmd.c index 910b7adb..506a8385 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -365,10 +365,6 @@ void Cmd_Alias_f( void ) ============================================================================= */ - -#define CMD_EXTDLL BIT( 0 ) // added by game.dll -#define CMD_CLIENTDLL BIT( 1 ) // added by client.dll - typedef struct cmd_function_s { struct cmd_function_s *next; @@ -444,7 +440,7 @@ void Cmd_TokenizeString( char *text ) while( 1 ) { // skip whitespace up to a /n - while( *text && *text <= ' ' && *text != '\n' ) + while( *text && ((byte)*text) <= ' ' && *text != '\n' ) text++; if( *text == '\n' ) @@ -775,7 +771,7 @@ Cmd_Unlink unlink all commands with flag CVAR_EXTDLL ============ */ -void Cmd_Unlink( void ) +void Cmd_Unlink( int group ) { cmd_function_t *cmd; cmd_function_t **prev; @@ -793,7 +789,7 @@ void Cmd_Unlink( void ) cmd = *prev; if( !cmd ) break; - if( !( cmd->flags & CMD_EXTDLL )) + if( group && !( cmd->flags & group )) { prev = &cmd->next; continue; diff --git a/engine/common/common.c b/engine/common/common.c index a74fb244..7103cd9c 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -64,7 +64,7 @@ char *COM_ParseFile( char *data, char *token ) // skip whitespace skipwhite: - while(( c = *data ) <= ' ' ) + while(( c = ((byte)*data)) <= ' ' ) { if( c == 0 ) return NULL; // end of file; @@ -85,7 +85,7 @@ skipwhite: data++; while( 1 ) { - c = *data++; + c = (byte)*data++; if( c == '\"' || !c ) { token[len] = 0; @@ -111,7 +111,7 @@ skipwhite: token[len] = c; data++; len++; - c = *data; + c = ((byte)*data); if( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ',' ) break; diff --git a/engine/common/common.h b/engine/common/common.h index 11b9af57..70172981 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -79,8 +79,8 @@ typedef enum #define XASH_VERSION 0.85f // engine current version // PERFORMANCE INFO -#define MIN_FPS 0.1 // host minimum fps value for maxfps. -#define MAX_FPS 1000.0 // upper limit for maxfps. +#define MIN_FPS 15.0 // host minimum fps value for maxfps. +#define MAX_FPS 500.0 // upper limit for maxfps. #define MAX_FRAMETIME 0.1 #define MIN_FRAMETIME 0.001 diff --git a/engine/common/console.c b/engine/common/console.c index a193d9c2..847c97e9 100644 --- a/engine/common/console.c +++ b/engine/common/console.c @@ -91,6 +91,9 @@ typedef struct // console input field_t input; + // chatfiled + field_t chat; + // console history field_t historyLines[CON_HISTORY]; int historyLine; // the line being displayed from history buffer will be <= nextHistoryLine @@ -107,6 +110,7 @@ typedef struct } console_t; static console_t con; +static qboolean chat_team; // say_team is active void Field_CharEvent( field_t *edit, int ch ); @@ -214,6 +218,52 @@ int Con_StringLength( const char *string ) return len; } +/* +================ +Con_MessageMode_f +================ +*/ +void Con_MessageMode_f( void ) +{ + chat_team = false; + Key_SetKeyDest( key_message ); +} + +/* +================ +Con_MessageMode2_f +================ +*/ +void Con_MessageMode2_f( void ) +{ + chat_team = true; + Key_SetKeyDest( key_message ); +} + +/* +================ +Con_ToggleChat_f +================ +*/ +void Con_ToggleChat_f( void ) +{ + Con_ClearTyping (); + + if( cls.key_dest == key_console ) + { + if( Cvar_VariableInteger( "sv_background" )) + UI_SetActiveMenu( true ); + else UI_SetActiveMenu( false ); + } + else + { + UI_SetActiveMenu( false ); + Key_SetKeyDest( key_console ); + } + + Con_ClearNotify(); +} + /* ================ Con_ToggleConsole_f @@ -395,12 +445,12 @@ static void Con_LoadConchars( void ) if( con_fontsize->integer > 2 ) Cvar_SetFloat( "con_fontsize", 2 ); // select properly fontsize - if( scr_width->integer < 640 ) Cvar_SetFloat( "con_fontsize", 0 ); + if( scr_width->integer <= 640 ) Cvar_SetFloat( "con_fontsize", 0 ); else if( scr_width->integer >= 1280 ) Cvar_SetFloat( "con_fontsize", 2 ); else Cvar_SetFloat( "con_fontsize", 1 ); // loading conchars - con.chars.hFontTexture = GL_LoadTexture( va( "fonts/font%i", con_fontsize->integer ), NULL, 0, TF_FONT ); + con.chars.hFontTexture = GL_LoadTexture( va( "fonts/font%i", con_fontsize->integer ), NULL, 0, TF_FONT|TF_NEAREST ); if( !con_fontsize->modified ) return; // font not changed @@ -592,6 +642,9 @@ void Con_Init( void ) Con_ClearField( &con.input ); con.input.widthInChars = con.linewidth; + Con_ClearField( &con.chat ); + con.chat.widthInChars = con.linewidth; + for( i = 0; i < CON_HISTORY; i++ ) { Con_ClearField( &con.historyLines[i] ); @@ -601,6 +654,9 @@ void Con_Init( void ) Cmd_AddCommand( "toggleconsole", Con_ToggleConsole_f, "opens or closes the console" ); Cmd_AddCommand( "con_color", Con_SetColor_f, "set a custom console color" ); Cmd_AddCommand( "clear", Con_Clear_f, "clear console history" ); + Cmd_AddCommand( "togglechat", Con_ToggleChat_f, "toggle console chat" ); + Cmd_AddCommand( "messagemode", Con_MessageMode_f, "enable message mode \"say\"" ); + Cmd_AddCommand( "messagemode2", Con_MessageMode2_f, "enable message mode \"say_team\"" ); MsgDev( D_NOTE, "Console initialized.\n" ); con.initialized = true; @@ -692,6 +748,13 @@ void Con_Print( const char *txt ) } } +/* +================ +Con_NPrint + +Draw a single debug line with specified height +================ +*/ void Con_NPrintf( int idx, char *fmt, ... ) { va_list args; @@ -712,6 +775,13 @@ void Con_NPrintf( int idx, char *fmt, ... ) con.draw_notify = true; } +/* +================ +Con_NXPrint + +Draw a single debug line with specified height, color and time to live +================ +*/ void Con_NXPrintf( con_nprint_t *info, char *fmt, ... ) { va_list args; @@ -734,6 +804,13 @@ void Con_NXPrintf( con_nprint_t *info, char *fmt, ... ) con.draw_notify = true; } +/* +================ +UI_NPrint + +Draw a single debug line with specified height (menu version) +================ +*/ void UI_NPrintf( int idx, char *fmt, ... ) { va_list args; @@ -754,6 +831,13 @@ void UI_NPrintf( int idx, char *fmt, ... ) con.draw_notify = true; } +/* +================ +UI_NXPrint + +Draw a single debug line with specified height, color and time to live (menu version) +================ +*/ void UI_NXPrintf( con_nprint_t *info, char *fmt, ... ) { va_list args; @@ -986,7 +1070,7 @@ Key events are used for non-printable characters, others are gotten from char ev */ void Field_KeyDownEvent( field_t *edit, int key ) { - int len; + int len; // shift-insert is paste if((( key == K_INS ) || ( key == K_KP_INS )) && Key_IsDown( K_SHIFT )) @@ -997,48 +1081,52 @@ void Field_KeyDownEvent( field_t *edit, int key ) len = Q_strlen( edit->buffer ); - if ( key == K_DEL ) + if( key == K_DEL ) { - if ( edit->cursor < len ) - { + if( edit->cursor < len ) memmove( edit->buffer + edit->cursor, edit->buffer + edit->cursor + 1, len - edit->cursor ); - } return; } - if ( key == K_BACKSPACE ) + + if( key == K_BACKSPACE ) { - if ( edit->cursor > 0 ) + if( edit->cursor > 0 ) { memmove( edit->buffer + edit->cursor - 1, edit->buffer + edit->cursor, len - edit->cursor + 1 ); edit->cursor--; - if ( edit->scroll ) edit->scroll--; + if( edit->scroll ) edit->scroll--; } return; } - if ( key == K_RIGHTARROW ) + + if( key == K_RIGHTARROW ) { - if ( edit->cursor < len ) edit->cursor++; - if ( edit->cursor >= edit->scroll + edit->widthInChars && edit->cursor <= len ) + if( edit->cursor < len ) edit->cursor++; + if( edit->cursor >= edit->scroll + edit->widthInChars && edit->cursor <= len ) edit->scroll++; return; } - if ( key == K_LEFTARROW ) + + if( key == K_LEFTARROW ) { - if ( edit->cursor > 0 ) edit->cursor--; - if ( edit->cursor < edit->scroll ) edit->scroll--; + if( edit->cursor > 0 ) edit->cursor--; + if( edit->cursor < edit->scroll ) edit->scroll--; return; } - if ( key == K_HOME || ( Q_tolower(key) == 'a' && Key_IsDown( K_CTRL ))) + + if( key == K_HOME || ( Q_tolower(key) == 'a' && Key_IsDown( K_CTRL ))) { edit->cursor = 0; return; } - if ( key == K_END || ( Q_tolower(key) == 'e' && Key_IsDown( K_CTRL ))) + + if( key == K_END || ( Q_tolower(key) == 'e' && Key_IsDown( K_CTRL ))) { edit->cursor = len; return; } - if ( key == K_INS ) + + if( key == K_INS ) { host.key_overstrike = !host.key_overstrike; return; @@ -1052,7 +1140,7 @@ Field_CharEvent */ void Field_CharEvent( field_t *edit, int ch ) { - int len; + int len; if( ch == 'v' - 'a' + 1 ) { @@ -1060,6 +1148,7 @@ void Field_CharEvent( field_t *edit, int ch ) Field_Paste( edit ); return; } + if( ch == 'c' - 'a' + 1 ) { // ctrl-c clears the field @@ -1076,6 +1165,7 @@ void Field_CharEvent( field_t *edit, int ch ) edit->scroll = 0; return; } + if( ch == 'e' - 'a' + 1 ) { // ctrl-e is end @@ -1085,9 +1175,9 @@ void Field_CharEvent( field_t *edit, int ch ) } // ignore any other non printable chars - if ( ch < 32 ) return; + if( ch < 32 ) return; - if ( host.key_overstrike ) + if( host.key_overstrike ) { if ( edit->cursor == MAX_STRING - 1 ) return; edit->buffer[edit->cursor] = ch; @@ -1106,6 +1196,76 @@ void Field_CharEvent( field_t *edit, int ch ) if( edit->cursor == len + 1) edit->buffer[edit->cursor] = 0; } +/* +================== +Field_DrawInputLine +================== +*/ +void Field_DrawInputLine( int x, int y, field_t *edit ) +{ + int len, cursorChar; + int drawLen, hideChar = -1; + int prestep, curPos; + char str[MAX_SYSPATH]; + byte *colorDefault; + + drawLen = edit->widthInChars; + len = Q_strlen( edit->buffer ) + 1; + colorDefault = g_color_table[ColorIndex( COLOR_DEFAULT )]; + + // guarantee that cursor will be visible + if( len <= drawLen ) + { + prestep = 0; + } + else + { + if( edit->scroll + drawLen > len ) + { + edit->scroll = len - drawLen; + if( edit->scroll < 0 ) edit->scroll = 0; + } + + prestep = edit->scroll; + } + + if( prestep + drawLen > len ) + drawLen = len - prestep; + + // extract characters from the field at + ASSERT( drawLen < MAX_SYSPATH ); + + Q_memcpy( str, edit->buffer + prestep, drawLen ); + str[drawLen] = 0; + + // save char for overstrike + cursorChar = str[edit->cursor - prestep]; + + if( host.key_overstrike && cursorChar && !((int)( host.realtime * 4 ) & 1 )) + hideChar = edit->cursor - prestep; // skip this char + + // draw it + Con_DrawGenericString( x, y, str, colorDefault, false, hideChar ); + + // draw the cursor + if((int)( host.realtime * 4 ) & 1 ) return; // off blink + + // calc cursor position + str[edit->cursor - prestep] = 0; + Con_DrawStringLen( str, &curPos, NULL ); + + if( host.key_overstrike && cursorChar ) + { + // overstrike cursor + pglEnable( GL_BLEND ); + pglDisable( GL_ALPHA_TEST ); + pglBlendFunc( GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA ); + pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + Con_DrawGenericChar( x + curPos, y, cursorChar, colorDefault ); + } + else Con_DrawCharacter( x + curPos, y, '_', colorDefault ); +} + /* ============================================================================= @@ -1247,6 +1407,42 @@ void Key_Console( int key ) Field_KeyDownEvent( &con.input, key ); } +/* +================ +Key_Message + +In game talk message +================ +*/ +void Key_Message( int key ) +{ + char buffer[MAX_SYSPATH]; + + if( key == K_ESCAPE ) + { + Key_SetKeyDest( key_game ); + Con_ClearField( &con.chat ); + return; + } + + if( key == K_ENTER || key == K_KP_ENTER ) + { + if( con.chat.buffer[0] && cls.state == ca_active ) + { + if( chat_team ) Q_snprintf( buffer, sizeof( buffer ), "say_team \"%s\"\n", con.chat.buffer ); + else Q_snprintf( buffer, sizeof( buffer ), "say \"%s\"\n", con.chat.buffer ); + + Cbuf_AddText( buffer ); + } + + Key_SetKeyDest( key_game ); + Con_ClearField( &con.chat ); + return; + } + + Field_KeyDownEvent( &con.chat, key ); +} + /* ============================================================================== @@ -1263,74 +1459,18 @@ The input line scrolls horizontally if typing goes beyond the right edge */ void Con_DrawInput( void ) { - int len; - int drawLen, hideChar = -1; - int prestep, curPos; - int x, y, cursorChar; - char str[MAX_SYSPATH]; byte *colorDefault; + int x, y; // don't draw anything (always draw if not active) if( cls.key_dest != key_console ) return; x = QCHAR_WIDTH; // room for ']' y = con.vislines - ( con.charHeight * 2 ); - drawLen = con.input.widthInChars; - len = Q_strlen( con.input.buffer ) + 1; colorDefault = g_color_table[ColorIndex( COLOR_DEFAULT )]; - // guarantee that cursor will be visible - if( len <= drawLen ) - { - prestep = 0; - } - else - { - if( con.input.scroll + drawLen > len ) - { - con.input.scroll = len - drawLen; - if( con.input.scroll < 0 ) - con.input.scroll = 0; - } - prestep = con.input.scroll; - } - - if( prestep + drawLen > len ) - drawLen = len - prestep; - - // extract characters from the field at - ASSERT( drawLen < MAX_SYSPATH ); - - Q_memcpy( str, con.input.buffer + prestep, drawLen ); - str[drawLen] = 0; - - // save char for overstrike - cursorChar = str[con.input.cursor - prestep]; - - if( host.key_overstrike && cursorChar && !((int)( host.realtime * 4 ) & 1 )) - hideChar = con.input.cursor - prestep; // skip this char - - // draw it - Con_DrawGenericString( x, y, str, colorDefault, false, hideChar ); Con_DrawCharacter( QCHAR_WIDTH >> 1, y, ']', colorDefault ); - - // draw the cursor - if((int)( host.realtime * 4 ) & 1 ) return; // off blink - - // calc cursor position - str[con.input.cursor - prestep] = 0; - Con_DrawStringLen( str, &curPos, NULL ); - - if( host.key_overstrike && cursorChar ) - { - // overstrike cursor - pglEnable( GL_BLEND ); - pglDisable( GL_ALPHA_TEST ); - pglBlendFunc( GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA ); - pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); - Con_DrawGenericChar( x + curPos, y, cursorChar, colorDefault ); - } - else Con_DrawCharacter( x + curPos, y, '_', colorDefault ); + Field_DrawInputLine( x, y, &con.input ); } /* @@ -1400,33 +1540,53 @@ void Con_DrawNotify( void ) short *text; float time; - if( !host.developer || Cvar_VariableInteger( "sv_background" )) - return; - - currentColor = 7; - pglColor4ubv( g_color_table[currentColor] ); - - for( i = con.current - CON_TIMES + 1; i <= con.current; i++ ) + if( host.developer && !Cvar_VariableInteger( "sv_background" )) { - if( i < 0 ) continue; - time = con.times[i % CON_TIMES]; - if( time == 0 ) continue; - time = host.realtime - time; + currentColor = 7; + pglColor4ubv( g_color_table[currentColor] ); - if( time > con_notifytime->value ) - continue; // expired + for( i = con.current - CON_TIMES + 1; i <= con.current; i++ ) + { + if( i < 0 ) continue; + time = con.times[i % CON_TIMES]; + if( time == 0 ) continue; + time = host.realtime - time; + + if( time > con_notifytime->value ) + continue; // expired + + text = con.text + (i % con.totallines) * con.linewidth; + start = con.charWidths[' ']; // offset one space at left screen side + + for( x = 0; x < con.linewidth; x++ ) + { + if((( text[x] >> 8 ) & 7 ) != currentColor ) + currentColor = ( text[x] >> 8 ) & 7; + start += Con_DrawCharacter( start, v, text[x] & 0xFF, g_color_table[currentColor] ); + } + v += con.charHeight; + } + } + + if( cls.key_dest == key_message ) + { + char buf[16]; + int len; + + currentColor = 7; + pglColor4ubv( g_color_table[currentColor] ); - text = con.text + (i % con.totallines) * con.linewidth; start = con.charWidths[' ']; // offset one space at left screen side - for( x = 0; x < con.linewidth; x++ ) - { - if((( text[x] >> 8 ) & 7 ) != currentColor ) - currentColor = ( text[x] >> 8 ) & 7; - start += Con_DrawCharacter( start, v, text[x] & 0xFF, g_color_table[currentColor] ); - } - v += con.charHeight; + if( chat_team ) Q_strncpy( buf, "say_team: ", sizeof( buf )); + else Q_strncpy( buf, "say: ", sizeof( buf )); + + Con_DrawStringLen( buf, &len, NULL ); + Con_DrawString( start, v, buf, g_color_table[7] ); + + Field_DrawInputLine( start + len, v, &con.chat ); } + pglColor4ub( 255, 255, 255, 255 ); } @@ -1591,7 +1751,7 @@ void Con_DrawConsole( void ) { if( con.displayFrac ) Con_DrawSolidConsole( con.displayFrac ); - else if( cls.state == ca_active && cls.key_dest == key_game ) + else if( cls.state == ca_active && ( cls.key_dest == key_game || cls.key_dest == key_message )) Con_DrawNotify(); // draw notify lines } break; @@ -1613,9 +1773,11 @@ void Con_DrawVersion( void ) int start, height = scr_height->integer; string curbuild; - if( cls.key_dest != key_menu ) return; + if( cls.key_dest != key_menu && cls.scrshot_action != scrshot_normal ) return; - Q_snprintf( curbuild, MAX_STRING, "v%i/%g (build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildnum( )); + if( cls.scrshot_action == scrshot_normal ) + Q_snprintf( curbuild, MAX_STRING, "Xash3D v%i/%g (build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildnum( )); + else Q_snprintf( curbuild, MAX_STRING, "v%i/%g (build %i)", PROTOCOL_VERSION, XASH_VERSION, Q_buildnum( )); Con_DrawStringLen( curbuild, &stringLen, &charH ); start = scr_width->integer - stringLen * 1.05f; stringLen = Con_StringLength( curbuild ); @@ -1668,9 +1830,24 @@ CONSOLE INTERFACE ============================================================================== */ +/* +================ +Con_CharEvent + +Console input +================ +*/ void Con_CharEvent( int key ) { - Field_CharEvent( &con.input, key ); + // distribute the key down event to the apropriate handler + if( cls.key_dest == key_console ) + { + Field_CharEvent( &con.input, key ); + } + else if( cls.key_dest == key_message ) + { + Field_CharEvent( &con.chat, key ); + } } void Con_VidInit( void ) diff --git a/engine/common/crtlib.h b/engine/common/crtlib.h index a14e647a..6b8921e1 100644 --- a/engine/common/crtlib.h +++ b/engine/common/crtlib.h @@ -27,6 +27,9 @@ enum TIME_FILENAME, }; +#define CMD_EXTDLL BIT( 0 ) // added by game.dll +#define CMD_CLIENTDLL BIT( 1 ) // added by client.dll + typedef void (*setpair_t)( const char *key, const char *value, void *buffer, void *numpairs ); typedef void (*xcommand_t)( void ); @@ -118,7 +121,7 @@ uint Cmd_Argc( void ); char *Cmd_Args( void ); char *Cmd_Argv( int arg ); void Cmd_Init( void ); -void Cmd_Unlink( void ); +void Cmd_Unlink( int group ); void Cmd_AddCommand( const char *cmd_name, xcommand_t function, const char *cmd_desc ); void Cmd_AddGameCommand( const char *cmd_name, xcommand_t function ); void Cmd_AddClientCommand( const char *cmd_name, xcommand_t function ); diff --git a/engine/common/cvar.c b/engine/common/cvar.c index de75130d..cfcd4eb0 100644 --- a/engine/common/cvar.c +++ b/engine/common/cvar.c @@ -450,7 +450,7 @@ convar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force ) // step through the string, only copying back in characters that are printable while( *pS ) { - if( *pS < 32 || *pS > 255 ) + if( ((byte)*pS) < 32 || ((byte)*pS) > 255 ) { pS++; continue; diff --git a/engine/common/imagelib/img_bmp.c b/engine/common/imagelib/img_bmp.c index ea3034fc..8c931b10 100644 --- a/engine/common/imagelib/img_bmp.c +++ b/engine/common/imagelib/img_bmp.c @@ -26,6 +26,7 @@ qboolean Image_LoadBMP( const char *name, const byte *buffer, size_t filesize ) byte palette[256][4]; int i, columns, column, rows, row, bpp = 1; int cbPalBytes = 0, padSize = 0, bps = 0; + qboolean load_qfont = false; bmp_t bhdr; if( filesize < sizeof( bhdr )) return false; @@ -81,9 +82,21 @@ qboolean Image_LoadBMP( const char *name, const byte *buffer, size_t filesize ) image.width = columns = bhdr.width; image.height = rows = abs( bhdr.height ); - if(!Image_ValidSize( name )) + if( !Image_ValidSize( name )) return false; + // special hack for loading qfont + if( !Q_strcmp( "#XASH_SYSTEMFONT_001", name )) + { + // NOTE: same as system font we can use 4-bit bmps only + // step1: move main layer into alpha-channel (give grayscale from RED channel) + // step2: fill main layer with 255 255 255 color (white) + // step3: ???? + // step4: PROFIT!!! (economy up to 150 kb for menu.dll final size) + image.flags |= IMAGE_HAS_ALPHA; + load_qfont = true; + } + if( bhdr.bitsPerPixel <= 8 ) { // figure out how many entires are actually in the table @@ -170,16 +183,36 @@ qboolean Image_LoadBMP( const char *name, const byte *buffer, size_t filesize ) case 4: alpha = *buf_p++; palIndex = alpha >> 4; - *pixbuf++ = palette[palIndex][2]; - *pixbuf++ = palette[palIndex][1]; - *pixbuf++ = palette[palIndex][0]; - *pixbuf++ = palette[palIndex][3]; + if( load_qfont ) + { + *pixbuf++ = red = 255; + *pixbuf++ = green = 255; + *pixbuf++ = blue = 255; + *pixbuf++ = palette[palIndex][2]; + } + else + { + *pixbuf++ = red = palette[palIndex][2]; + *pixbuf++ = green = palette[palIndex][1]; + *pixbuf++ = blue = palette[palIndex][0]; + *pixbuf++ = palette[palIndex][3]; + } if( ++column == columns ) break; palIndex = alpha & 0x0F; - *pixbuf++ = palette[palIndex][2]; - *pixbuf++ = palette[palIndex][1]; - *pixbuf++ = palette[palIndex][0]; - *pixbuf++ = palette[palIndex][3]; + if( load_qfont ) + { + *pixbuf++ = red = 255; + *pixbuf++ = green = 255; + *pixbuf++ = blue = 255; + *pixbuf++ = palette[palIndex][2]; + } + else + { + *pixbuf++ = red = palette[palIndex][2]; + *pixbuf++ = green = palette[palIndex][1]; + *pixbuf++ = blue = palette[palIndex][0]; + *pixbuf++ = palette[palIndex][3]; + } break; case 8: palIndex = *buf_p++; diff --git a/engine/common/imagelib/img_tga.c b/engine/common/imagelib/img_tga.c index 19e5fe26..3079bb95 100644 --- a/engine/common/imagelib/img_tga.c +++ b/engine/common/imagelib/img_tga.c @@ -49,7 +49,7 @@ qboolean Image_LoadTGA( const char *name, const byte *buffer, size_t filesize ) if( targa_header.id_length != 0 ) buf_p += targa_header.id_length; // skip TARGA image comment // check for tga file - if(!Image_ValidSize( name )) return false; + if( !Image_ValidSize( name )) return false; image.type = PF_RGBA_32; // always exctracted to 32-bit buffer diff --git a/engine/common/imagelib/img_utils.c b/engine/common/imagelib/img_utils.c index 1ba59d0a..5003cdf9 100644 --- a/engine/common/imagelib/img_utils.c +++ b/engine/common/imagelib/img_utils.c @@ -95,8 +95,8 @@ static const loadpixformat_t load_null[] = static const loadpixformat_t load_game[] = { +{ "%s%s.%s", "bmp", Image_LoadBMP, IL_HINT_NO }, // WON menu images { "%s%s.%s", "tga", Image_LoadTGA, IL_HINT_NO }, // hl vgui menus -{ "%s%s.%s", "bmp", Image_LoadBMP, IL_HINT_NO }, // hl skyboxes { "%s%s.%s", "jpg", Image_LoadJPG, IL_HINT_NO }, // hl skyboxes { "%s%s.%s", "mip", Image_LoadMIP, IL_HINT_NO }, // hl textures from wad or buffer { "%s%s.%s", "mdl", Image_LoadMDL, IL_HINT_HL }, // hl studio model skins diff --git a/engine/common/imagelib/img_wad.c b/engine/common/imagelib/img_wad.c index d7131f2b..8121e950 100644 --- a/engine/common/imagelib/img_wad.c +++ b/engine/common/imagelib/img_wad.c @@ -78,10 +78,11 @@ qboolean Image_LoadFNT( const char *name, const byte *buffer, size_t filesize ) if( filesize < sizeof( font )) return false; + Q_memcpy( &font, buffer, sizeof( font )); // last sixty four bytes - what the hell ???? - size = sizeof( qfont_t ) - 4 + ( 128 * font.width * QCHAR_WIDTH ) + sizeof( short ) + 768 + 64; + size = sizeof( qfont_t ) - 4 + ( font.height * font.width * QCHAR_WIDTH ) + sizeof( short ) + 768 + 64; if( size != filesize ) { @@ -96,21 +97,22 @@ qboolean Image_LoadFNT( const char *name, const byte *buffer, size_t filesize ) image.height = font.height; } - if(!Image_LumpValidSize( name )) return false; - fin = buffer + sizeof( font ) - 4; + if( !Image_LumpValidSize( name )) + return false; + fin = buffer + sizeof( font ) - 4; pal = fin + (image.width * image.height); numcolors = *(short *)pal, pal += sizeof( short ); - image.flags |= IMAGE_HAS_ALPHA; // fonts always have transparency if( numcolors == 768 ) { // newstyle font Image_GetPaletteLMP( pal, LUMP_QFONT ); + image.flags |= IMAGE_HAS_ALPHA; // fonts always have transparency } else if( numcolors == 256 ) { - // oldstyle font + // oldstyle font (no transparency) Image_GetPaletteLMP( pal, LUMP_TRANSPARENT ); } else diff --git a/engine/common/keys.c b/engine/common/keys.c index f0646981..30f30b2f 100644 --- a/engine/common/keys.c +++ b/engine/common/keys.c @@ -548,6 +548,9 @@ void Key_Event( int key, qboolean down ) if( host.mouse_visible && cls.state != ca_cinematic ) return; // handled in client.dll break; + case key_message: + Key_Message( key ); + return; case key_console: if( cls.state == ca_active && !cl.background ) Key_SetKeyDest( key_game ); @@ -636,6 +639,10 @@ void Key_Event( int key, qboolean down ) { Key_Console( key ); } + else if( cls.key_dest == key_message ) + { + Key_Message( key ); + } } /* @@ -658,6 +665,9 @@ void Key_SetKeyDest( int key_dest ) case key_console: cls.key_dest = key_console; break; + case key_message: + cls.key_dest = key_message; + break; default: Host_Error( "Key_SetKeyDest: wrong destination (%i)\n", key_dest ); break; @@ -701,7 +711,7 @@ void CL_CharEvent( int key ) if( key == '`' || key == '~' ) return; // distribute the key down event to the apropriate handler - if( cls.key_dest == key_console ) + if( cls.key_dest == key_console || cls.key_dest == key_message ) { Con_CharEvent( key ); } diff --git a/engine/common/library.c b/engine/common/library.c index 7f13fafb..00667c6c 100644 --- a/engine/common/library.c +++ b/engine/common/library.c @@ -164,7 +164,8 @@ qboolean LibraryLoadSymbols( dll_user_t *hInst ) goto table_error; } - if( !Q_strcmp( section_header.Name, ".rdata" )) + if((( optional_header.DataDirectory[0].VirtualAddress >= section_header.VirtualAddress ) && + (optional_header.DataDirectory[0].VirtualAddress < (section_header.VirtualAddress + section_header.Misc.VirtualSize)))) { rdata_found = true; break; diff --git a/engine/common/model.c b/engine/common/model.c index 965bddde..1833ed13 100644 --- a/engine/common/model.c +++ b/engine/common/model.c @@ -29,6 +29,7 @@ static model_t *com_models[MAX_MODELS]; // shared replacement modeltable static model_t cm_models[MAX_MODELS]; static int cm_nummodels = 0; static byte visdata[MAX_MAP_LEAFS/8]; // intermediate buffer +int bmodel_version; // global stuff to detect bsp version model_t *loadmodel; model_t *worldmodel; @@ -484,10 +485,13 @@ static void Mod_LoadTextures( const dlump_t *l ) mip_t *mt; int i, j; - // release old sky layers first - GL_FreeTexture( tr.solidskyTexture ); - GL_FreeTexture( tr.alphaskyTexture ); - tr.solidskyTexture = tr.alphaskyTexture = 0; + if( world.loading ) + { + // release old sky layers first + GL_FreeTexture( tr.solidskyTexture ); + GL_FreeTexture( tr.alphaskyTexture ); + tr.solidskyTexture = tr.alphaskyTexture = 0; + } if( !l->filelen ) { @@ -535,7 +539,7 @@ static void Mod_LoadTextures( const dlump_t *l ) tx->height = mt->height; // check for sky texture (quake1 only!) - if( world.version == Q1BSP_VERSION && !Q_strncmp( mt->name, "sky", 3 )) + if( world.loading && world.version == Q1BSP_VERSION && !Q_strncmp( mt->name, "sky", 3 )) { R_InitSky( mt, tx ); } @@ -544,7 +548,7 @@ static void Mod_LoadTextures( const dlump_t *l ) // NOTE: imagelib detect miptex version by size // 770 additional bytes is indicated custom palette int size = (int)sizeof( mip_t ) + ((mt->width * mt->height * 85)>>6); - if( world.version == HLBSP_VERSION ) size += sizeof( short ) + 768; + if( bmodel_version == HLBSP_VERSION ) size += sizeof( short ) + 768; tx->gl_texturenum = GL_LoadTexture( texname, (byte *)mt, size, 0 ); } @@ -566,7 +570,7 @@ static void Mod_LoadTextures( const dlump_t *l ) // NOTE: imagelib detect miptex version by size // 770 additional bytes is indicated custom palette int size = (int)sizeof( mip_t ) + ((mt->width * mt->height * 85)>>6); - if( world.version == HLBSP_VERSION ) size += sizeof( short ) + 768; + if( bmodel_version == HLBSP_VERSION ) size += sizeof( short ) + 768; tx->fb_texturenum = GL_LoadTexture( texname, (byte *)mt, size, TF_MAKELUMA|TF_NOMIPMAP ); } @@ -789,7 +793,7 @@ static void Mod_LoadLighting( const dlump_t *l ) if( !l->filelen ) return; in = (void *)(mod_base + l->fileofs); - switch( world.version ) + switch( bmodel_version ) { case Q1BSP_VERSION: // expand the white lighting data @@ -953,7 +957,7 @@ static void Mod_LoadSurfaces( const dlump_t *l ) if( loadmodel->lightdata && in->lightofs != -1 ) { - if( world.version == HLBSP_VERSION ) + if( bmodel_version == HLBSP_VERSION ) out->samples = loadmodel->lightdata + (in->lightofs / 3); else out->samples = loadmodel->lightdata + in->lightofs; } @@ -961,7 +965,7 @@ static void Mod_LoadSurfaces( const dlump_t *l ) for( j = 0; j < MAXLIGHTMAPS; j++ ) out->styles[j] = in->styles[j]; - if( out->flags & SURF_DRAWSKY && world.version == Q1BSP_VERSION ) + if( world.loading && out->flags & SURF_DRAWSKY && world.version == Q1BSP_VERSION ) GL_SubdivideSurface( out ); // cut up polygon for warps if( out->flags & SURF_DRAWTURB ) @@ -1222,6 +1226,9 @@ Mod_LoadVisibility */ static void Mod_LoadVisibility( const dlump_t *l ) { + // bmodels has no visibility + if( !world.loading ) return; + if( !l->filelen ) { MsgDev( D_WARN, "map ^2%s^7 has no visibility\n", loadmodel->name ); @@ -1367,7 +1374,7 @@ void Mod_CalcPHS( void ) size_t phsdatasize; // no worldmodel or no visdata - if( !worldmodel || !worldmodel->visdata ) + if( !world.loading || !worldmodel || !worldmodel->visdata ) return; MsgDev( D_NOTE, "Building PAS...\n" ); @@ -1539,6 +1546,7 @@ static void Mod_LoadBrushModel( model_t *mod, const void *buffer ) // will be merged later loadmodel->type = mod_brush; if( world.loading ) world.version = i; + bmodel_version = i; // share it // swap all the lumps mod_base = (byte *)header; @@ -1705,6 +1713,7 @@ Loads a model into the cache model_t *Mod_LoadModel( model_t *mod, qboolean crash ) { byte *buf; + char tempname[64]; if( !mod ) { @@ -1717,12 +1726,17 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash ) if( mod->mempool || mod->name[0] == '*' ) return mod; + // store modelname to show error + Q_strncpy( tempname, mod->name, sizeof( tempname )); + buf = COM_LoadFile( mod->name, 0, NULL ); if( !buf ) { - if( crash ) Host_Error( "Mod_ForName: %s couldn't load\n", mod->name ); - else MsgDev( D_ERROR, "Mod_ForName: %s couldn't load\n", mod->name ); Q_memset( mod, 0, sizeof( model_t )); + + if( crash ) Host_Error( "Mod_ForName: %s couldn't load\n", tempname ); + else MsgDev( D_ERROR, "Mod_ForName: %s couldn't load\n", tempname ); + return NULL; } @@ -1753,8 +1767,8 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash ) Mod_FreeModel( mod ); // check for loading problems - if( crash ) Host_Error( "Mod_ForName: %s unknown format\n", mod->name ); - else MsgDev( D_ERROR, "Mod_ForName: %s unknown format\n", mod->name ); + if( crash ) Host_Error( "Mod_ForName: %s unknown format\n", tempname ); + else MsgDev( D_ERROR, "Mod_ForName: %s unknown format\n", tempname ); return NULL; } return mod; @@ -1800,11 +1814,13 @@ void Mod_LoadWorld( const char *name, uint *checksum, qboolean force ) } // clear all studio submodels on restart - for( i = 0; i < cm_nummodels; i++ ) + // HACKHACK: throw all external BSP-models to refresh their lightmaps properly + for( i = 1; i < cm_nummodels; i++ ) { - if( cm_models[i].type != mod_studio ) - continue; - cm_models[i].submodels = NULL; + if( cm_models[i].type == mod_studio ) + cm_models[i].submodels = NULL; + else if( cm_models[i].type == mod_brush ) + Mod_FreeModel( cm_models + i ); } // purge all submodels diff --git a/engine/common/netchan.h b/engine/common/netchan.h index 9b2b9db7..75439a0f 100644 --- a/engine/common/netchan.h +++ b/engine/common/netchan.h @@ -59,6 +59,7 @@ GNU General Public License for more details. // bytes will be stripped by the networking channel layer #define NET_MAX_MESSAGE PAD_NUMBER(( NET_MAX_PAYLOAD + HEADER_BYTES ), 16 ) +#define MASTERSERVER_ADR "hl1master.steampowered.com:27010" #define PORT_MASTER 27010 #define PORT_CLIENT 27005 #define PORT_SERVER 27015 @@ -201,6 +202,7 @@ void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport ); qboolean Netchan_CopyNormalFragments( netchan_t *chan, sizebuf_t *msg ); qboolean Netchan_CopyFileFragments( netchan_t *chan, sizebuf_t *msg ); void Netchan_CreateFragments( qboolean server, netchan_t *chan, sizebuf_t *msg ); +int Netchan_CreateFileFragments( qboolean server, netchan_t *chan, const char *filename ); void Netchan_Transmit( netchan_t *chan, int lengthInBytes, byte *data ); void Netchan_TransmitBits( netchan_t *chan, int lengthInBits, byte *data ); void Netchan_OutOfBand( int net_socket, netadr_t adr, int length, byte *data ); @@ -209,6 +211,7 @@ qboolean Netchan_Process( netchan_t *chan, sizebuf_t *msg ); void Netchan_UpdateProgress( netchan_t *chan ); qboolean Netchan_IncomingReady( netchan_t *chan ); qboolean Netchan_CanPacket( netchan_t *chan ); +void Netchan_FragSend( netchan_t *chan ); void Netchan_Clear( netchan_t *chan ); // huffman compression diff --git a/engine/common/network.c b/engine/common/network.c index ee127937..bbcfc37b 100644 --- a/engine/common/network.c +++ b/engine/common/network.c @@ -553,7 +553,7 @@ static void NET_OpenIP( void ) if( !ip_sockets[NS_SERVER] ) { - port = Cvar_Get("ip_hostport", "0", CVAR_INIT, "network server port" )->integer; + port = Cvar_Get( "ip_hostport", "0", CVAR_INIT, "network server port" )->integer; if( !port ) port = Cvar_Get( "port", va( "%i", PORT_SERVER ), CVAR_INIT, "network default port" )->integer; ip_sockets[NS_SERVER] = NET_IPSocket( net_ip->string, port ); diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 1fc388b6..4cd285fc 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -16,7 +16,7 @@ GNU General Public License for more details. #ifndef PROTOCOL_H #define PROTOCOL_H -#define PROTOCOL_VERSION 41 +#define PROTOCOL_VERSION 42 // server to client #define svc_bad 0 // immediately crash client when received @@ -29,7 +29,7 @@ GNU General Public License for more details. #define svc_time 7 // [float] server time #define svc_print 8 // [byte] id [string] null terminated string #define svc_stufftext 9 // [string] stuffed into client's console buffer -#define svc_setangle 10 // [angle angle] set the view angle to this absolute value +#define svc_setangle 10 // [angle angle angle] set the view angle to this absolute value #define svc_serverdata 11 // [long] protocol ... #define svc_lightstyle 12 // [index][pattern] #define svc_updateuserinfo 13 // [byte] playernum, [string] userinfo @@ -62,9 +62,9 @@ GNU General Public License for more details. #define svc_packetentities 40 // [short][...] #define svc_deltapacketentities 41 // [short][byte][...] #define svc_chokecount 42 // [byte] - +#define svc_resourcelist 43 // [short][...] #define svc_deltamovevars 44 // [movevars_t] - +#define svc_customization 45 #define svc_crosshairangle 47 // [byte][byte] #define svc_soundfade 48 // [float*4] sound fade parms @@ -154,4 +154,13 @@ GNU General Public License for more details. #error MAX_COORD_INTEGER does not match COORD_INTEGER_BITS #endif +#define MAX_RESOURCES (MAX_MODELS+MAX_SOUNDS+MAX_CUSTOM+MAX_EVENTS) + +typedef struct +{ + int rescount; + int restype[MAX_RESOURCES]; + char resnames[MAX_RESOURCES][CS_SIZE]; +} resourcelist_t; + #endif//PROTOCOL_H \ No newline at end of file diff --git a/engine/common/soundlib/mpeg.lib b/engine/common/soundlib/mpeg.lib index 1979c5eb5356aca41606c3362fcc2d2cdd2716e8..b4155833851eb7dd9c545fefe9eeea1e634c4228 100644 GIT binary patch literal 62114 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

_sM+w&eimHTn?PxY-e~ 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 diff --git a/engine/common/soundlib/mpeg.old b/engine/common/soundlib/mpeg.old new file mode 100644 index 0000000000000000000000000000000000000000..1979c5eb5356aca41606c3362fcc2d2cdd2716e8 GIT binary patch literal 143350 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

_sM+w&eimHTn?PxY-e~ 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 literal 0 HcmV?d00001 diff --git a/engine/common/soundlib/snd_mp3.c b/engine/common/soundlib/snd_mp3.c index 0b1eae0b..d4e7d642 100644 --- a/engine/common/soundlib/snd_mp3.c +++ b/engine/common/soundlib/snd_mp3.c @@ -17,246 +17,33 @@ GNU General Public License for more details. /* ======================================================================= - LIBMAD DEFINITION + MPG123 DEFINITION ======================================================================= */ -#define BUFFER_GUARD 8 -#define BUFFER_MDLEN (511 + 2048 + BUFFER_GUARD) -#define BUFFER_SIZE 4096 // must be large than BUFFER_MDLEN +#define MP3_ERR -1 +#define MP3_OK 0 +#define MP3_NEED_MORE 1 -#define MPEG_F_FRACBITS 28 -#define MPEG_F( x ) ((int)( x##L )) -#define MPEG_F_ONE MPEG_F( 0x10000000 ) +#define FRAME_SIZE 16384 // must match with mp3 frame size -enum +typedef struct mpeg_s { - MP3_ERROR_NONE = 0x0000, // no error - MP3_ERROR_BUFLEN = 0x0001, // input buffer too small (or EOF) - MP3_ERROR_BUFPTR = 0x0002, // invalid (null) buffer pointer - MP3_ERROR_NOMEM = 0x0031, // not enough memory - MP3_ERROR_LOSTSYNC = 0x0101, // lost synchronization - MP3_ERROR_BADLAYER = 0x0102, // reserved header layer value - MP3_ERROR_BADBITRATE = 0x0103, // forbidden bitrate value - MP3_ERROR_BADSAMPLERATE = 0x0104, // reserved sample frequency value - MP3_ERROR_BADEMPHASIS = 0x0105, // reserved emphasis value - MP3_ERROR_BADCRC = 0x0201, // CRC check failed - MP3_ERROR_BADBITALLOC = 0x0211, // forbidden bit allocation value - MP3_ERROR_BADSCALEFACTOR = 0x0221, // bad scalefactor index - MP3_ERROR_BADMODE = 0x0222, // bad bitrate/mode combination - MP3_ERROR_BADFRAMELEN = 0x0231, // bad frame length - MP3_ERROR_BADBIGVALUES = 0x0232, // bad big_values count - MP3_ERROR_BADBLOCKTYPE = 0x0233, // reserved block_type - MP3_ERROR_BADSCFSI = 0x0234, // bad scalefactor selection info - MP3_ERROR_BADDATAPTR = 0x0235, // bad main_data_begin pointer - MP3_ERROR_BADPART3LEN = 0x0236, // bad audio data length - MP3_ERROR_BADHUFFTABLE = 0x0237, // bad Huffman table select - MP3_ERROR_BADHUFFDATA = 0x0238, // Huffman data overrun - MP3_ERROR_BADSTEREO = 0x0239 // incompatible block_type for JS -}; + void *state; // hidden decoder state + void *vbrtag; // valid for VBR-encoded mpegs -enum -{ - MODE_SINGLE_CHANNEL = 0, // single channel - MODE_DUAL_CHANNEL, // dual channel - MODE_JOINT_STEREO, // joint (MS/intensity) stereo - MODE_STEREO // normal LR stereo -}; - -typedef struct -{ - uint samplerate; // sampling frequency (Hz) - word channels; // number of channels - word length; // number of samples per channel - int samples[2][1152]; // PCM output samples [ch][sample] -} pcm_t; - -typedef struct -{ - int filter[2][2][2][16][8]; // polyphase filterbank outputs - uint phase; // current processing phase - pcm_t pcm; // PCM output -} synth_t; - -typedef struct -{ - const byte *byte; - word cache; - word left; -} bitptr_t; - -typedef struct -{ - long seconds; // whole seconds - dword fraction; // 1 / TIMER_RESOLUTION seconds -} mp3_timer_t; - -typedef struct -{ - int layer; // audio layer (1, 2, or 3) - int mode; // channel mode (see above) - int mode_extension; // additional mode info - int emphasis; // de-emphasis to use (see above) - - dword bitrate; // stream bitrate (bps) - uint samplerate; // sampling frequency (Hz) - - word crc_check; // frame CRC accumulator - word crc_target; // final target CRC checksum - - int flags; // flags (see below) - int private_bits; // private bits (see below) - mp3_timer_t duration; // audio playing time of frame -} mp3_header_t; - -typedef struct -{ - mp3_header_t header; // MPEG audio header - int options; // decoding options (from stream) - - int sbsample[2][36][32]; // synthesis subband filter samples - int (*overlap)[2][32][18]; // Layer III block overlap data -} mp3_frame_t; - -typedef struct -{ - const byte *buffer; // input bitstream buffer - const byte *bufend; // end of buffer - dword skiplen; // bytes to skip before next frame - - int sync; // stream sync found - dword freerate; // free bitrate (fixed) - - const byte *this_frame; // start of current frame - const byte *next_frame; // start of next frame - bitptr_t ptr; // current processing bit pointer - - bitptr_t anc_ptr; // ancillary bits pointer - uint anc_bitlen; // number of ancillary bits - - byte (*data)[BUFFER_MDLEN]; - // Layer III data() - uint md_len; // bytes in data - - int options; // decoding options - int error; // error code -} mp3_stream_t; - -typedef struct -{ - synth_t synth; - mp3_stream_t stream; - mp3_frame_t frame; - int buffer_length; // for reading - byte buffer[BUFFER_SIZE];// frame buffer -} mpegfile_t; - -// libmad exports -extern void mad_synth_init( synth_t* ); -extern void mad_synth_frame( synth_t*, const mp3_frame_t* ); -extern void mad_stream_init( mp3_stream_t* ); -extern void mad_stream_buffer( mp3_stream_t*, const byte*, dword ); -extern void mad_stream_finish( mp3_stream_t* ); -extern void mad_frame_init( mp3_frame_t* ); -extern int mad_frame_decode( mp3_frame_t*, mp3_stream_t* ); -extern void mad_frame_finish( mp3_frame_t* ); - - -/* -================================================================= - - MPEG decompression - -================================================================= -*/ -static int mpeg_read( file_t *file, mpegfile_t *mpeg ) -{ - int ret; - - while( 1 ) - { - ret = FS_Read( file, &mpeg->buffer[mpeg->buffer_length], BUFFER_SIZE - mpeg->buffer_length ); - - // no more bytes are left - if( ret <= 0 ) break; - - mpeg->buffer_length += ret; - - while( 1 ) - { - mad_stream_buffer( &mpeg->stream, mpeg->buffer, mpeg->buffer_length ); - ret = mad_frame_decode( &mpeg->frame, &mpeg->stream ); - - if( mpeg->stream.next_frame ) - { - int length; - - length = mpeg->buffer + mpeg->buffer_length - mpeg->stream.next_frame; - memmove( mpeg->buffer, mpeg->stream.next_frame, length ); - mpeg->buffer_length = length; - } - - if( !ret ) return 1; - if( mpeg->stream.error == MP3_ERROR_BUFLEN ) - break; - } - } - return 0; -} - -static int mpeg_read_mem( const byte *buffer, int *pos, size_t filesize, mpegfile_t *mpeg ) -{ - int ret, readSize; - - while( 1 ) - { - readSize = ( BUFFER_SIZE - mpeg->buffer_length ); - - if(( *pos + readSize ) > filesize ) - readSize = ( filesize - *pos ); - Q_memcpy( &mpeg->buffer[mpeg->buffer_length], buffer + *pos, readSize ); - - // no more bytes are left - if( readSize <= 0 ) break; - *pos += readSize; - mpeg->buffer_length += readSize; - - while( 1 ) - { - mad_stream_buffer( &mpeg->stream, mpeg->buffer, mpeg->buffer_length ); - ret = mad_frame_decode( &mpeg->frame, &mpeg->stream ); - - if( mpeg->stream.next_frame ) - { - int length; - - length = mpeg->buffer + mpeg->buffer_length - mpeg->stream.next_frame; - memmove( mpeg->buffer, mpeg->stream.next_frame, length ); - mpeg->buffer_length = length; - } - - if( !ret ) return 1; - if( mpeg->stream.error == MP3_ERROR_BUFLEN ) - break; - } - } - return 0; -} - -static int mpeg_scale( int sample ) -{ - sample += (1 << ( MPEG_F_FRACBITS - 16 )); - - if( sample >= MPEG_F_ONE ) sample = MPEG_F_ONE - 1; - else if( sample < -MPEG_F_ONE ) sample = -MPEG_F_ONE; - - return sample >> ( MPEG_F_FRACBITS + 1 - 16 ); -} - -static int mpeg_size( mp3_frame_t *frame, long bytes ) -{ - return bytes * 8 / frame->header.bitrate * sound.channels * sound.rate * sound.width; -} + int channels; // num channels + int samples; // per one second + int play_time;// stream size in milliseconds + int rate; // frequency + int outsize; // current data size + char out[8192];// temporary buffer +} mpeg_t; +// mpg123 exports +int create_decoder( mpeg_t *mpg ); +int read_mpeg_header( mpeg_t *mpg, const char *data, long bufsize, long streamsize ); +int read_mpeg_stream( mpeg_t *mpg, const char *data, long bufsize ); +void close_decoder( mpeg_t *mpg ); /* ================================================================= @@ -267,39 +54,38 @@ static int mpeg_size( mp3_frame_t *frame, long bytes ) */ qboolean Sound_LoadMPG( const char *name, const byte *buffer, size_t filesize ) { - mpegfile_t mpeg; - size_t pos = 0; - size_t bytesWrite = 0; + mpeg_t mpeg; + size_t pos = 0; + size_t bytesWrite = 0; // load the file - if( !buffer || filesize <= 0 ) + if( !buffer || filesize < FRAME_SIZE ) return false; - Q_memset( &mpeg, 0, sizeof( mpeg )); - mad_synth_init( &mpeg.synth ); - mad_stream_init( &mpeg.stream ); - mad_frame_init( &mpeg.frame ); + // couldn't create decoder + if( !create_decoder( &mpeg )) + return false; - if( mpeg_read_mem( buffer, &pos, filesize, &mpeg ) == 0 ) + // trying to read header + if( !read_mpeg_header( &mpeg, buffer, FRAME_SIZE, filesize )) { MsgDev( D_ERROR, "Sound_LoadMPG: (%s) is probably corrupted\n", name ); - mad_stream_finish( &mpeg.stream ); - mad_frame_finish( &mpeg.frame ); + close_decoder( &mpeg ); return false; } - sound.channels = ( mpeg.frame.header.mode == MODE_SINGLE_CHANNEL ) ? 1 : 2; - sound.rate = mpeg.frame.header.samplerate; + sound.channels = mpeg.channels; + sound.rate = mpeg.rate; sound.width = 2; // always 16-bit PCM sound.loopstart = -1; - sound.size = mpeg_size( &mpeg.frame, filesize ); + sound.size = ( sound.channels * sound.rate * sound.width ) * ( mpeg.play_time / 1000 ); // in bytes + pos += FRAME_SIZE; // evaluate pos if( !sound.size ) { - // bad ogg file + // bad mpeg file ? MsgDev( D_ERROR, "Sound_LoadMPG: (%s) is probably corrupted\n", name ); - mad_stream_finish( &mpeg.stream ); - mad_frame_finish( &mpeg.frame ); + close_decoder( &mpeg ); return false; } @@ -309,35 +95,36 @@ qboolean Sound_LoadMPG( const char *name, const byte *buffer, size_t filesize ) // decompress mpg into pcm wav format while( bytesWrite < sound.size ) { - word *data; - int i; + int outsize; - mad_synth_frame( &mpeg.synth, &mpeg.frame ); - data = (short *)(sound.wav + bytesWrite); - - for( i = 0; i < mpeg.synth.pcm.length; i++ ) + if( read_mpeg_stream( &mpeg, NULL, 0 ) != MP3_OK ) { - if( sound.channels == 2 ) - { - *data++ = mpeg_scale( mpeg.synth.pcm.samples[0][i] ); - *data++ = mpeg_scale( mpeg.synth.pcm.samples[1][i] ); - } - else - { - *data++ = mpeg_scale( mpeg.synth.pcm.samples[0][i] ); - } + char *data = (char *)buffer + pos; + int bufsize; - bytesWrite += ( sound.width * sound.channels ); - if( bytesWrite >= sound.size ) break; + // if there are no bytes remainig so we can decompress the new frame + if( pos + FRAME_SIZE > filesize ) + bufsize = ( filesize - pos ); + else bufsize = FRAME_SIZE; + pos += bufsize; + + if( read_mpeg_stream( &mpeg, data, bufsize ) != MP3_OK ) + break; // there was end of the stream } - if( !mpeg_read_mem( buffer, &pos, filesize, &mpeg )) - break; + if( bytesWrite + mpeg.outsize > sound.size ) + { + outsize = ( sound.size - bytesWrite ); + Msg( "merge size from %i, to %i\n", mpeg.outsize, outsize ); + } + else outsize = mpeg.outsize; + + Q_memcpy( &sound.wav[bytesWrite], mpeg.out, outsize ); + bytesWrite += outsize; } sound.samples = bytesWrite / ( sound.width * sound.channels ); - mad_stream_finish( &mpeg.stream ); - mad_frame_finish( &mpeg.frame ); + close_decoder( &mpeg ); return true; } @@ -349,28 +136,55 @@ Stream_OpenMPG */ stream_t *Stream_OpenMPG( const char *filename ) { - mpegfile_t *mpegFile; - stream_t *stream; - file_t *file; + mpeg_t *mpegFile; + stream_t *stream; + file_t *file; + long filesize, read_len; + char tempbuff[FRAME_SIZE]; file = FS_Open( filename, "rb", false ); if( !file ) return NULL; + filesize = FS_FileLength( file ); + if( filesize < FRAME_SIZE ) + { + MsgDev( D_ERROR, "Stream_OpenMPG: %s is probably corrupted\n", filename ); + FS_Close( file ); + return NULL; + } + // at this point we have valid stream stream = Mem_Alloc( host.soundpool, sizeof( stream_t )); stream->file = file; - mpegFile = Mem_Alloc( host.soundpool, sizeof( mpegfile_t )); + mpegFile = Mem_Alloc( host.soundpool, sizeof( mpeg_t )); - mad_synth_init( &mpegFile->synth ); - mad_stream_init( &mpegFile->stream ); - mad_frame_init( &mpegFile->frame ); - - if( mpeg_read( file, mpegFile ) == 0 ) + // couldn't create decoder + if( !create_decoder( mpegFile )) { - MsgDev( D_ERROR, "Stream_OpenMPG: couldn't open %s\n", filename ); - mad_stream_finish( &mpegFile->stream ); - mad_frame_finish( &mpegFile->frame ); + MsgDev( D_ERROR, "Stream_OpenMPG: couldn't create decoder\n" ); + Mem_Free( mpegFile ); + Mem_Free( stream ); + FS_Close( file ); + return NULL; + } + + read_len = FS_Read( file, tempbuff, sizeof( tempbuff )); + if( read_len < sizeof( tempbuff )) + { + MsgDev( D_ERROR, "Stream_OpenMPG: %s is probably corrupted\n", filename ); + close_decoder( mpegFile ); + Mem_Free( mpegFile ); + Mem_Free( stream ); + FS_Close( file ); + return NULL; + } + + // trying to read header + if( !read_mpeg_header( mpegFile, tempbuff, sizeof( tempbuff ), filesize )) + { + MsgDev( D_ERROR, "Sound_LoadMPG: (%s) is probably corrupted\n", filename ); + close_decoder( mpegFile ); Mem_Free( mpegFile ); Mem_Free( stream ); FS_Close( file ); @@ -378,19 +192,12 @@ stream_t *Stream_OpenMPG( const char *filename ) } stream->pos = 0; // how many samples left from previous frame - stream->channels = ( mpegFile->frame.header.mode == MODE_SINGLE_CHANNEL ) ? 1 : 2; - stream->rate = mpegFile->frame.header.samplerate; + stream->channels = mpegFile->channels; + stream->rate = mpegFile->rate; stream->width = 2; // always 16 bit stream->ptr = mpegFile; stream->type = WF_MPGDATA; - // g-cont: there is a stupid way... - if( stream->rate > 44100 ) - { - mpegFile->stream.options = 0x0002; - stream->rate /= 2; - } - return stream; } @@ -401,52 +208,49 @@ Stream_ReadMPG assume stream is valid ================= */ -long Stream_ReadMPG( stream_t *stream, long bytes, void *buffer ) +long Stream_ReadMPG( stream_t *stream, long needBytes, void *buffer ) { // buffer handling - int bytesRead = 0; - mpegfile_t *mpg; + int bytesWritten = 0; + mpeg_t *mpg; - mpg = (mpegfile_t *)stream->ptr; + mpg = (mpeg_t *)stream->ptr; ASSERT( mpg != NULL ); while( 1 ) { - pcm_t *wav; - word *data; - int i; + char tempbuff[FRAME_SIZE]; + long read_len, outsize; + byte *data; if( !stream->pos ) { - // if there are no bytes remainig so we can synth new frame - mad_synth_frame( &mpg->synth, &mpg->frame ); - } - wav = &mpg->synth.pcm; - data = (word *)((byte *)buffer + bytesRead); - - for( i = stream->pos; i < wav->length; i++ ) - { - if( stream->channels == 2 ) + if( read_mpeg_stream( mpg, NULL, 0 ) != MP3_OK ) { - *data++ = mpeg_scale( wav->samples[0][i] ); - *data++ = mpeg_scale( wav->samples[1][i] ); - } - else - { - *data++ = mpeg_scale( wav->samples[0][i] ); - } - bytesRead += ( stream->width * stream->channels ); - - if( bytesRead >= bytes ) - { - // continue from this sample on a next call - stream->pos = i; - return bytesRead; + // if there are no bytes remainig so we can decompress the new frame + read_len = FS_Read( stream->file, tempbuff, sizeof( tempbuff )); + if( read_mpeg_stream( mpg, tempbuff, read_len ) != MP3_OK ) + break; // there was end of the stream } } - stream->pos = 0; // no bytes remainig - if( !mpeg_read( stream->file, mpg )) break; + // check remaining size + if( bytesWritten + mpg->outsize > needBytes ) + outsize = ( needBytes - bytesWritten ); + else outsize = mpg->outsize; + + // copy raw sample to output buffer + data = (byte *)buffer + bytesWritten; + Q_memcpy( data, &mpg->out[stream->pos], outsize ); + bytesWritten += outsize; + mpg->outsize -= outsize; + stream->pos += outsize; + + // continue from this sample on a next call + if( bytesWritten >= needBytes ) + return bytesWritten; + + stream->pos = 0; // no bytes remaining } return 0; } @@ -462,12 +266,10 @@ void Stream_FreeMPG( stream_t *stream ) { if( stream->ptr ) { - mpegfile_t *mpg; + mpeg_t *mpg; - mpg = (mpegfile_t *)stream->ptr; - - mad_stream_finish( &mpg->stream ); - mad_frame_finish( &mpg->frame ); + mpg = (mpeg_t *)stream->ptr; + close_decoder( mpg ); Mem_Free( stream->ptr ); } diff --git a/engine/common/soundlib/snd_mp3.old b/engine/common/soundlib/snd_mp3.old new file mode 100644 index 00000000..0b1eae0b --- /dev/null +++ b/engine/common/soundlib/snd_mp3.old @@ -0,0 +1,480 @@ +/* +snd_mp3.c - mp3 format loading and streaming +Copyright (C) 2010 Uncle Mike + +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 3 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. +*/ + +#include "soundlib.h" + +/* +======================================================================= + LIBMAD DEFINITION +======================================================================= +*/ +#define BUFFER_GUARD 8 +#define BUFFER_MDLEN (511 + 2048 + BUFFER_GUARD) +#define BUFFER_SIZE 4096 // must be large than BUFFER_MDLEN + +#define MPEG_F_FRACBITS 28 +#define MPEG_F( x ) ((int)( x##L )) +#define MPEG_F_ONE MPEG_F( 0x10000000 ) + +enum +{ + MP3_ERROR_NONE = 0x0000, // no error + MP3_ERROR_BUFLEN = 0x0001, // input buffer too small (or EOF) + MP3_ERROR_BUFPTR = 0x0002, // invalid (null) buffer pointer + MP3_ERROR_NOMEM = 0x0031, // not enough memory + MP3_ERROR_LOSTSYNC = 0x0101, // lost synchronization + MP3_ERROR_BADLAYER = 0x0102, // reserved header layer value + MP3_ERROR_BADBITRATE = 0x0103, // forbidden bitrate value + MP3_ERROR_BADSAMPLERATE = 0x0104, // reserved sample frequency value + MP3_ERROR_BADEMPHASIS = 0x0105, // reserved emphasis value + MP3_ERROR_BADCRC = 0x0201, // CRC check failed + MP3_ERROR_BADBITALLOC = 0x0211, // forbidden bit allocation value + MP3_ERROR_BADSCALEFACTOR = 0x0221, // bad scalefactor index + MP3_ERROR_BADMODE = 0x0222, // bad bitrate/mode combination + MP3_ERROR_BADFRAMELEN = 0x0231, // bad frame length + MP3_ERROR_BADBIGVALUES = 0x0232, // bad big_values count + MP3_ERROR_BADBLOCKTYPE = 0x0233, // reserved block_type + MP3_ERROR_BADSCFSI = 0x0234, // bad scalefactor selection info + MP3_ERROR_BADDATAPTR = 0x0235, // bad main_data_begin pointer + MP3_ERROR_BADPART3LEN = 0x0236, // bad audio data length + MP3_ERROR_BADHUFFTABLE = 0x0237, // bad Huffman table select + MP3_ERROR_BADHUFFDATA = 0x0238, // Huffman data overrun + MP3_ERROR_BADSTEREO = 0x0239 // incompatible block_type for JS +}; + +enum +{ + MODE_SINGLE_CHANNEL = 0, // single channel + MODE_DUAL_CHANNEL, // dual channel + MODE_JOINT_STEREO, // joint (MS/intensity) stereo + MODE_STEREO // normal LR stereo +}; + +typedef struct +{ + uint samplerate; // sampling frequency (Hz) + word channels; // number of channels + word length; // number of samples per channel + int samples[2][1152]; // PCM output samples [ch][sample] +} pcm_t; + +typedef struct +{ + int filter[2][2][2][16][8]; // polyphase filterbank outputs + uint phase; // current processing phase + pcm_t pcm; // PCM output +} synth_t; + +typedef struct +{ + const byte *byte; + word cache; + word left; +} bitptr_t; + +typedef struct +{ + long seconds; // whole seconds + dword fraction; // 1 / TIMER_RESOLUTION seconds +} mp3_timer_t; + +typedef struct +{ + int layer; // audio layer (1, 2, or 3) + int mode; // channel mode (see above) + int mode_extension; // additional mode info + int emphasis; // de-emphasis to use (see above) + + dword bitrate; // stream bitrate (bps) + uint samplerate; // sampling frequency (Hz) + + word crc_check; // frame CRC accumulator + word crc_target; // final target CRC checksum + + int flags; // flags (see below) + int private_bits; // private bits (see below) + mp3_timer_t duration; // audio playing time of frame +} mp3_header_t; + +typedef struct +{ + mp3_header_t header; // MPEG audio header + int options; // decoding options (from stream) + + int sbsample[2][36][32]; // synthesis subband filter samples + int (*overlap)[2][32][18]; // Layer III block overlap data +} mp3_frame_t; + +typedef struct +{ + const byte *buffer; // input bitstream buffer + const byte *bufend; // end of buffer + dword skiplen; // bytes to skip before next frame + + int sync; // stream sync found + dword freerate; // free bitrate (fixed) + + const byte *this_frame; // start of current frame + const byte *next_frame; // start of next frame + bitptr_t ptr; // current processing bit pointer + + bitptr_t anc_ptr; // ancillary bits pointer + uint anc_bitlen; // number of ancillary bits + + byte (*data)[BUFFER_MDLEN]; + // Layer III data() + uint md_len; // bytes in data + + int options; // decoding options + int error; // error code +} mp3_stream_t; + +typedef struct +{ + synth_t synth; + mp3_stream_t stream; + mp3_frame_t frame; + int buffer_length; // for reading + byte buffer[BUFFER_SIZE];// frame buffer +} mpegfile_t; + +// libmad exports +extern void mad_synth_init( synth_t* ); +extern void mad_synth_frame( synth_t*, const mp3_frame_t* ); +extern void mad_stream_init( mp3_stream_t* ); +extern void mad_stream_buffer( mp3_stream_t*, const byte*, dword ); +extern void mad_stream_finish( mp3_stream_t* ); +extern void mad_frame_init( mp3_frame_t* ); +extern int mad_frame_decode( mp3_frame_t*, mp3_stream_t* ); +extern void mad_frame_finish( mp3_frame_t* ); + + +/* +================================================================= + + MPEG decompression + +================================================================= +*/ +static int mpeg_read( file_t *file, mpegfile_t *mpeg ) +{ + int ret; + + while( 1 ) + { + ret = FS_Read( file, &mpeg->buffer[mpeg->buffer_length], BUFFER_SIZE - mpeg->buffer_length ); + + // no more bytes are left + if( ret <= 0 ) break; + + mpeg->buffer_length += ret; + + while( 1 ) + { + mad_stream_buffer( &mpeg->stream, mpeg->buffer, mpeg->buffer_length ); + ret = mad_frame_decode( &mpeg->frame, &mpeg->stream ); + + if( mpeg->stream.next_frame ) + { + int length; + + length = mpeg->buffer + mpeg->buffer_length - mpeg->stream.next_frame; + memmove( mpeg->buffer, mpeg->stream.next_frame, length ); + mpeg->buffer_length = length; + } + + if( !ret ) return 1; + if( mpeg->stream.error == MP3_ERROR_BUFLEN ) + break; + } + } + return 0; +} + +static int mpeg_read_mem( const byte *buffer, int *pos, size_t filesize, mpegfile_t *mpeg ) +{ + int ret, readSize; + + while( 1 ) + { + readSize = ( BUFFER_SIZE - mpeg->buffer_length ); + + if(( *pos + readSize ) > filesize ) + readSize = ( filesize - *pos ); + Q_memcpy( &mpeg->buffer[mpeg->buffer_length], buffer + *pos, readSize ); + + // no more bytes are left + if( readSize <= 0 ) break; + *pos += readSize; + mpeg->buffer_length += readSize; + + while( 1 ) + { + mad_stream_buffer( &mpeg->stream, mpeg->buffer, mpeg->buffer_length ); + ret = mad_frame_decode( &mpeg->frame, &mpeg->stream ); + + if( mpeg->stream.next_frame ) + { + int length; + + length = mpeg->buffer + mpeg->buffer_length - mpeg->stream.next_frame; + memmove( mpeg->buffer, mpeg->stream.next_frame, length ); + mpeg->buffer_length = length; + } + + if( !ret ) return 1; + if( mpeg->stream.error == MP3_ERROR_BUFLEN ) + break; + } + } + return 0; +} + +static int mpeg_scale( int sample ) +{ + sample += (1 << ( MPEG_F_FRACBITS - 16 )); + + if( sample >= MPEG_F_ONE ) sample = MPEG_F_ONE - 1; + else if( sample < -MPEG_F_ONE ) sample = -MPEG_F_ONE; + + return sample >> ( MPEG_F_FRACBITS + 1 - 16 ); +} + +static int mpeg_size( mp3_frame_t *frame, long bytes ) +{ + return bytes * 8 / frame->header.bitrate * sound.channels * sound.rate * sound.width; +} + + +/* +================================================================= + + MPEG decompression + +================================================================= +*/ +qboolean Sound_LoadMPG( const char *name, const byte *buffer, size_t filesize ) +{ + mpegfile_t mpeg; + size_t pos = 0; + size_t bytesWrite = 0; + + // load the file + if( !buffer || filesize <= 0 ) + return false; + + Q_memset( &mpeg, 0, sizeof( mpeg )); + mad_synth_init( &mpeg.synth ); + mad_stream_init( &mpeg.stream ); + mad_frame_init( &mpeg.frame ); + + if( mpeg_read_mem( buffer, &pos, filesize, &mpeg ) == 0 ) + { + MsgDev( D_ERROR, "Sound_LoadMPG: (%s) is probably corrupted\n", name ); + mad_stream_finish( &mpeg.stream ); + mad_frame_finish( &mpeg.frame ); + return false; + } + + sound.channels = ( mpeg.frame.header.mode == MODE_SINGLE_CHANNEL ) ? 1 : 2; + sound.rate = mpeg.frame.header.samplerate; + sound.width = 2; // always 16-bit PCM + sound.loopstart = -1; + sound.size = mpeg_size( &mpeg.frame, filesize ); + + if( !sound.size ) + { + // bad ogg file + MsgDev( D_ERROR, "Sound_LoadMPG: (%s) is probably corrupted\n", name ); + mad_stream_finish( &mpeg.stream ); + mad_frame_finish( &mpeg.frame ); + return false; + } + + sound.type = WF_PCMDATA; + sound.wav = (byte *)Mem_Alloc( host.soundpool, sound.size ); + + // decompress mpg into pcm wav format + while( bytesWrite < sound.size ) + { + word *data; + int i; + + mad_synth_frame( &mpeg.synth, &mpeg.frame ); + data = (short *)(sound.wav + bytesWrite); + + for( i = 0; i < mpeg.synth.pcm.length; i++ ) + { + if( sound.channels == 2 ) + { + *data++ = mpeg_scale( mpeg.synth.pcm.samples[0][i] ); + *data++ = mpeg_scale( mpeg.synth.pcm.samples[1][i] ); + } + else + { + *data++ = mpeg_scale( mpeg.synth.pcm.samples[0][i] ); + } + + bytesWrite += ( sound.width * sound.channels ); + if( bytesWrite >= sound.size ) break; + } + + if( !mpeg_read_mem( buffer, &pos, filesize, &mpeg )) + break; + } + + sound.samples = bytesWrite / ( sound.width * sound.channels ); + mad_stream_finish( &mpeg.stream ); + mad_frame_finish( &mpeg.frame ); + + return true; +} + +/* +================= +Stream_OpenMPG +================= +*/ +stream_t *Stream_OpenMPG( const char *filename ) +{ + mpegfile_t *mpegFile; + stream_t *stream; + file_t *file; + + file = FS_Open( filename, "rb", false ); + if( !file ) return NULL; + + // at this point we have valid stream + stream = Mem_Alloc( host.soundpool, sizeof( stream_t )); + stream->file = file; + + mpegFile = Mem_Alloc( host.soundpool, sizeof( mpegfile_t )); + + mad_synth_init( &mpegFile->synth ); + mad_stream_init( &mpegFile->stream ); + mad_frame_init( &mpegFile->frame ); + + if( mpeg_read( file, mpegFile ) == 0 ) + { + MsgDev( D_ERROR, "Stream_OpenMPG: couldn't open %s\n", filename ); + mad_stream_finish( &mpegFile->stream ); + mad_frame_finish( &mpegFile->frame ); + Mem_Free( mpegFile ); + Mem_Free( stream ); + FS_Close( file ); + return NULL; + } + + stream->pos = 0; // how many samples left from previous frame + stream->channels = ( mpegFile->frame.header.mode == MODE_SINGLE_CHANNEL ) ? 1 : 2; + stream->rate = mpegFile->frame.header.samplerate; + stream->width = 2; // always 16 bit + stream->ptr = mpegFile; + stream->type = WF_MPGDATA; + + // g-cont: there is a stupid way... + if( stream->rate > 44100 ) + { + mpegFile->stream.options = 0x0002; + stream->rate /= 2; + } + + return stream; +} + +/* +================= +Stream_ReadMPG + +assume stream is valid +================= +*/ +long Stream_ReadMPG( stream_t *stream, long bytes, void *buffer ) +{ + // buffer handling + int bytesRead = 0; + mpegfile_t *mpg; + + mpg = (mpegfile_t *)stream->ptr; + ASSERT( mpg != NULL ); + + while( 1 ) + { + pcm_t *wav; + word *data; + int i; + + if( !stream->pos ) + { + // if there are no bytes remainig so we can synth new frame + mad_synth_frame( &mpg->synth, &mpg->frame ); + } + wav = &mpg->synth.pcm; + data = (word *)((byte *)buffer + bytesRead); + + for( i = stream->pos; i < wav->length; i++ ) + { + if( stream->channels == 2 ) + { + *data++ = mpeg_scale( wav->samples[0][i] ); + *data++ = mpeg_scale( wav->samples[1][i] ); + } + else + { + *data++ = mpeg_scale( wav->samples[0][i] ); + } + bytesRead += ( stream->width * stream->channels ); + + if( bytesRead >= bytes ) + { + // continue from this sample on a next call + stream->pos = i; + return bytesRead; + } + } + + stream->pos = 0; // no bytes remainig + if( !mpeg_read( stream->file, mpg )) break; + } + return 0; +} + +/* +================= +Stream_FreeMPG + +assume stream is valid +================= +*/ +void Stream_FreeMPG( stream_t *stream ) +{ + if( stream->ptr ) + { + mpegfile_t *mpg; + + mpg = (mpegfile_t *)stream->ptr; + + mad_stream_finish( &mpg->stream ); + mad_frame_finish( &mpg->frame ); + Mem_Free( stream->ptr ); + } + + if( stream->file ) + { + FS_Close( stream->file ); + } + + Mem_Free( stream ); +} \ No newline at end of file diff --git a/engine/common/soundlib/snd_wav.c b/engine/common/soundlib/snd_wav.c index afe5b86e..25cdca39 100644 --- a/engine/common/soundlib/snd_wav.c +++ b/engine/common/soundlib/snd_wav.c @@ -146,7 +146,7 @@ qboolean Sound_LoadWAV( const char *name, const byte *buffer, size_t filesize ) iff_data = buffer; iff_end = buffer + filesize; - // dind "RIFF" chunk + // find "RIFF" chunk FindChunk( "RIFF" ); if( !( iff_dataPtr && !Q_strncmp( iff_dataPtr + 8, "WAVE", 4 ))) { diff --git a/engine/eiface.h b/engine/eiface.h index 4ab78b66..f98a907f 100644 --- a/engine/eiface.h +++ b/engine/eiface.h @@ -259,6 +259,20 @@ typedef struct enginefuncs_s qboolean (*pfnVoice_SetClientListening)(int iReceiver, int iSender, qboolean bListen); const char *(*pfnGetPlayerAuthId) ( edict_t *e ); + + void *(*pfnSequenceGet)( const char *fileName, const char *entryName ); + void *(*pfnSequencePickSentence)( const char *groupName, int pickMethod, int *picked ); + int (*pfnGetFileSize)( char *filename ); + unsigned int (*pfnGetApproxWavePlayLen)( const char *filepath ); + int (*pfnIsCareerMatch)( void ); + int (*pfnGetLocalizedStringLength)( const char *label ); + void (*pfnRegisterTutorMessageShown)( int mid ); + int (*pfnGetTimesTutorMessageShown)( int mid ); + void (*pfnProcessTutorMessageDecayBuffer)( int *buffer, int bufferLength ); + void (*pfnConstructTutorMessageDecayBuffer)( int *buffer, int bufferLength ); + void (*pfnResetTutorMessageDecayData)( void ); + void (*pfnQueryClientCvarValue)( const edict_t *player, const char *cvarName ); + void (*pfnQueryClientCvarValue2)( const edict_t *player, const char *cvarName, int requestID ); } enginefuncs_t; // ONLY ADD NEW FUNCTIONS TO THE END OF THIS STRUCT. INTERFACE VERSION IS FROZEN AT 138 @@ -476,8 +490,8 @@ typedef struct void (*pfnOnFreeEntPrivateData)( edict_t *pEnt ); void (*pfnGameShutdown)(void); int (*pfnShouldCollide)( edict_t *pentTouched, edict_t *pentOther ); - int (*pfnCreate)( edict_t *pent, const char *szName ); // passed through pfnCreate (0 is attempt to create, -1 is reject) - int (*pfnPhysicsEntity)( edict_t *pEntity ); // run custom physics for each entity (return 0 to use engine physic) + void (*pfnCvarValue)( const edict_t *pEnt, const char *value ); + void (*pfnCvarValue2)( const edict_t *pEnt, int requestID, const char *cvarName, const char *value ); } NEW_DLL_FUNCTIONS; typedef int (*NEW_DLL_FUNCTIONS_FN)( NEW_DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion ); diff --git a/engine/physint.h b/engine/physint.h new file mode 100644 index 00000000..818a7d8b --- /dev/null +++ b/engine/physint.h @@ -0,0 +1,38 @@ +/* +physint.h - Server Physics Interface +Copyright (C) 2011 Uncle Mike + +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 3 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. +*/ + +#ifndef PHYSINT_H +#define PHYSINT_H + +#define SV_PHYSICS_INTERFACE_VERSION 1 + +typedef struct server_physics_api_s +{ + // unlink edict from old position and link onto new + void ( *pfnLinkEdict) ( edict_t *ent, qboolean touch_triggers ); + double ( *pfnGetServerTime )( void ); // unclamped +} server_physics_api_t; + +// physic callbacks +typedef struct physics_interface_s +{ + int version; + // passed through pfnCreate (0 is attempt to create, -1 is reject) + int ( *SV_CreateEntity )( edict_t *pent, const char *szName ); + // run custom physics for each entity (return 0 to use built-in engine physic) + int ( *SV_PhysicsEntity )( edict_t *pEntity ); +} physics_interface_t; + +#endif//PHYSINT_H \ No newline at end of file diff --git a/engine/server/server.h b/engine/server/server.h index 28b5fac9..b6b4d78e 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -19,6 +19,7 @@ GNU General Public License for more details. #include "mathlib.h" #include "edict.h" #include "eiface.h" +#include "physint.h" // physics interface #include "mod_local.h" #include "pm_defs.h" #include "pm_movevars.h" @@ -29,7 +30,6 @@ GNU General Public License for more details. #include "world.h" //============================================================================= -#define MAX_MASTERS 8 // max recipients for heartbeat packets #define SV_UPDATE_MASK (SV_UPDATE_BACKUP - 1) extern int SV_UPDATE_BACKUP; @@ -105,6 +105,9 @@ typedef struct server_s string name; // map name string startspot; // player_start name on nextmap + double lastchecktime; + int lastcheck; // number of last checked client + char model_precache[MAX_MODELS][CS_SIZE]; char sound_precache[MAX_SOUNDS][CS_SIZE]; char files_precache[MAX_CUSTOM][CS_SIZE]; @@ -322,6 +325,7 @@ typedef struct globalvars_t *globals; // server globals DLL_FUNCTIONS dllFuncs; // dll exported funcs NEW_DLL_FUNCTIONS dllFuncs2; // new dll exported funcs (can be NULL) + physics_interface_t physFuncs; // physics interface functions (Xash3D extension) byte *mempool; // server premamnent pool: edicts etc byte *stringspool; // for shared strings @@ -353,7 +357,6 @@ typedef struct //============================================================================= -extern netadr_t master_adr[MAX_MASTERS]; // address of the master server extern server_static_t svs; // persistant server info extern server_t sv; // local server extern svgame_static_t svgame; // persistant game info @@ -396,6 +399,7 @@ extern convar_t *sv_send_resources; extern convar_t *sv_send_logos; extern convar_t *sv_sendvelocity; extern convar_t *mp_consistency; +extern convar_t *public_server; extern convar_t *physinfo; //=========================================================== @@ -415,6 +419,9 @@ void SV_InitOperatorCommands( void ); void SV_KillOperatorCommands( void ); void SV_UserinfoChanged( sv_client_t *cl, const char *userinfo ); void SV_PrepWorldFrame( void ); +void SV_ProcessFile( sv_client_t *cl, char *filename ); +void SV_SendResourceList( sv_client_t *cl ); +void Master_Add( void ); void Master_Heartbeat( void ); void Master_Packet( void ); @@ -431,6 +438,7 @@ qboolean SV_SpawnServer( const char *server, const char *startspot ); // sv_phys.c // void SV_Physics( void ); +qboolean SV_InitPhysicsAPI( void ); void SV_CheckVelocity( edict_t *ent ); qboolean SV_CheckWater( edict_t *ent ); qboolean SV_RunThink( edict_t *ent ); diff --git a/engine/server/sv_client.c b/engine/server/sv_client.c index c133b78a..17edc32d 100644 --- a/engine/server/sv_client.c +++ b/engine/server/sv_client.c @@ -933,7 +933,7 @@ void SV_PutClientInServer( edict_t *ent ) return; } - // enable dev-mode to prevent crash cheat-protecting from invasion + // enable dev-mode to prevent crash cheat-protecting from Invasion mod if( ent->v.flags & (FL_GODMODE|FL_NOTARGET) && !Q_stricmp( GI->gamefolder, "invasion" )) SV_ExecuteClientCommand( client, "test\n" ); @@ -943,6 +943,7 @@ void SV_PutClientInServer( edict_t *ent ) BF_WriteByte( &client->netchan.message, svc_setangle ); BF_WriteBitAngle( &client->netchan.message, ent->v.angles[0], 16 ); BF_WriteBitAngle( &client->netchan.message, ent->v.angles[1], 16 ); + BF_WriteBitAngle( &client->netchan.message, ent->v.angles[2], 16 ); ent->v.fixangle = 0; } ent->v.effects |= EF_NOINTERP; @@ -1054,14 +1055,111 @@ void SV_New_f( sv_client_t *cl ) // set up the entity for the client ent = EDICT_NUM( playernum + 1 ); cl->edict = ent; - Q_memset( &cl->lastcmd, 0, sizeof( cl->lastcmd )); - // begin fetching modellist - BF_WriteByte( &cl->netchan.message, svc_stufftext ); - BF_WriteString( &cl->netchan.message, va( "cmd modellist %i %i\n", svs.spawncount, 0 )); + if( sv_maxclients->integer == 1 ) + { + Q_memset( &cl->lastcmd, 0, sizeof( cl->lastcmd )); + + // begin fetching modellist + BF_WriteByte( &cl->netchan.message, svc_stufftext ); + BF_WriteString( &cl->netchan.message, va( "cmd modellist %i %i\n", svs.spawncount, 0 )); + } + else + { + // request resource list + BF_WriteByte( &cl->netchan.message, svc_stufftext ); + BF_WriteString( &cl->netchan.message, va( "cmd getresourelist\n" )); + } } } +/* +================== +SV_ContinueLoading_f +================== +*/ +void SV_ContinueLoading_f( sv_client_t *cl ) +{ + if( cl->state != cs_connected ) + { + MsgDev( D_INFO, "continueloading is not valid from the console\n" ); + return; + } + + Q_memset( &cl->lastcmd, 0, sizeof( cl->lastcmd )); + + // begin fetching modellist + BF_WriteByte( &cl->netchan.message, svc_stufftext ); + BF_WriteString( &cl->netchan.message, va( "cmd modellist %i %i\n", svs.spawncount, 0 )); +} + +/* +======================= +SV_SendResourceList + +NOTE: Sending the list of cached resources. +g-cont. this is fucking big message!!! i've rewriting this code +======================= +*/ +void SV_SendResourceList_f( sv_client_t *cl ) +{ + int index = 0; + int rescount = 0; + resourcelist_t reslist; + size_t msg_size; + + Q_memset( &reslist, 0, sizeof( resourcelist_t )); + + reslist.restype[rescount] = t_world; // terminator + Q_strcpy( reslist.resnames[rescount], "NULL" ); + rescount++; + + for( index = 1; index < MAX_MODELS && sv.model_precache[index][0]; index++ ) + { + if( sv.model_precache[index][0] == '*' ) // internal bmodel + continue; + + reslist.restype[rescount] = t_model; + Q_strcpy( reslist.resnames[rescount], sv.model_precache[index] ); + rescount++; + } + + for( index = 1; index < MAX_SOUNDS && sv.sound_precache[index][0]; index++ ) + { + reslist.restype[rescount] = t_sound; + Q_strcpy( reslist.resnames[rescount], sv.sound_precache[index] ); + rescount++; + } + + for( index = 1; index < MAX_EVENTS && sv.event_precache[index][0]; index++ ) + { + reslist.restype[rescount] = t_eventscript; + Q_strcpy( reslist.resnames[rescount], sv.event_precache[index] ); + rescount++; + } + + for( index = 1; index < MAX_CUSTOM && sv.files_precache[index][0]; index++ ) + { + reslist.restype[rescount] = t_generic; + Q_strcpy( reslist.resnames[rescount], sv.files_precache[index] ); + rescount++; + } + + msg_size = BF_GetRealBytesWritten( &cl->netchan.message ); // start + + BF_WriteByte( &cl->netchan.message, svc_resourcelist ); + BF_WriteWord( &cl->netchan.message, rescount ); + + for( index = 1; index < rescount; index++ ) + { + BF_WriteWord( &cl->netchan.message, reslist.restype[index] ); + BF_WriteString( &cl->netchan.message, reslist.resnames[index] ); + } + + Msg( "Count res: %d\n", rescount ); + Msg( "ResList size: %s\n", Q_memprint( BF_GetRealBytesWritten( &cl->netchan.message ) - msg_size )); +} + /* ================== SV_WriteModels_f @@ -1692,6 +1790,8 @@ ucmd_t ucmds[] = { "usermsgs", SV_UserMessages_f }, { "userinfo", SV_UpdateUserinfo_f }, { "lightstyles", SV_WriteLightstyles_f }, +{ "getresourelist", SV_SendResourceList_f }, +{ "continueloading", SV_ContinueLoading_f }, { NULL, NULL } }; @@ -1741,6 +1841,10 @@ void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg ) char *args; char *c, buf[MAX_SYSPATH]; int len = sizeof( buf ); + dword challenge; + int index, count = 0; + char query[512]; + word port; BF_Clear( msg ); BF_ReadLong( msg );// skip the -1 marker @@ -1758,6 +1862,25 @@ void SV_ConnectionlessPacket( netadr_t from, sizebuf_t *msg ) else if( !Q_strcmp( c, "getchallenge" )) SV_GetChallenge( from ); else if( !Q_strcmp( c, "connect" )) SV_DirectConnect( from ); else if( !Q_strcmp( c, "rcon" )) SV_RemoteCommand( from, msg ); + else if( msg->pData[0] == 0xFF && msg->pData[1] == 0xFF && msg->pData[2] == 0xFF && msg->pData[3] == 0xFF && msg->pData[4] == 0x4E && msg->pData[5] == 0x0A ) + { + challenge = *(dword *)&msg->pData[6]; + + port = Cvar_Get( "ip_hostport", "0", CVAR_INIT, "network server port" )->integer; + if( !port ) port = Cvar_Get( "port", va( "%i", PORT_SERVER ), CVAR_INIT, "network default port" )->integer; + + for( index = 0; index < sv_maxclients->integer; index++ ) + { + if( svs.clients[index].state >= cs_connected ) + count++; + } + + Q_snprintf( query, sizeof( query ), + "0\n\\protocol\\7\\challenge\\%ld\\players\\%d\\max\\%d\\bots\\0\\gamedir\\%s_xash\\map\\%s\\password\\0\\os\\w\\lan\\0\\region\\255\\gameport\\%d\\specport\\27015\\dedicated\\1\\appid\\70\\type\\d\\secure\\0\\version\\1.1.2.1\\product\\valve\n", + challenge, count, sv_maxclients->integer, GI->gamefolder, sv.name, port ); + + NET_SendPacket( NS_SERVER, Q_strlen( query ), query, from ); + } else if( svgame.dllFuncs.pfnConnectionlessPacket( &from, args, buf, &len )) { // user out of band message (must be handled in CL_ConnectionlessPacket) @@ -1903,6 +2026,19 @@ static void SV_ParseClientMove( sv_client_t *cl, sizebuf_t *msg ) player->v.animtime = sv.time + host.frametime; } +/* +=================== +SV_ParseResourceList + +Parse resource list +=================== +*/ +void SV_ParseResourceList( sv_client_t *cl, sizebuf_t *msg ) +{ + Netchan_CreateFileFragments( true, &cl->netchan, BF_ReadString( msg )); + Netchan_FragSend( &cl->netchan ); +} + /* =================== SV_ExecuteClientMessage @@ -1976,6 +2112,9 @@ void SV_ExecuteClientMessage( sv_client_t *cl, sizebuf_t *msg ) if( ++stringCmdCount < 8 ) SV_ExecuteClientCommand( cl, s ); if( cl->state == cs_zombie ) return; // disconnect command break; + case clc_resourcelist: + SV_ParseResourceList( cl, msg ); + break; default: MsgDev( D_ERROR, "SV_ReadClientMessage: clc_bad\n" ); SV_DropClient( cl ); diff --git a/engine/server/sv_cmds.c b/engine/server/sv_cmds.c index 8f295eeb..2c30ed94 100644 --- a/engine/server/sv_cmds.c +++ b/engine/server/sv_cmds.c @@ -96,51 +96,6 @@ void SV_BroadcastCommand( char *fmt, ... ) BF_WriteString( &sv.reliable_datagram, string ); } -/* -==================== -SV_SetMaster_f - -Specify a list of master servers -==================== -*/ -void SV_SetMaster_f( void ) -{ - int i, slot; - - // only dedicated servers send heartbeats - if( host.type != HOST_DEDICATED ) - { - Msg( "Only dedicated servers use masters.\n" ); - return; - } - - // make sure the server is listed public - Cvar_Set( "public", "1" ); - - for( i = 1; i < MAX_MASTERS; i++ ) - { - Q_memset( &master_adr[i], 0, sizeof( master_adr[i] )); - } - - // slot 0 will always contain the id master - for( i = 1, slot = 1; i < Cmd_Argc(); i++ ) - { - if( slot == MAX_MASTERS ) break; - if( !NET_StringToAdr( Cmd_Argv( i ), &master_adr[i] )) - { - Msg( "Bad address: %s\n", Cmd_Argv( i )); - continue; - } - - if( !master_adr[slot].port ) master_adr[slot].port = BF_BigShort( PORT_MASTER ); - Msg( "Master server at %s\n", NET_AdrToString( master_adr[slot] )); - Msg( "Sending a ping.\n" ); - Netchan_OutOfBandPrint( NS_SERVER, master_adr[slot], "ping" ); - slot++; - } - svs.last_heartbeat = MAX_HEARTBEAT; -} - /* ================== SV_SetPlayer @@ -832,7 +787,6 @@ void SV_InitOperatorCommands( void ) if( host.type == HOST_DEDICATED ) { Cmd_AddCommand( "say", SV_ConSay_f, "send a chat message to everyone on the server" ); - Cmd_AddCommand( "setmaster", SV_SetMaster_f, "set ip address for dedicated server" ); Cmd_AddCommand( "killserver", SV_KillServer_f, "shutdown current server" ); } diff --git a/engine/server/sv_frame.c b/engine/server/sv_frame.c index a00f1a3d..f8f0c515 100644 --- a/engine/server/sv_frame.c +++ b/engine/server/sv_frame.c @@ -381,6 +381,7 @@ void SV_WriteClientdataToMessage( sv_client_t *cl, sizebuf_t *msg ) BF_WriteByte( msg, svc_setangle ); BF_WriteBitAngle( msg, clent->v.angles[0], 16 ); BF_WriteBitAngle( msg, clent->v.angles[1], 16 ); + BF_WriteBitAngle( msg, clent->v.angles[2], 16 ); clent->v.effects |= EF_NOINTERP; break; case 2: diff --git a/engine/server/sv_game.c b/engine/server/sv_game.c index 5b899ebb..01782457 100644 --- a/engine/server/sv_game.c +++ b/engine/server/sv_game.c @@ -21,11 +21,10 @@ GNU General Public License for more details. #include "pm_defs.h" #include "const.h" -#define DEBUG_NEW_CLIENTPVS_CHECK - // fatpvs stuff static byte fatpvs[MAX_MAP_LEAFS/8]; static byte fatphs[MAX_MAP_LEAFS/8]; +static byte clientpvs[MAX_MAP_LEAFS/8]; // for find client in PVS static vec3_t viewPoint[MAX_CLIENTS]; static byte *bitvector; static int fatbytes; @@ -314,6 +313,10 @@ qboolean SV_Send( int dest, const vec3_t origin, const edict_t *ent ) clientnum = cl - svs.clients; viewOrg = viewPoint[clientnum]; + // Invasion issues: wrong camera position received in ENGINE_SET_PVS + if( cl->pViewEntity && !VectorCompare( viewOrg, cl->pViewEntity->v.origin )) + viewOrg = cl->pViewEntity->v.origin; + // -1 is because pvs rows are 1 based, not 0 based like leafs leafnum = Mod_PointLeafnum( viewOrg ) - 1; if( mask && (!(mask[leafnum>>3] & (1<<( leafnum & 7 ))))) @@ -766,7 +769,7 @@ edict_t* SV_AllocPrivateData( edict_t *ent, string_t className ) if( !SpawnEdict ) { // attempt to create custom entity (Xash3D extension) - if( svgame.dllFuncs2.pfnCreate && svgame.dllFuncs2.pfnCreate( ent, pszClassName ) != -1 ) + if( svgame.physFuncs.SV_CreateEntity && svgame.physFuncs.SV_CreateEntity( ent, pszClassName ) != -1 ) return ent; ent->v.flags |= FL_KILLME; @@ -1249,73 +1252,98 @@ edict_t *pfnFindEntityInSphere( edict_t *pStartEdict, const float *org, float fl return NULL; } +/* +================= +SV_CheckClientPVS + +build the new client PVS +================= +*/ +int SV_CheckClientPVS( int check ) +{ + byte *pvs; + edict_t *ent; + mleaf_t *leaf; + vec3_t view; + int i; + + // cycle to the next one + check = bound( 1, check, svgame.globals->maxClients ); + + if( check == svgame.globals->maxClients ) + i = 1; + else i = check + 1; + + for( ;; i++ ) + { + if( i == svgame.globals->maxClients + 1 ) + i = 1; + + ent = EDICT_NUM( i ); + + if( i == check ) break; // didn't find anything else + + if( ent->free ) continue; + if( !ent->pvPrivateData ) continue; + if( ent->v.flags & FL_NOTARGET ) continue; + + // anything that is a client, or has a client as an enemy + break; + } + + // get the PVS for the entity + VectorAdd( ent->v.origin, ent->v.view_ofs, view ); + leaf = Mod_PointInLeaf( view, sv.worldmodel->nodes ); + pvs = Mod_LeafPVS( leaf, sv.worldmodel ); + memcpy( clientpvs, pvs, (sv.worldmodel->numleafs + 7) >> 3 ); + + return i; +} + /* ================= pfnFindClientInPVS -FIXME: this code is totally wrong. Get PF_checkclient from QW. ================= */ edict_t* pfnFindClientInPVS( edict_t *pEdict ) { - edict_t *pClient; - sv_client_t *cl; - vec3_t view1, view2; - int i; + edict_t *pClient; + mleaf_t *leaf; + vec3_t view; + int i; if( !SV_IsValidEdict( pEdict )) return svgame.edicts; - VectorAdd( pEdict->v.origin, pEdict->v.view_ofs, view1 ); - - for( i = 0; i < svgame.globals->maxClients; i++ ) + // find a new check if on a new frame + if(( sv.time - sv.lastchecktime ) >= 0.1 ) { - pClient = EDICT_NUM( i + 1 ); - if(( cl = SV_ClientFromEdict( pClient, true )) == NULL ) - continue; - - // check for SET_VIEW - if( SV_IsValidEdict( cl->pViewEntity )) - VectorAdd( cl->pViewEntity->v.origin, cl->pViewEntity->v.view_ofs, view2 ); - else VectorAdd( pClient->v.origin, pClient->v.view_ofs, view2 ); - - if( pEdict->v.modelindex ) - { - // can use entity leafs or headnode for fast testing - // FIXME: this is need to be detail tested! - mleaf_t *leaf = Mod_PointInLeaf( view2, sv.worldmodel->nodes ); - byte *mask = Mod_LeafPVS( leaf, sv.worldmodel ); - - if( pfnCheckVisibility( pEdict, mask )) - { - return pClient; - } -#ifdef DEBUG_NEW_CLIENTPVS_CHECK - else if( sv_check_errors->integer ) - { - trace_t tr; - tr = SV_Move( view1, vec3_origin, vec3_origin, view2, MOVE_WORLDONLY, NULL ); - - if( tr.fraction == 1.0f && !tr.allsolid ) - { - MsgDev( D_ERROR, "CHECK_CLIENT_PVS: fail to see %s, probably client is underwater\n", SV_ClassName( pEdict )); - } - } -#endif - } - else - { - if( SV_OriginIn( DVIS_PVS, view1, view2 )) - return pClient; - } + sv.lastcheck = SV_CheckClientPVS( sv.lastcheck ); + sv.lastchecktime = sv.time; } - return svgame.edicts; + + // return check if it might be visible + pClient = EDICT_NUM( sv.lastcheck ); + if( !SV_ClientFromEdict( pClient, true )) + return svgame.edicts; + + VectorAdd( pEdict->v.origin, pEdict->v.view_ofs, view ); + leaf = Mod_PointInLeaf( view, sv.worldmodel->nodes ); + i = (leaf - sv.worldmodel->leafs) - 1; + + if( i < 0 || !((clientpvs[i>>3]) & (1 << (i & 7)))) + return svgame.edicts; + + // client which currently in PVS + return pClient; } /* ================= pfnEntitiesInPVS +FIXME: rewrite this code. get rid of hack ================= */ edict_t *pfnEntitiesInPVS( edict_t *pplayer ) @@ -1673,6 +1701,8 @@ void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float int msg_dest; vec3_t origin; + if( !sample ) return; + if( attn < ATTN_NONE || attn > ATTN_IDLE ) { MsgDev( D_ERROR, "SV_StartSound: attenuation %g must be in range 0-2\n", attn ); @@ -1781,6 +1811,8 @@ void pfnEmitAmbientSound( edict_t *ent, float *pos, const char *sample, float vo int msg_dest = MSG_PAS_R; vec3_t origin; + if( !sample ) return; + if( attn < ATTN_NONE || attn > ATTN_IDLE ) { MsgDev( D_ERROR, "SV_AmbientSound: attenuation must be in range 0-2\n" ); @@ -3282,6 +3314,9 @@ char *pfnGetInfoKeyBuffer( edict_t *e ) { sv_client_t *cl; + if( !SV_IsValidEdict( e )) + return Cvar_Serverinfo(); // otherwise return ServerInfo + cl = SV_ClientFromEdict( e, false ); // pfnUserInfoChanged passed if( cl == NULL ) { @@ -3947,6 +3982,150 @@ const char *pfnGetPlayerAuthId( edict_t *e ) return result; } + +/* +============= +pfnSequenceGet + +used by CS:CZ +============= +*/ +void *pfnSequenceGet( const char *fileName, const char *entryName ) +{ + return NULL; +} + +/* +============= +pfnSequencePickSentence + +used by CS:CZ +============= +*/ +void *pfnSequencePickSentence( const char *groupName, int pickMethod, int *picked ) +{ + return NULL; +} + +/* +============= +pfnGetFileSize + +returns the filesize in bytes +============= +*/ +int pfnGetFileSize( char *filename ) +{ + return FS_FileSize( filename, false ); +} + +/* +============= +pfnGetApproxWavePlayLen + +returns the wave length in samples +============= +*/ +uint pfnGetApproxWavePlayLen( const char *filepath ) +{ + return 0; +} + +/* +============= +pfnIsCareerMatch + +used by CS:CZ +============= +*/ +int pfnIsCareerMatch( void ) +{ + return 0; +} + +/* +============= +pfnGetLocalizedStringLength + +============= +*/ +int pfnGetLocalizedStringLength( const char *label ) +{ + return 0; +} + +/* +============= +pfnRegisterTutorMessageShown + +============= +*/ +void pfnRegisterTutorMessageShown( int mid ) +{ +} + +/* +============= +pfnGetTimesTutorMessageShown + +============= +*/ +int pfnGetTimesTutorMessageShown( int mid ) +{ + return 0; +} + +/* +============= +pfnProcessTutorMessageDecayBuffer + +============= +*/ +void pfnProcessTutorMessageDecayBuffer( int *buffer, int bufferLength ) +{ +} + +/* +============= +pfnConstructTutorMessageDecayBuffer + +============= +*/ +void pfnConstructTutorMessageDecayBuffer( int *buffer, int bufferLength ) +{ +} + +/* +============= +pfnSequenceGet + +============= +*/ +void pfnResetTutorMessageDecayData( void ) +{ +} + +/* +============= +pfnQueryClientCvarValue + +request client cvar value +============= +*/ +void pfnQueryClientCvarValue( const edict_t *player, const char *cvarName ) +{ +} + +/* +============= +pfnQueryClientCvarValue2 + +request client cvar value (bugfixed) +============= +*/ +void pfnQueryClientCvarValue2( const edict_t *player, const char *cvarName, int requestID ) +{ +} // engine callbacks static enginefuncs_t gEngfuncs = @@ -4095,6 +4274,19 @@ static enginefuncs_t gEngfuncs = pfnVoice_GetClientListening, pfnVoice_SetClientListening, pfnGetPlayerAuthId, + pfnSequenceGet, + pfnSequencePickSentence, + pfnGetFileSize, + pfnGetApproxWavePlayLen, + pfnIsCareerMatch, + pfnGetLocalizedStringLength, + pfnRegisterTutorMessageShown, + pfnGetTimesTutorMessageShown, + pfnProcessTutorMessageDecayBuffer, + pfnConstructTutorMessageDecayBuffer, + pfnResetTutorMessageDecayData, + pfnQueryClientCvarValue, + pfnQueryClientCvarValue2, }; /* @@ -4388,6 +4580,9 @@ qboolean SV_LoadProgs( const char *name ) // make sure what new dll functions is cleared Q_memset( &svgame.dllFuncs2, 0, sizeof( svgame.dllFuncs2 )); + // make sure what physic functions is cleared + Q_memset( &svgame.physFuncs, 0, sizeof( svgame.physFuncs )); + // make local copy of engfuncs to prevent overwrite it with bots.dll Q_memcpy( &gpEngfuncs, &gEngfuncs, sizeof( gpEngfuncs )); @@ -4395,7 +4590,7 @@ qboolean SV_LoadProgs( const char *name ) GetEntityAPI2 = (APIFUNCTION2)Com_GetProcAddress( svgame.hInstance, "GetEntityAPI2" ); GiveNewDllFuncs = (NEW_DLL_FUNCTIONS_FN)Com_GetProcAddress( svgame.hInstance, "GetNewDLLFunctions" ); - if( !GetEntityAPI ) + if( !GetEntityAPI && !GetEntityAPI2 ) { Com_FreeLibrary( svgame.hInstance ); MsgDev( D_NOTE, "SV_LoadProgs: failed to get address of GetEntityAPI proc\n" ); @@ -4430,22 +4625,29 @@ qboolean SV_LoadProgs( const char *name ) version = INTERFACE_VERSION; - if( !GetEntityAPI( &svgame.dllFuncs, version )) + if( GetEntityAPI2 ) { - if( !GetEntityAPI2 ) + if( !GetEntityAPI2( &svgame.dllFuncs, &version )) { - Com_FreeLibrary( svgame.hInstance ); - MsgDev( D_ERROR, "SV_LoadProgs: couldn't get entity API\n" ); - svgame.hInstance = NULL; - return false; - } - else if( !GetEntityAPI2( &svgame.dllFuncs, &version )) - { - Com_FreeLibrary( svgame.hInstance ); - MsgDev( D_ERROR, "SV_LoadProgs: interface version %i should be %i\n", INTERFACE_VERSION, version ); - svgame.hInstance = NULL; - return false; + MsgDev( D_WARN, "SV_LoadProgs: interface version %i should be %i\n", INTERFACE_VERSION, version ); + + // fallback to old API + if( !GetEntityAPI( &svgame.dllFuncs, version )) + { + Com_FreeLibrary( svgame.hInstance ); + MsgDev( D_ERROR, "SV_LoadProgs: couldn't get entity API\n" ); + svgame.hInstance = NULL; + return false; + } } + else MsgDev( D_AICONSOLE, "SV_LoadProgs: ^2initailized extended EntityAPI ^7ver. %i\n", version ); + } + else if( !GetEntityAPI( &svgame.dllFuncs, version )) + { + Com_FreeLibrary( svgame.hInstance ); + MsgDev( D_ERROR, "SV_LoadProgs: couldn't get entity API\n" ); + svgame.hInstance = NULL; + return false; } if( !SV_InitStudioAPI( )) @@ -4456,6 +4658,11 @@ qboolean SV_LoadProgs( const char *name ) return false; } + if( !SV_InitPhysicsAPI( )) + { + MsgDev( D_WARN, "SV_LoadProgs: couldn't get physics API\n" ); + } + // grab function SV_SaveGameComment SV_InitSaveRestore (); diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index 22f296bf..c351a672 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -337,6 +337,12 @@ void SV_ActivateServer( void ) sv.paused = false; Host_SetServerState( sv.state ); + + if( sv_maxclients->integer > 1 && public_server->integer ) + { + MsgDev( D_INFO, "Add your server, to master server list\n" ); + Master_Add( ); + } } /* @@ -540,7 +546,6 @@ A brand new game has been started */ void SV_InitGame( void ) { - string idmaster; edict_t *ent; int i; @@ -621,8 +626,6 @@ void SV_InitGame( void ) // heartbeats will always be sent to the id master svs.last_heartbeat = MAX_HEARTBEAT; // send immediately - Q_sprintf( idmaster, "192.246.40.37:%i", PORT_MASTER ); // TODO: parse woncomm.lst - NET_StringToAdr( idmaster, &master_adr[0] ); // set client fields on player ents for( i = 0; i < svgame.globals->maxClients; i++ ) diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index ef6752c3..7f9e6301 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -19,8 +19,6 @@ GNU General Public License for more details. #define HEARTBEAT_SECONDS 300.0f // 300 seconds -netadr_t master_adr[MAX_MASTERS]; // address of group servers - convar_t *sv_zmax; convar_t *sv_novis; // disable server culling entities by vis convar_t *sv_unlag; @@ -364,7 +362,7 @@ void SV_ReadPackets( void ) if( Netchan_CopyFileFragments( &cl->netchan, &net_message )) { -// SV_ProcessFile( cl, cl->netchan.incomingfilename ); + SV_ProcessFile( cl, cl->netchan.incomingfilename ); } } @@ -460,6 +458,17 @@ void SV_PrepWorldFrame( void ) } } +/* +================= +SV_ProcessFile +================= +*/ +void SV_ProcessFile( sv_client_t *cl, char *filename ) +{ + // some other file... + MsgDev( D_INFO, "Received file %s from %s\n", filename, cl->name ); +} + /* ================= SV_IsSimulating @@ -543,6 +552,23 @@ void Host_ServerFrame( void ) //============================================================================ +/* +================= +Master_Add +================= +*/ +void Master_Add( void ) +{ + netadr_t adr; + + NET_Config( true ); // allow remote + + if( !NET_StringToAdr( MASTERSERVER_ADR, &adr )) + MsgDev( D_INFO, "Can't resolve adr: %s\n", MASTERSERVER_ADR ); + + NET_SendPacket( NS_SERVER, 2, "\x4D\xFF", adr ); +} + /* ================ Master_Heartbeat @@ -553,11 +579,8 @@ let it know we are alive, and log information */ void Master_Heartbeat( void ) { - char *string; - int i; - - if( host.type != HOST_DEDICATED || !public_server->integer ) - return; // only dedicated servers send heartbeats + if( !public_server->integer || sv_maxclients->integer == 1 ) + return; // only public servers send heartbeats // check for time wraparound if( svs.last_heartbeat > host.realtime ) @@ -568,18 +591,7 @@ void Master_Heartbeat( void ) svs.last_heartbeat = host.realtime; - // send the same string that we would give for a status OOB command - string = SV_StatusString( ); - - // send to group master - for( i = 0; i < MAX_MASTERS; i++ ) - { - if( master_adr[i].port ) - { - MsgDev( D_INFO, "Sending heartbeat to %s\n", NET_AdrToString( master_adr[i] )); - Netchan_OutOfBandPrint( NS_SERVER, master_adr[i], "heartbeat\n%s", string ); - } - } + Master_Add(); } /* @@ -591,20 +603,6 @@ Informs all masters that this server is going down */ void Master_Shutdown( void ) { - int i; - - if( host.type != HOST_DEDICATED || !public_server->integer ) - return; // only dedicated servers send heartbeats - - // send to group master - for( i = 0; i < MAX_MASTERS; i++ ) - { - if( master_adr[i].port ) - { - if( i ) MsgDev( D_INFO, "Sending heartbeat to %s\n", NET_AdrToString( master_adr[i] )); - Netchan_OutOfBandPrint( NS_SERVER, master_adr[i], "shutdown" ); - } - } } //============================================================================ diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index 892f210a..e1b06f83 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -16,6 +16,9 @@ GNU General Public License for more details. #include "common.h" #include "server.h" #include "const.h" +#include "library.h" + +typedef int (*PHYSICAPI)( int, server_physics_api_t*, physics_interface_t* ); /* @@ -311,7 +314,7 @@ qboolean SV_CheckWater( edict_t *ent ) ent->v.watertype = cont; ent->v.waterlevel = 1; - point[2] = ent->v.origin[2] + (ent->v.mins[2] + ent->v.maxs[2]) * 0.5f; + point[2] = ent->v.origin[2] + (ent->v.mins[2] + ent->v.maxs[2]) * 0.5f; svs.groupmask = ent->v.groupinfo; cont = SV_PointContents( point ); @@ -593,7 +596,7 @@ PUSHMOVE ============ SV_AllowPushRotate -Allows to chnage entity yaw? +Allows to change entity yaw? ============ */ qboolean SV_AllowPushRotate( edict_t *ent ) @@ -1060,7 +1063,7 @@ void SV_Physics_Pusher( edict_t *ent ) { if( VectorLength2( ent->v.velocity ) > STOP_EPSILON ) { - pBlocker = SV_PushRotate( ent, movetime ); + pBlocker = SV_PushRotate( ent, movetime ); if( !pBlocker ) { @@ -1529,7 +1532,7 @@ void SV_Physics_Step( edict_t *ent ) point[0] = x ? maxs[0] : mins[0]; point[1] = y ? maxs[1] : mins[1]; - trace = SV_Move( point, vec3_origin, vec3_origin, point, MOVE_NORMAL, ent ); + trace = SV_Move( point, vec3_origin, vec3_origin, point, MOVE_NORMAL, ent ); if( trace.startsolid ) { @@ -1595,9 +1598,9 @@ static void SV_Physics_Entity( edict_t *ent ) } // user dll can override movement type (Xash3D extension) - if( svgame.dllFuncs2.pfnPhysicsEntity ) + if( svgame.physFuncs.SV_PhysicsEntity ) { - if( svgame.dllFuncs2.pfnPhysicsEntity( ent )) + if( svgame.physFuncs.SV_PhysicsEntity( ent )) { if( ent->v.flags & FL_KILLME ) SV_FreeEdict( ent ); @@ -1680,4 +1683,52 @@ void SV_Physics( void ) // decrement svgame.numEntities if the highest number entities died for( ; EDICT_NUM( svgame.numEntities - 1 )->free; svgame.numEntities-- ); +} + +/* +================ +SV_GetServerTime + +Inplementation for new physics interface +================ +*/ +double SV_GetServerTime( void ) +{ + return sv.time; +} + +static server_physics_api_t gPhysicsAPI = +{ + SV_LinkEdict, + SV_GetServerTime, +}; + +/* +=============== +SV_InitPhysicsAPI + +Initialize server external physics +=============== +*/ +qboolean SV_InitPhysicsAPI( void ) +{ + static PHYSICAPI pPhysIface; + + pPhysIface = (PHYSICAPI)Com_GetProcAddress( svgame.hInstance, "Server_GetPhysicsInterface" ); + if( pPhysIface ) + { + if( pPhysIface( SV_PHYSICS_INTERFACE_VERSION, &gPhysicsAPI, &svgame.physFuncs )) + { + MsgDev( D_AICONSOLE, "SV_LoadProgs: ^2initailized extended PhysicAPI ^7ver. %i\n", SV_PHYSICS_INTERFACE_VERSION ); + return true; + } + + // make sure what physic functions is cleared + Q_memset( &svgame.physFuncs, 0, sizeof( svgame.physFuncs )); + + return false; // just tell user about problems + } + + // physic interface is missed + return true; } \ No newline at end of file diff --git a/engine/server/sv_pmove.c b/engine/server/sv_pmove.c index 435ef510..eb079a17 100644 --- a/engine/server/sv_pmove.c +++ b/engine/server/sv_pmove.c @@ -831,9 +831,9 @@ SV_RunCmd */ void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd, int random_seed ) { + usercmd_t cmd; edict_t *clent; vec3_t oldvel; - usercmd_t cmd; int oldmsec; clent = cl->edict; diff --git a/engine/server/sv_world.c b/engine/server/sv_world.c index 4437d702..b850b405 100644 --- a/engine/server/sv_world.c +++ b/engine/server/sv_world.c @@ -143,8 +143,11 @@ hull_t *SV_HullForEntity( edict_t *ent, int hullNumber, vec3_t mins, vec3_t maxs float lastdiff = 999; int i; +#ifdef RANDOM_HULL_NULLIZATION + hullNumber = Com_RandomLong( 0, 0 ); +#else hullNumber = 0; // assume we fail - +#endif // select the hull automatically for( i = 0; i < 4; i++ ) { diff --git a/mainui/basemenu.cpp b/mainui/basemenu.cpp index 0d169c93..66bf591a 100644 --- a/mainui/basemenu.cpp +++ b/mainui/basemenu.cpp @@ -25,7 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "extdll.h" #include "basemenu.h" #include "keydefs.h" -#include "images.h" // built-in resources +#include "menufont.h" // built-in menu font #include "utils.h" #include "menu_btnsbmp_table.h" //CR @@ -56,6 +56,7 @@ int uiInputFgColor = 0xFF555555; // 85, 85, 85, 255 // field, scrollist, che int uiColorWhite = 0xFFFFFFFF; // 255, 255, 255, 255 // useful for bitmaps int uiColorDkGrey = 0xFF404040; // 64, 64, 64, 255 // shadow and grayed items int uiColorBlack = 0xFF000000; // 0, 0, 0, 255 // some controls background +int uiColorConsole = 0xFFF0B418; // just for reference // color presets (this is nasty hack to allow color presets to part of text) const int g_iColorTable[8] = @@ -204,9 +205,12 @@ void UI_DrawString( int x, int y, int w, int h, const char *string, const int co if( !string || !string[0] ) return; +#if 0 // g-cont. disabled 29/06/2011 + // this code do a bad things with prompt dialogues // vertically centered if( !strchr( string, '\n' )) y = y + (( h - charH ) / 2 ); +#endif if( shadow ) { @@ -727,6 +731,20 @@ void UI_RefreshServerList( void ) CLIENT_COMMAND( FALSE, "localservers\n" ); } +/* +================= +UI_RefreshInternetServerList +================= +*/ +void UI_RefreshInternetServerList( void ) +{ + uiStatic.numServers = 0; + memset( uiStatic.serverAddresses, 0, sizeof( uiStatic.serverAddresses )); + memset( uiStatic.serverNames, 0, sizeof( uiStatic.serverNames )); + + CLIENT_COMMAND( FALSE, "internetservers\n" ); +} + /* ================= UI_StartBackGroundMap @@ -1201,6 +1219,7 @@ void UI_Precache( void ) UI_SaveLoad_Precache(); UI_MultiPlayer_Precache(); UI_Options_Precache(); + UI_InternetGames_Precache(); UI_LanGame_Precache(); UI_PlayerSetup_Precache(); UI_Controls_Precache(); @@ -1275,11 +1294,15 @@ void UI_ApplyCustomColors( void ) { UI_ParseColor( pfile, &uiInputFgColor ); } + else if( !stricmp( token, "CON_TEXT_COLOR" )) + { + UI_ParseColor( pfile, &uiColorConsole ); + } } int r, g, b; - UnpackRGB( r, g, b, uiPromptTextColor ); + UnpackRGB( r, g, b, uiColorConsole ); ConsoleSetColor( r, g, b ); FREE_FILE( afile ); @@ -1323,9 +1346,6 @@ UI_VidInit int UI_VidInit( void ) { UI_Precache (); - - // setup game info - GetGameInfo( &gMenu.m_gameinfo ); uiStatic.scaleX = ScreenWidth / 1024.0f; uiStatic.scaleY = ScreenHeight / 768.0f; @@ -1350,8 +1370,17 @@ int UI_VidInit( void ) // trying to load chapterbackgrounds.txt UI_LoadBackgroundMapList (); - // register ui font - uiStatic.hFont = PIC_Load( "menufont", font_tga, sizeof( font_tga )); + // register menu font + uiStatic.hFont = PIC_Load( "#XASH_SYSTEMFONT_001", menufont_bmp, sizeof( menufont_bmp )); + +#if 0 + FILE *f; + + // dump menufont onto disk + f = fopen( "menufont.bmp", "wb" ); + fwrite( menufont_bmp, sizeof( menufont_bmp ), 1, f ); + fclose( f ); +#endif // reload all menu buttons UI_LoadBmpButtons (); @@ -1387,6 +1416,7 @@ void UI_Init( void ) Cmd_AddCommand( "menu_multiplayer", UI_MultiPlayer_Menu ); Cmd_AddCommand( "menu_options", UI_Options_Menu ); Cmd_AddCommand( "menu_langame", UI_LanGame_Menu ); + Cmd_AddCommand( "menu_intenetgames", UI_InternetGames_Menu ); Cmd_AddCommand( "menu_playersetup", UI_PlayerSetup_Menu ); Cmd_AddCommand( "menu_controls", UI_Controls_Menu ); Cmd_AddCommand( "menu_advcontrols", UI_AdvControls_Menu ); @@ -1403,6 +1433,12 @@ void UI_Init( void ) memset( uiEmptyString, ' ', sizeof( uiEmptyString )); // HACKHACK uiStatic.initialized = true; + // setup game info + GetGameInfo( &gMenu.m_gameinfo ); + + // load custom strings + UI_LoadCustomStrings(); + //CR UI_InitTitleAnim(); } @@ -1424,6 +1460,7 @@ void UI_Shutdown( void ) Cmd_RemoveCommand( "menu_saveload" ); Cmd_RemoveCommand( "menu_multiplayer" ); Cmd_RemoveCommand( "menu_options" ); + Cmd_RemoveCommand( "menu_intenetgames" ); Cmd_RemoveCommand( "menu_langame" ); Cmd_RemoveCommand( "menu_playersetup" ); Cmd_RemoveCommand( "menu_controls" ); diff --git a/mainui/basemenu.h b/mainui/basemenu.h index c214f16c..f68f7b6a 100644 --- a/mainui/basemenu.h +++ b/mainui/basemenu.h @@ -404,6 +404,7 @@ void UI_AdjustCursor( menuFramework_s *menu, int dir ); void UI_DrawMenu( menuFramework_s *menu ); const char *UI_DefaultKey( menuFramework_s *menu, int key, int down ); const char *UI_ActivateItem( menuFramework_s *menu, menuCommon_s *item ); +void UI_RefreshInternetServerList( void ); void UI_RefreshServerList( void ); int UI_CreditsActive( void ); void UI_DrawFinalCredits( void ); @@ -420,6 +421,7 @@ void UI_SaveGame_Precache( void ); void UI_SaveLoad_Precache( void ); void UI_MultiPlayer_Precache( void ); void UI_Options_Precache( void ); +void UI_InternetGames_Precache( void ); void UI_LanGame_Precache( void ); void UI_PlayerSetup_Precache( void ); void UI_Controls_Precache( void ); @@ -442,6 +444,7 @@ void UI_SaveGame_Menu( void ); void UI_SaveLoad_Menu( void ); void UI_MultiPlayer_Menu( void ); void UI_Options_Menu( void ); +void UI_InternetGames_Menu( void ); void UI_LanGame_Menu( void ); void UI_PlayerSetup_Menu( void ); void UI_Controls_Menu( void ); diff --git a/mainui/mainui.dsp b/mainui/mainui.dsp index 3c85325d..2445b764 100644 --- a/mainui/mainui.dsp +++ b/mainui/mainui.dsp @@ -154,6 +154,10 @@ SOURCE=.\menu_gameoptions.cpp # End Source File # Begin Source File +SOURCE=.\menu_internetgames.cpp +# End Source File +# Begin Source File + SOURCE=.\menu_langame.cpp # End Source File # Begin Source File @@ -186,6 +190,10 @@ SOURCE=.\menu_saveload.cpp # End Source File # Begin Source File +SOURCE=.\menu_strings.cpp +# End Source File +# Begin Source File + SOURCE=.\menu_video.cpp # End Source File # Begin Source File @@ -226,11 +234,15 @@ SOURCE=.\extdll.h # End Source File # Begin Source File -SOURCE=.\images.h +SOURCE=.\menu_btnsbmp_table.h # End Source File # Begin Source File -SOURCE=.\menu_btnsbmp_table.h +SOURCE=.\menu_strings.h +# End Source File +# Begin Source File + +SOURCE=.\menufont.H # End Source File # Begin Source File diff --git a/mainui/menu_advcontrols.cpp b/mainui/menu_advcontrols.cpp index 44c00c52..dbb54bd1 100644 --- a/mainui/menu_advcontrols.cpp +++ b/mainui/menu_advcontrols.cpp @@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "utils.h" #include "../cl_dll/kbutton.h" #include "menu_btnsbmp_table.h" +#include "menu_strings.h" #define ART_BANNER "gfx/shell/head_advanced" @@ -233,7 +234,7 @@ static void UI_AdvControls_Init( void ) uiAdvControls.invertMouse.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_NOTIFY|QMF_ACT_ONRELEASE|QMF_MOUSEONLY|QMF_DROPSHADOW; uiAdvControls.invertMouse.generic.x = 72; uiAdvControls.invertMouse.generic.y = 280; - uiAdvControls.invertMouse.generic.name = "Reverse mouse"; + uiAdvControls.invertMouse.generic.name = MenuStrings[HINT_REVERSE_MOUSE]; uiAdvControls.invertMouse.generic.callback = UI_AdvControls_Callback; uiAdvControls.invertMouse.generic.statusText = "Reverse mouse up/down axis"; @@ -285,7 +286,7 @@ static void UI_AdvControls_Init( void ) uiAdvControls.sensitivity.generic.id = ID_SENSITIVITY; uiAdvControls.sensitivity.generic.type = QMTYPE_SLIDER; uiAdvControls.sensitivity.generic.flags = QMF_PULSEIFFOCUS|QMF_DROPSHADOW; - uiAdvControls.sensitivity.generic.name = "Mouse sensitivity"; + uiAdvControls.sensitivity.generic.name = MenuStrings[HINT_MOUSE_SENSE]; uiAdvControls.sensitivity.generic.x = 72; uiAdvControls.sensitivity.generic.y = 625; uiAdvControls.sensitivity.generic.callback = UI_AdvControls_Callback; diff --git a/mainui/menu_btns.cpp b/mainui/menu_btns.cpp index 6b23b640..49dfb586 100644 --- a/mainui/menu_btns.cpp +++ b/mainui/menu_btns.cpp @@ -25,7 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define ART_BUTTONS_MAIN "gfx/shell/btns_main.bmp" // we support bmp only -const char *MenuStrings[PC_BUTTONCOUNT] = +const char *MenuButtons[PC_BUTTONCOUNT] = { "New game", "Resume Game", @@ -143,21 +143,21 @@ void UI_LoadBmpButtons( void ) int pallete_sz = pHdr->bmp_offset - sizeof( bmphdr_t ) - pInfoHdr->biSize; - uiStatic.buttons_height = 78; + uiStatic.buttons_height = ( pInfoHdr->biBitCount == 4 ) ? 80 : 78; // bugstompers issues uiStatic.buttons_width = pInfoHdr->biWidth - 3; // make some offset int cutted_img_sz = pInfoHdr->biWidth * uiStatic.buttons_height * pInfoHdr->biBitCount / 8; int CuttedBmpSize = sizeof( bmphdr_t ) + pInfoHdr->biSize + pallete_sz + cutted_img_sz; byte *img_data = &bmp_buffer[bmp_len_holder-cutted_img_sz]; - if ( pInfoHdr->biBitCount == 8 ) + if ( pInfoHdr->biBitCount <= 8 ) { - byte*pallete=&bmp_buffer[sizeof( bmphdr_t ) + pInfoHdr->biSize]; - byte*firstpixel_col=&pallete[img_data[0]*4]; + byte* pallete=&bmp_buffer[sizeof( bmphdr_t ) + pInfoHdr->biSize]; + byte* firstpixel_col=&pallete[img_data[0]*4]; firstpixel_col[0]=firstpixel_col[1]=firstpixel_col[2]=0; } - CuttedDibHdr.biHeight = uiStatic.buttons_height; + CuttedDibHdr.biHeight = 78; //uiStatic.buttons_height; CuttedHdr.filesz = CuttedBmpSize; CuttedDibHdr.biSizeImage = CuttedBmpSize - CuttedHdr.bmp_offset; @@ -178,7 +178,7 @@ void UI_LoadBmpButtons( void ) memcpy( &raw_img_buff[offset], &CuttedDibHdr, CuttedDibHdr.biSize ); offset += CuttedDibHdr.biSize; - if( CuttedDibHdr.biBitCount == 8 ) + if( CuttedDibHdr.biBitCount <= 8 ) { memcpy( &raw_img_buff[offset], &bmp_buffer[offset], pallete_sz ); offset += pallete_sz; diff --git a/mainui/menu_btnsbmp_table.h b/mainui/menu_btnsbmp_table.h index d59b4630..5b050924 100644 --- a/mainui/menu_btnsbmp_table.h +++ b/mainui/menu_btnsbmp_table.h @@ -96,14 +96,14 @@ enum #define BUTTON_FOCUS 1 #define BUTTON_PRESSED 2 -extern const char *MenuStrings[PC_BUTTONCOUNT]; +extern const char *MenuButtons[PC_BUTTONCOUNT]; inline int PicButtonWidth( int pic_id ) { if( pic_id < 0 || pic_id > PC_BUTTONCOUNT ) return 0; - return strlen( MenuStrings[pic_id] ); + return strlen( MenuButtons[pic_id] ); } #endif//MENU_BTNSBMP_TABLE_H \ No newline at end of file diff --git a/mainui/menu_internetgames.cpp b/mainui/menu_internetgames.cpp new file mode 100644 index 00000000..7bb62af4 --- /dev/null +++ b/mainui/menu_internetgames.cpp @@ -0,0 +1,467 @@ +/* +Copyright (C) 1997-2001 Id Software, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "extdll.h" +#include "basemenu.h" +#include "utils.h" +#include "keydefs.h" +#include "menu_btnsbmp_table.h" + +#define ART_BANNER "gfx/shell/head_inetgames" + +#define ID_BACKGROUND 0 +#define ID_BANNER 1 +#define ID_JOINGAME 2 +#define ID_CREATEGAME 3 +#define ID_GAMEINFO 4 +#define ID_REFRESH 5 +#define ID_DONE 6 +#define ID_SERVERSLIST 7 +#define ID_TABLEHINT 8 + +#define ID_MSGBOX 9 +#define ID_MSGTEXT 10 +#define ID_YES 130 +#define ID_NO 131 + +#define GAME_LENGTH 18 +#define MAPNAME_LENGTH 20+GAME_LENGTH +#define TYPE_LENGTH 16+MAPNAME_LENGTH +#define MAXCL_LENGTH 15+TYPE_LENGTH + +typedef struct +{ + char gameDescription[UI_MAX_SERVERS][256]; + char *gameDescriptionPtr[UI_MAX_SERVERS]; + + menuFramework_s menu; + + menuBitmap_s background; + menuBitmap_s banner; + menuPicButton_s joinGame; + menuPicButton_s createGame; + menuPicButton_s gameInfo; + menuPicButton_s refresh; + menuPicButton_s done; + + // joingame prompt dialog + menuAction_s msgBox; + menuAction_s dlgMessage1; + menuAction_s dlgMessage2; + menuPicButton_s yes; + menuPicButton_s no; + + menuScrollList_s gameList; + menuAction_s hintMessage; + char hintText[MAX_HINT_TEXT]; + int refreshTime; +} uiInternetGames_t; + +static uiInternetGames_t uiInternetGames; + +static void UI_PromptDialog( void ) +{ + // toggle main menu between active\inactive + // show\hide quit dialog + uiInternetGames.joinGame.generic.flags ^= QMF_INACTIVE; + uiInternetGames.createGame.generic.flags ^= QMF_INACTIVE; + uiInternetGames.gameInfo.generic.flags ^= QMF_INACTIVE; + uiInternetGames.refresh.generic.flags ^= QMF_INACTIVE; + uiInternetGames.done.generic.flags ^= QMF_INACTIVE; + uiInternetGames.gameList.generic.flags ^= QMF_INACTIVE; + + uiInternetGames.msgBox.generic.flags ^= QMF_HIDDEN; + uiInternetGames.dlgMessage1.generic.flags ^= QMF_HIDDEN; + uiInternetGames.dlgMessage2.generic.flags ^= QMF_HIDDEN; + uiInternetGames.no.generic.flags ^= QMF_HIDDEN; + uiInternetGames.yes.generic.flags ^= QMF_HIDDEN; + +} + +/* +================= +UI_InternetGames_KeyFunc +================= +*/ +static const char *UI_InternetGames_KeyFunc( int key, int down ) +{ + if( down && key == K_ESCAPE && !( uiInternetGames.dlgMessage1.generic.flags & QMF_HIDDEN )) + { + UI_PromptDialog(); + return uiSoundNull; + } + return UI_DefaultKey( &uiInternetGames.menu, key, down ); +} + +/* +================= +UI_InternetGames_GetGamesList +================= +*/ +static void UI_InternetGames_GetGamesList( void ) +{ + int i; + const char *info; + + for( i = 0; i < uiStatic.numServers; i++ ) + { + if( i >= UI_MAX_SERVERS ) break; + info = uiStatic.serverNames[i]; +#if 1 + // NOTE: Xash3D is support hot switching between games in multiplayer + // but this feature not detail tested and may be bugly + if( stricmp( gMenu.m_gameinfo.gamefolder, Info_ValueForKey( info, "gamedir" ))) + continue; // filter by game +#endif + StringConcat( uiInternetGames.gameDescription[i], Info_ValueForKey( info, "host" ), GAME_LENGTH ); + StringConcat( uiInternetGames.gameDescription[i], uiEmptyString, GAME_LENGTH ); + StringConcat( uiInternetGames.gameDescription[i], Info_ValueForKey( info, "map" ), MAPNAME_LENGTH ); + StringConcat( uiInternetGames.gameDescription[i], uiEmptyString, MAPNAME_LENGTH ); + if( !strcmp( Info_ValueForKey( info, "dm" ), "1" )) + StringConcat( uiInternetGames.gameDescription[i], "deathmatch", TYPE_LENGTH ); + else if( !strcmp( Info_ValueForKey( info, "coop" ), "1" )) + StringConcat( uiInternetGames.gameDescription[i], "coop", TYPE_LENGTH ); + else if( !strcmp( Info_ValueForKey( info, "team" ), "1" )) + StringConcat( uiInternetGames.gameDescription[i], "teamplay", TYPE_LENGTH ); + StringConcat( uiInternetGames.gameDescription[i], uiEmptyString, TYPE_LENGTH ); + StringConcat( uiInternetGames.gameDescription[i], Info_ValueForKey( info, "numcl" ), MAXCL_LENGTH ); + StringConcat( uiInternetGames.gameDescription[i], "\\", MAXCL_LENGTH ); + StringConcat( uiInternetGames.gameDescription[i], Info_ValueForKey( info, "maxcl" ), MAXCL_LENGTH ); + StringConcat( uiInternetGames.gameDescription[i], uiEmptyString, MAXCL_LENGTH ); + uiInternetGames.gameDescriptionPtr[i] = uiInternetGames.gameDescription[i]; + } + + for( ; i < UI_MAX_SERVERS; i++ ) + uiInternetGames.gameDescriptionPtr[i] = NULL; + + uiInternetGames.gameList.itemNames = (const char **)uiInternetGames.gameDescriptionPtr; + uiInternetGames.gameList.numItems = 0; // reset it + + if( !uiInternetGames.gameList.generic.charHeight ) + return; // to avoid divide integer by zero + + // count number of items + while( uiInternetGames.gameList.itemNames[uiInternetGames.gameList.numItems] ) + uiInternetGames.gameList.numItems++; + + // calculate number of visible rows + uiInternetGames.gameList.numRows = (uiInternetGames.gameList.generic.height2 / uiInternetGames.gameList.generic.charHeight) - 2; + if( uiInternetGames.gameList.numRows > uiInternetGames.gameList.numItems ) uiInternetGames.gameList.numRows = uiInternetGames.gameList.numItems; + + if( uiStatic.numServers ) + uiInternetGames.joinGame.generic.flags &= ~QMF_GRAYED; +} + +/* +================= +UI_InternetGames_JoinGame +================= +*/ +static void UI_InternetGames_JoinGame( void ) +{ + if( !strlen( uiInternetGames.gameDescription[uiInternetGames.gameList.curItem] )) + return; + + CLIENT_JOIN( uiStatic.serverAddresses[uiInternetGames.gameList.curItem] ); +} + +/* +================= +UI_Background_Ownerdraw +================= +*/ +static void UI_Background_Ownerdraw( void *self ) +{ + menuCommon_s *item = (menuCommon_s *)self; + + if( !CVAR_GET_FLOAT( "sv_background" )) + UI_DrawPic(item->x, item->y, item->width, item->height, uiColorWhite, ((menuBitmap_s *)self)->pic); + + if( uiStatic.realTime > uiInternetGames.refreshTime ) + { + uiInternetGames.refreshTime = uiStatic.realTime + 10000; // refresh every 10 secs + UI_RefreshInternetServerList(); + } + + // serverinfo has been changed update display + if( uiStatic.updateServers ) + { + UI_InternetGames_GetGamesList (); + uiStatic.updateServers = false; + } +} + +/* +================= +UI_MsgBox_Ownerdraw +================= +*/ +static void UI_MsgBox_Ownerdraw( void *self ) +{ + menuCommon_s *item = (menuCommon_s *)self; + + UI_FillRect( item->x, item->y, item->width, item->height, uiPromptBgColor ); +} + +/* +================= +UI_InternetGames_Callback +================= +*/ +static void UI_InternetGames_Callback( void *self, int event ) +{ + menuCommon_s *item = (menuCommon_s *)self; + + if( event != QM_ACTIVATED ) + return; + + switch( item->id ) + { + case ID_JOINGAME: + if( CL_IsActive( )) + UI_PromptDialog(); + else UI_InternetGames_JoinGame(); + break; + case ID_CREATEGAME: + CVAR_SET_FLOAT( "public", 1.0f ); + UI_CreateGame_Menu(); + break; + case ID_GAMEINFO: + // UNDONE: not implemented + break; + case ID_REFRESH: + UI_RefreshInternetServerList(); + break; + case ID_DONE: + UI_PopMenu(); + break; + case ID_YES: + UI_InternetGames_JoinGame(); + break; + case ID_NO: + UI_PromptDialog(); + break; + } +} + +/* +================= +UI_InternetGames_Init +================= +*/ +static void UI_InternetGames_Init( void ) +{ + memset( &uiInternetGames, 0, sizeof( uiInternetGames_t )); + + uiInternetGames.menu.vidInitFunc = UI_InternetGames_Init; + uiInternetGames.menu.keyFunc = UI_InternetGames_KeyFunc; + + StringConcat( uiInternetGames.hintText, "Game", GAME_LENGTH ); + StringConcat( uiInternetGames.hintText, uiEmptyString, GAME_LENGTH ); + StringConcat( uiInternetGames.hintText, "Map", MAPNAME_LENGTH ); + StringConcat( uiInternetGames.hintText, uiEmptyString, MAPNAME_LENGTH ); + StringConcat( uiInternetGames.hintText, "Type", TYPE_LENGTH ); + StringConcat( uiInternetGames.hintText, uiEmptyString, TYPE_LENGTH ); + StringConcat( uiInternetGames.hintText, "Num/Max Clients", MAXCL_LENGTH ); + StringConcat( uiInternetGames.hintText, uiEmptyString, MAXCL_LENGTH ); + + uiInternetGames.background.generic.id = ID_BACKGROUND; + uiInternetGames.background.generic.type = QMTYPE_BITMAP; + uiInternetGames.background.generic.flags = QMF_INACTIVE; + uiInternetGames.background.generic.x = 0; + uiInternetGames.background.generic.y = 0; + uiInternetGames.background.generic.width = 1024; + uiInternetGames.background.generic.height = 768; + uiInternetGames.background.pic = ART_BACKGROUND; + uiInternetGames.background.generic.ownerdraw = UI_Background_Ownerdraw; + + uiInternetGames.banner.generic.id = ID_BANNER; + uiInternetGames.banner.generic.type = QMTYPE_BITMAP; + uiInternetGames.banner.generic.flags = QMF_INACTIVE|QMF_DRAW_ADDITIVE; + uiInternetGames.banner.generic.x = UI_BANNER_POSX; + uiInternetGames.banner.generic.y = UI_BANNER_POSY; + uiInternetGames.banner.generic.width = UI_BANNER_WIDTH; + uiInternetGames.banner.generic.height = UI_BANNER_HEIGHT; + uiInternetGames.banner.pic = ART_BANNER; + + uiInternetGames.joinGame.generic.id = ID_JOINGAME; + uiInternetGames.joinGame.generic.type = QMTYPE_BM_BUTTON; + uiInternetGames.joinGame.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW|QMF_GRAYED; + uiInternetGames.joinGame.generic.x = 72; + uiInternetGames.joinGame.generic.y = 230; + uiInternetGames.joinGame.generic.name = "Join game"; + uiInternetGames.joinGame.generic.statusText = "Join to selected game"; + uiInternetGames.joinGame.generic.callback = UI_InternetGames_Callback; + + UI_UtilSetupPicButton( &uiInternetGames.joinGame, PC_JOIN_GAME ); + + uiInternetGames.createGame.generic.id = ID_CREATEGAME; + uiInternetGames.createGame.generic.type = QMTYPE_BM_BUTTON; + uiInternetGames.createGame.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW; + uiInternetGames.createGame.generic.x = 72; + uiInternetGames.createGame.generic.y = 280; + uiInternetGames.createGame.generic.name = "Create game"; + uiInternetGames.createGame.generic.statusText = "Create new Internet game"; + uiInternetGames.createGame.generic.callback = UI_InternetGames_Callback; + + UI_UtilSetupPicButton( &uiInternetGames.createGame, PC_CREATE_GAME ); + + uiInternetGames.gameInfo.generic.id = ID_GAMEINFO; + uiInternetGames.gameInfo.generic.type = QMTYPE_BM_BUTTON; + uiInternetGames.gameInfo.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW|QMF_GRAYED; + uiInternetGames.gameInfo.generic.x = 72; + uiInternetGames.gameInfo.generic.y = 330; + uiInternetGames.gameInfo.generic.name = "View game info"; + uiInternetGames.gameInfo.generic.statusText = "Get detail game info"; + uiInternetGames.gameInfo.generic.callback = UI_InternetGames_Callback; + + UI_UtilSetupPicButton( &uiInternetGames.gameInfo, PC_VIEW_GAME_INFO ); + + uiInternetGames.refresh.generic.id = ID_REFRESH; + uiInternetGames.refresh.generic.type = QMTYPE_BM_BUTTON; + uiInternetGames.refresh.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW; + uiInternetGames.refresh.generic.x = 72; + uiInternetGames.refresh.generic.y = 380; + uiInternetGames.refresh.generic.name = "Refresh"; + uiInternetGames.refresh.generic.statusText = "Refresh servers list"; + uiInternetGames.refresh.generic.callback = UI_InternetGames_Callback; + + UI_UtilSetupPicButton( &uiInternetGames.refresh, PC_REFRESH ); + + uiInternetGames.done.generic.id = ID_DONE; + uiInternetGames.done.generic.type = QMTYPE_BM_BUTTON; + uiInternetGames.done.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW; + uiInternetGames.done.generic.x = 72; + uiInternetGames.done.generic.y = 430; + uiInternetGames.done.generic.name = "Done"; + uiInternetGames.done.generic.statusText = "Return to main menu"; + uiInternetGames.done.generic.callback = UI_InternetGames_Callback; + + UI_UtilSetupPicButton( &uiInternetGames.done, PC_DONE ); + + uiInternetGames.msgBox.generic.id = ID_MSGBOX; + uiInternetGames.msgBox.generic.type = QMTYPE_ACTION; + uiInternetGames.msgBox.generic.flags = QMF_INACTIVE|QMF_HIDDEN; + uiInternetGames.msgBox.generic.ownerdraw = UI_MsgBox_Ownerdraw; // just a fill rectangle + uiInternetGames.msgBox.generic.x = 192; + uiInternetGames.msgBox.generic.y = 256; + uiInternetGames.msgBox.generic.width = 640; + uiInternetGames.msgBox.generic.height = 256; + + uiInternetGames.dlgMessage1.generic.id = ID_MSGTEXT; + uiInternetGames.dlgMessage1.generic.type = QMTYPE_ACTION; + uiInternetGames.dlgMessage1.generic.flags = QMF_INACTIVE|QMF_HIDDEN|QMF_DROPSHADOW; + uiInternetGames.dlgMessage1.generic.name = "Join a network game will exit"; + uiInternetGames.dlgMessage1.generic.x = 248; + uiInternetGames.dlgMessage1.generic.y = 280; + + uiInternetGames.dlgMessage2.generic.id = ID_MSGTEXT; + uiInternetGames.dlgMessage2.generic.type = QMTYPE_ACTION; + uiInternetGames.dlgMessage2.generic.flags = QMF_INACTIVE|QMF_HIDDEN|QMF_DROPSHADOW; + uiInternetGames.dlgMessage2.generic.name = "any current game, OK to exit?"; + uiInternetGames.dlgMessage2.generic.x = 248; + uiInternetGames.dlgMessage2.generic.y = 310; + + uiInternetGames.yes.generic.id = ID_YES; + uiInternetGames.yes.generic.type = QMTYPE_BM_BUTTON; + uiInternetGames.yes.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_HIDDEN|QMF_DROPSHADOW; + uiInternetGames.yes.generic.name = "Ok"; + uiInternetGames.yes.generic.x = 380; + uiInternetGames.yes.generic.y = 460; + uiInternetGames.yes.generic.callback = UI_InternetGames_Callback; + + UI_UtilSetupPicButton( &uiInternetGames.yes, PC_OK ); + + uiInternetGames.no.generic.id = ID_NO; + uiInternetGames.no.generic.type = QMTYPE_BM_BUTTON; + uiInternetGames.no.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_HIDDEN|QMF_DROPSHADOW; + uiInternetGames.no.generic.name = "Cancel"; + uiInternetGames.no.generic.x = 530; + uiInternetGames.no.generic.y = 460; + uiInternetGames.no.generic.callback = UI_InternetGames_Callback; + + UI_UtilSetupPicButton( &uiInternetGames.no, PC_CANCEL ); + + uiInternetGames.hintMessage.generic.id = ID_TABLEHINT; + uiInternetGames.hintMessage.generic.type = QMTYPE_ACTION; + uiInternetGames.hintMessage.generic.flags = QMF_INACTIVE|QMF_SMALLFONT; + uiInternetGames.hintMessage.generic.color = uiColorHelp; + uiInternetGames.hintMessage.generic.name = uiInternetGames.hintText; + uiInternetGames.hintMessage.generic.x = 360; + uiInternetGames.hintMessage.generic.y = 225; + + uiInternetGames.gameList.generic.id = ID_SERVERSLIST; + uiInternetGames.gameList.generic.type = QMTYPE_SCROLLLIST; + uiInternetGames.gameList.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_SMALLFONT; + uiInternetGames.gameList.generic.x = 360; + uiInternetGames.gameList.generic.y = 255; + uiInternetGames.gameList.generic.width = 640; + uiInternetGames.gameList.generic.height = 440; + uiInternetGames.gameList.generic.callback = UI_InternetGames_Callback; + uiInternetGames.gameList.itemNames = (const char **)uiInternetGames.gameDescriptionPtr; + + // server.dll needs for reading savefiles or startup newgame + if( !CheckGameDll( )) + uiInternetGames.createGame.generic.flags |= QMF_GRAYED; // server.dll is missed - remote servers only + + UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.background ); + UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.banner ); + UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.joinGame ); + UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.createGame ); + UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.gameInfo ); + UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.refresh ); + UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.done ); + UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.hintMessage ); + UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.gameList ); + UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.msgBox ); + UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.dlgMessage1 ); + UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.dlgMessage2 ); + UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.no ); + UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.yes ); + + uiInternetGames.refreshTime = uiStatic.realTime + 500; // delay before update 0.5 sec +} + +/* +================= +UI_InternetGames_Precache +================= +*/ +void UI_InternetGames_Precache( void ) +{ + PIC_Load( ART_BACKGROUND ); + PIC_Load( ART_BANNER ); +} + +/* +================= +UI_InternetGames_Menu +================= +*/ +void UI_InternetGames_Menu( void ) +{ + if ( gMenu.m_gameinfo.gamemode == GAME_SINGLEPLAYER_ONLY ) + return; + + UI_InternetGames_Precache(); + UI_InternetGames_Init(); + + UI_PushMenu( &uiInternetGames.menu ); +} \ No newline at end of file diff --git a/mainui/menu_langame.cpp b/mainui/menu_langame.cpp index 6b541160..0d61f32f 100644 --- a/mainui/menu_langame.cpp +++ b/mainui/menu_langame.cpp @@ -240,6 +240,7 @@ static void UI_LanGame_Callback( void *self, int event ) else UI_LanGame_JoinGame(); break; case ID_CREATEGAME: + CVAR_SET_FLOAT( "public", 0.0f ); UI_CreateGame_Menu(); break; case ID_GAMEINFO: diff --git a/mainui/menu_main.cpp b/mainui/menu_main.cpp index b51bde1b..d424c842 100644 --- a/mainui/menu_main.cpp +++ b/mainui/menu_main.cpp @@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "utils.h" #include "keydefs.h" #include "menu_btnsbmp_table.h" +#include "menu_strings.h" #define ART_MINIMIZE_N "gfx/shell/min_n" #define ART_MINIMIZE_F "gfx/shell/min_f" @@ -40,7 +41,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define ID_SAVERESTORE 6 #define ID_MULTIPLAYER 7 #define ID_CUSTOMGAME 8 -#define ID_CREDITS 9 +#define ID_PREVIEWS 9 #define ID_QUIT 10 #define ID_QUIT_BUTTON 11 #define ID_MINIMIZE 12 @@ -62,7 +63,7 @@ typedef struct menuPicButton_s saveRestore; menuPicButton_s multiPlayer; menuPicButton_s customGame; - menuPicButton_s credits; + menuPicButton_s previews; menuPicButton_s quit; menuBitmap_s minimizeBtn; @@ -72,7 +73,6 @@ typedef struct menuAction_s msgBox; menuAction_s quitMessage; menuAction_s dlgMessage1; - menuAction_s dlgMessage2; menuPicButton_s yes; menuPicButton_s no; } uiMain_t; @@ -133,7 +133,7 @@ static void UI_QuitDialog( void ) uiMain.configuration.generic.flags ^= QMF_INACTIVE; uiMain.multiPlayer.generic.flags ^= QMF_INACTIVE; uiMain.customGame.generic.flags ^= QMF_INACTIVE; - uiMain.credits.generic.flags ^= QMF_INACTIVE; + uiMain.previews.generic.flags ^= QMF_INACTIVE; uiMain.quit.generic.flags ^= QMF_INACTIVE; uiMain.minimizeBtn.generic.flags ^= QMF_INACTIVE; uiMain.quitButton.generic.flags ^= QMF_INACTIVE; @@ -157,14 +157,13 @@ static void UI_PromptDialog( void ) uiMain.configuration.generic.flags ^= QMF_INACTIVE; uiMain.multiPlayer.generic.flags ^= QMF_INACTIVE; uiMain.customGame.generic.flags ^= QMF_INACTIVE; - uiMain.credits.generic.flags ^= QMF_INACTIVE; + uiMain.previews.generic.flags ^= QMF_INACTIVE; uiMain.quit.generic.flags ^= QMF_INACTIVE; uiMain.minimizeBtn.generic.flags ^= QMF_INACTIVE; uiMain.quitButton.generic.flags ^= QMF_INACTIVE; uiMain.msgBox.generic.flags ^= QMF_HIDDEN; uiMain.dlgMessage1.generic.flags ^= QMF_HIDDEN; - uiMain.dlgMessage2.generic.flags ^= QMF_HIDDEN; uiMain.no.generic.flags ^= QMF_HIDDEN; uiMain.yes.generic.flags ^= QMF_HIDDEN; @@ -220,7 +219,7 @@ static void UI_Main_HazardCourse( void ) if( CVAR_GET_FLOAT( "host_serverstate" ) && CVAR_GET_FLOAT( "maxplayers" ) > 1 ) HOST_ENDGAME( "end of the game" ); - CVAR_SET_FLOAT( "skill", 0.0f ); + CVAR_SET_FLOAT( "skill", 1.0f ); CVAR_SET_FLOAT( "deathmatch", 0.0f ); CVAR_SET_FLOAT( "teamplay", 0.0f ); CVAR_SET_FLOAT( "pausable", 1.0f ); // singleplayer is always allowing pause @@ -286,8 +285,8 @@ static void UI_Main_Callback( void *self, int event ) case ID_CUSTOMGAME: UI_CustomGame_Menu(); break; - case ID_CREDITS: - UI_Credits_Menu(); + case ID_PREVIEWS: + SHELL_EXECUTE( MenuStrings[HINT_PREVIEWS_CMD], NULL, false ); break; case ID_QUIT: case ID_QUIT_BUTTON: @@ -361,7 +360,7 @@ static void UI_Main_Init( void ) uiMain.resumeGame.generic.type = QMTYPE_BM_BUTTON; uiMain.resumeGame.generic.name = "Resume game"; uiMain.resumeGame.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW|QMF_NOTIFY; - uiMain.resumeGame.generic.statusText = "Return to game."; + uiMain.resumeGame.generic.statusText = MenuStrings[HINT_RESUME_GAME]; uiMain.resumeGame.generic.x = 72; uiMain.resumeGame.generic.y = 230; uiMain.resumeGame.generic.callback = UI_Main_Callback; @@ -372,7 +371,7 @@ static void UI_Main_Init( void ) uiMain.newGame.generic.type = QMTYPE_BM_BUTTON; uiMain.newGame.generic.name = "New game"; uiMain.newGame.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW|QMF_NOTIFY; - uiMain.newGame.generic.statusText = "Start a new game."; + uiMain.newGame.generic.statusText = MenuStrings[HINT_NEWGAME]; uiMain.newGame.generic.x = 72; uiMain.newGame.generic.y = 280; uiMain.newGame.generic.callback = UI_Main_Callback; @@ -386,7 +385,7 @@ static void UI_Main_Init( void ) uiMain.hazardCourse.generic.type = QMTYPE_BM_BUTTON; uiMain.hazardCourse.generic.name = "Hazard course"; uiMain.hazardCourse.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW|QMF_NOTIFY; - uiMain.hazardCourse.generic.statusText = "Learn how to play the game"; + uiMain.hazardCourse.generic.statusText = MenuStrings[HINT_HAZARD_COURSE]; uiMain.hazardCourse.generic.x = 72; uiMain.hazardCourse.generic.y = 330; uiMain.hazardCourse.generic.callback = UI_Main_Callback; @@ -408,13 +407,13 @@ static void UI_Main_Init( void ) if( CL_IsActive( )) { uiMain.saveRestore.generic.name = "Save\\Load Game"; - uiMain.saveRestore.generic.statusText = "Load a saved game, save the current game."; + uiMain.saveRestore.generic.statusText = MenuStrings[HINT_SAVELOADGAME]; UI_UtilSetupPicButton(&uiMain.saveRestore,PC_SAVE_LOAD_GAME); } else { uiMain.saveRestore.generic.name = "Load Game"; - uiMain.saveRestore.generic.statusText = "Load a previously saved game."; + uiMain.saveRestore.generic.statusText = MenuStrings[HINT_LOADGAME]; uiMain.resumeGame.generic.flags |= QMF_HIDDEN; UI_UtilSetupPicButton( &uiMain.saveRestore, PC_LOAD_GAME ); } @@ -427,7 +426,7 @@ static void UI_Main_Init( void ) uiMain.configuration.generic.type = QMTYPE_BM_BUTTON; uiMain.configuration.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW|QMF_NOTIFY; uiMain.configuration.generic.name = "Configuration"; - uiMain.configuration.generic.statusText = "Change game settings, configure controls"; + uiMain.configuration.generic.statusText = MenuStrings[HINT_CONFIGURATION]; uiMain.configuration.generic.x = 72; uiMain.configuration.generic.y = bTrainMap ? 430 : 380; uiMain.configuration.generic.callback = UI_Main_Callback; @@ -438,7 +437,7 @@ static void UI_Main_Init( void ) uiMain.multiPlayer.generic.type = QMTYPE_BM_BUTTON; uiMain.multiPlayer.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW|QMF_NOTIFY; uiMain.multiPlayer.generic.name = "Multiplayer"; - uiMain.multiPlayer.generic.statusText = "Search for internet servers, configure character"; + uiMain.multiPlayer.generic.statusText = MenuStrings[HINT_MULTIPLAYER]; uiMain.multiPlayer.generic.x = 72; uiMain.multiPlayer.generic.y = bTrainMap ? 480 : 430; uiMain.multiPlayer.generic.callback = UI_Main_Callback; @@ -458,29 +457,33 @@ static void UI_Main_Init( void ) uiMain.customGame.generic.type = QMTYPE_BM_BUTTON; uiMain.customGame.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW|QMF_NOTIFY; uiMain.customGame.generic.name = "Custom Game"; - uiMain.customGame.generic.statusText = "Select a custom game"; + uiMain.customGame.generic.statusText = MenuStrings[HINT_CUSTOM_GAME]; uiMain.customGame.generic.x = 72; uiMain.customGame.generic.y = bTrainMap ? 530 : 480; uiMain.customGame.generic.callback = UI_Main_Callback; UI_UtilSetupPicButton( &uiMain.customGame, PC_CUSTOM_GAME ); - uiMain.credits.generic.id = ID_CREDITS; - uiMain.credits.generic.type = QMTYPE_BM_BUTTON; - uiMain.credits.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW|QMF_NOTIFY; - uiMain.credits.generic.name = "About"; - uiMain.credits.generic.statusText = "Game credits"; - uiMain.credits.generic.x = 72; - uiMain.credits.generic.y = (bCustomGame) ? (bTrainMap ? 580 : 530) : (bTrainMap ? 530 : 480); - uiMain.credits.generic.callback = UI_Main_Callback; + uiMain.previews.generic.id = ID_PREVIEWS; + uiMain.previews.generic.type = QMTYPE_BM_BUTTON; + uiMain.previews.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW|QMF_NOTIFY; + uiMain.previews.generic.name = "Previews"; + uiMain.previews.generic.statusText = MenuStrings[HINT_PREVIEWS_TEXT]; + uiMain.previews.generic.x = 72; + uiMain.previews.generic.y = (bCustomGame) ? (bTrainMap ? 580 : 530) : (bTrainMap ? 530 : 480); + uiMain.previews.generic.callback = UI_Main_Callback; - UI_UtilSetupPicButton( &uiMain.credits, PC_VIEW_README ); + // too short execute string - not a real command + if( strlen( MenuStrings[HINT_PREVIEWS_CMD] ) <= 3 ) + uiMain.previews.generic.flags |= QMF_GRAYED; + + UI_UtilSetupPicButton( &uiMain.previews, PC_PREVIEWS ); uiMain.quit.generic.id = ID_QUIT; uiMain.quit.generic.type = QMTYPE_BM_BUTTON; uiMain.quit.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW|QMF_NOTIFY; uiMain.quit.generic.name = "Quit"; - uiMain.quit.generic.statusText = "Quit from game"; + uiMain.quit.generic.statusText = MenuStrings[HINT_QUIT_BUTTON]; uiMain.quit.generic.x = 72; uiMain.quit.generic.y = (bCustomGame) ? (bTrainMap ? 630 : 580) : (bTrainMap ? 580 : 530); uiMain.quit.generic.callback = UI_Main_Callback; @@ -520,24 +523,21 @@ static void UI_Main_Init( void ) uiMain.quitMessage.generic.id = ID_MSGBOX; uiMain.quitMessage.generic.type = QMTYPE_ACTION; - uiMain.quitMessage.generic.flags = QMF_INACTIVE|QMF_DROPSHADOW|QMF_HIDDEN; - uiMain.quitMessage.generic.name = "Are you sure you want to quit?"; - uiMain.quitMessage.generic.x = 248; + uiMain.quitMessage.generic.flags = QMF_INACTIVE|QMF_DROPSHADOW|QMF_HIDDEN|QMF_CENTER_JUSTIFY; + uiMain.quitMessage.generic.name = (CL_IsActive( )) ? MenuStrings[HINT_QUIT_ACTIVE] : MenuStrings[HINT_QUIT]; + uiMain.quitMessage.generic.x = 192; uiMain.quitMessage.generic.y = 280; + uiMain.quitMessage.generic.width = 640; + uiMain.quitMessage.generic.height = 256; uiMain.dlgMessage1.generic.id = ID_MSGTEXT; uiMain.dlgMessage1.generic.type = QMTYPE_ACTION; - uiMain.dlgMessage1.generic.flags = QMF_INACTIVE|QMF_DROPSHADOW|QMF_HIDDEN; - uiMain.dlgMessage1.generic.name = "Starting a Hazard Course will exit"; - uiMain.dlgMessage1.generic.x = 212; + uiMain.dlgMessage1.generic.flags = QMF_INACTIVE|QMF_DROPSHADOW|QMF_HIDDEN|QMF_CENTER_JUSTIFY; + uiMain.dlgMessage1.generic.name = MenuStrings[HINT_RESTART_HZ]; + uiMain.dlgMessage1.generic.x = 192; uiMain.dlgMessage1.generic.y = 280; - - uiMain.dlgMessage2.generic.id = ID_MSGTEXT; - uiMain.dlgMessage2.generic.type = QMTYPE_ACTION; - uiMain.dlgMessage2.generic.flags = QMF_INACTIVE|QMF_DROPSHADOW|QMF_HIDDEN; - uiMain.dlgMessage2.generic.name = "any current game, OK to exit?"; - uiMain.dlgMessage2.generic.x = 256; - uiMain.dlgMessage2.generic.y = 310; + uiMain.dlgMessage1.generic.width = 640; + uiMain.dlgMessage1.generic.height = 256; uiMain.yes.generic.id = ID_YES; uiMain.yes.generic.type = QMTYPE_BM_BUTTON; @@ -577,14 +577,13 @@ static void UI_Main_Init( void ) if ( bCustomGame ) UI_AddItem( &uiMain.menu, (void *)&uiMain.customGame ); - UI_AddItem( &uiMain.menu, (void *)&uiMain.credits ); + UI_AddItem( &uiMain.menu, (void *)&uiMain.previews ); UI_AddItem( &uiMain.menu, (void *)&uiMain.quit ); UI_AddItem( &uiMain.menu, (void *)&uiMain.minimizeBtn ); UI_AddItem( &uiMain.menu, (void *)&uiMain.quitButton ); UI_AddItem( &uiMain.menu, (void *)&uiMain.msgBox ); UI_AddItem( &uiMain.menu, (void *)&uiMain.quitMessage ); UI_AddItem( &uiMain.menu, (void *)&uiMain.dlgMessage1 ); - UI_AddItem( &uiMain.menu, (void *)&uiMain.dlgMessage2 ); UI_AddItem( &uiMain.menu, (void *)&uiMain.no ); UI_AddItem( &uiMain.menu, (void *)&uiMain.yes ); } diff --git a/mainui/menu_multiplayer.cpp b/mainui/menu_multiplayer.cpp index 7ca444da..199dc33b 100644 --- a/mainui/menu_multiplayer.cpp +++ b/mainui/menu_multiplayer.cpp @@ -67,6 +67,8 @@ static void UI_MultiPlayer_Callback( void *self, int event ) switch( item->id ) { case ID_INTERNETGAMES: + UI_InternetGames_Menu(); + break; case ID_SPECTATEGAMES: // UNDONE: write menus break; @@ -116,7 +118,7 @@ static void UI_MultiPlayer_Init( void ) uiMultiPlayer.internetGames.generic.id = ID_INTERNETGAMES; uiMultiPlayer.internetGames.generic.type = QMTYPE_BM_BUTTON; - uiMultiPlayer.internetGames.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW|QMF_NOTIFY|QMF_GRAYED; + uiMultiPlayer.internetGames.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW|QMF_NOTIFY; uiMultiPlayer.internetGames.generic.x = 72; uiMultiPlayer.internetGames.generic.y = 230; uiMultiPlayer.internetGames.generic.name = "Internet games"; diff --git a/mainui/menu_newgame.cpp b/mainui/menu_newgame.cpp index d2abbfd0..2f84851c 100644 --- a/mainui/menu_newgame.cpp +++ b/mainui/menu_newgame.cpp @@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "utils.h" #include "keydefs.h" #include "menu_btnsbmp_table.h" +#include "menu_strings.h" #define ART_BANNER "gfx/shell/head_newgame" @@ -54,7 +55,6 @@ typedef struct // newgame prompt dialog menuAction_s msgBox; menuAction_s dlgMessage1; - menuAction_s dlgMessage2; menuPicButton_s yes; menuPicButton_s no; @@ -103,7 +103,6 @@ static void UI_PromptDialog( float skill ) uiNewGame.msgBox.generic.flags ^= QMF_HIDDEN; uiNewGame.dlgMessage1.generic.flags ^= QMF_HIDDEN; - uiNewGame.dlgMessage2.generic.flags ^= QMF_HIDDEN; uiNewGame.no.generic.flags ^= QMF_HIDDEN; uiNewGame.yes.generic.flags ^= QMF_HIDDEN; @@ -139,14 +138,14 @@ static void UI_NewGame_Callback( void *self, int event ) switch( item->id ) { case ID_EASY: - UI_PromptDialog( 0.0f ); - break; - case ID_MEDIUM: UI_PromptDialog( 1.0f ); break; - case ID_DIFFICULT: + case ID_MEDIUM: UI_PromptDialog( 2.0f ); break; + case ID_DIFFICULT: + UI_PromptDialog( 3.0f ); + break; case ID_CANCEL: UI_PopMenu(); break; @@ -154,7 +153,7 @@ static void UI_NewGame_Callback( void *self, int event ) UI_NewGame_StartGame( uiNewGame.skill ); break; case ID_NO: - UI_PromptDialog( 0.0f ); // clear skill + UI_PromptDialog( 1.0f ); // clear skill break; } } @@ -205,7 +204,7 @@ static void UI_NewGame_Init( void ) uiNewGame.easy.generic.type = QMTYPE_BM_BUTTON; uiNewGame.easy.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW|QMF_NOTIFY; uiNewGame.easy.generic.name = "Easy"; - uiNewGame.easy.generic.statusText = "Play the game on the 'easy' skill setting"; + uiNewGame.easy.generic.statusText = MenuStrings[HINT_SKILL_EASY]; uiNewGame.easy.generic.x = 72; uiNewGame.easy.generic.y = 230; uiNewGame.easy.generic.callback = UI_NewGame_Callback; @@ -216,7 +215,7 @@ static void UI_NewGame_Init( void ) uiNewGame.medium.generic.type = QMTYPE_BM_BUTTON; uiNewGame.medium.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW|QMF_NOTIFY; uiNewGame.medium.generic.name = "Medium"; - uiNewGame.medium.generic.statusText = "Play the game on the 'medium' skill setting"; + uiNewGame.medium.generic.statusText = MenuStrings[HINT_SKILL_NORMAL]; uiNewGame.medium.generic.x = 72; uiNewGame.medium.generic.y = 280; uiNewGame.medium.generic.callback = UI_NewGame_Callback; @@ -227,7 +226,7 @@ static void UI_NewGame_Init( void ) uiNewGame.hard.generic.type = QMTYPE_BM_BUTTON; uiNewGame.hard.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW|QMF_NOTIFY; uiNewGame.hard.generic.name = "Difficult"; - uiNewGame.hard.generic.statusText = "Play the game on the 'difficult' skill setting"; + uiNewGame.hard.generic.statusText = MenuStrings[HINT_SKILL_HARD]; uiNewGame.hard.generic.x = 72; uiNewGame.hard.generic.y = 330; uiNewGame.hard.generic.callback = UI_NewGame_Callback; @@ -256,17 +255,12 @@ static void UI_NewGame_Init( void ) uiNewGame.dlgMessage1.generic.id = ID_MSGTEXT; uiNewGame.dlgMessage1.generic.type = QMTYPE_ACTION; - uiNewGame.dlgMessage1.generic.flags = QMF_INACTIVE|QMF_HIDDEN|QMF_DROPSHADOW; - uiNewGame.dlgMessage1.generic.name = "Starting a new game will exit"; - uiNewGame.dlgMessage1.generic.x = 248; + uiNewGame.dlgMessage1.generic.flags = QMF_INACTIVE|QMF_HIDDEN|QMF_DROPSHADOW|QMF_CENTER_JUSTIFY; + uiNewGame.dlgMessage1.generic.name = MenuStrings[HINT_RESTART_GAME]; + uiNewGame.dlgMessage1.generic.x = 192; uiNewGame.dlgMessage1.generic.y = 280; - - uiNewGame.dlgMessage2.generic.id = ID_MSGTEXT; - uiNewGame.dlgMessage2.generic.type = QMTYPE_ACTION; - uiNewGame.dlgMessage2.generic.flags = QMF_INACTIVE|QMF_HIDDEN|QMF_DROPSHADOW; - uiNewGame.dlgMessage2.generic.name = "any current game, OK to exit?"; - uiNewGame.dlgMessage2.generic.x = 248; - uiNewGame.dlgMessage2.generic.y = 310; + uiNewGame.dlgMessage1.generic.width = 640; + uiNewGame.dlgMessage1.generic.height = 256; uiNewGame.yes.generic.id = ID_YES; uiNewGame.yes.generic.type = QMTYPE_BM_BUTTON; @@ -296,7 +290,6 @@ static void UI_NewGame_Init( void ) UI_AddItem( &uiNewGame.menu, (void *)&uiNewGame.cancel ); UI_AddItem( &uiNewGame.menu, (void *)&uiNewGame.msgBox ); UI_AddItem( &uiNewGame.menu, (void *)&uiNewGame.dlgMessage1 ); - UI_AddItem( &uiNewGame.menu, (void *)&uiNewGame.dlgMessage2 ); UI_AddItem( &uiNewGame.menu, (void *)&uiNewGame.no ); UI_AddItem( &uiNewGame.menu, (void *)&uiNewGame.yes ); } diff --git a/mainui/menu_strings.cpp b/mainui/menu_strings.cpp new file mode 100644 index 00000000..d9bab119 --- /dev/null +++ b/mainui/menu_strings.cpp @@ -0,0 +1,634 @@ +/* +menu_strings.cpp - custom menu strings +Copyright (C) 2011 Uncle Mike + +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 3 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. +*/ + +#include "extdll.h" +#include "basemenu.h" +#include "utils.h" +#include "menu_strings.h" + +char *MenuStrings[HINT_MAXSTRINGS] = +{ +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 10 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 20 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 30 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 40 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 50 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 60 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 70 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 80 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 90 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 100 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 110 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 120 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 130 +"", +"Display mode", +"", +"", +"", +"", +"", +"", +"", +"", // 140 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 150 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 160 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 170 +"Reverse mouse", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 180 +"", +"", +"", +"Mouse sensitivity", +"", +"", +"", +"Return to game.", +"Start a new game.", +"", // 190 +"Load a previously saved game.", +"Load a saved game, save the current game.", +"Change game settings, configure controls", +"", +"", +"", +"", +"", +"", +"", // 200 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 210 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 220 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 230 +"", +"", +"", +"Starting a Hazard Course will exit\nany current game, OK to exit?", +"", // filled in UI_LoadCustomStrings +"Are you sure you want to quit?", +"", +"", +"", +"Starting a new game will exit\nany current game, OK to exit?", // 240 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 250 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 260 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 270 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 280 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 290 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 300 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 310 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 320 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 330 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 340 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 350 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 360 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 370 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 380 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 390 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"Find more about Valve's product lineup", // 400 +"", +"http://www.valvesoftware.com/projects.htm", +"", +"", +"", +"", +"", +"", +"", +"", // 410 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 420 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 430 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 440 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 450 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 460 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 470 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 480 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 490 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 500 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 510 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 520 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"Select a custom game", // 530 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 540 +"", +"", +"", +"", +"", +"", +"", +"", +"", +"", // 550 +}; + +void UI_InitAliasStrings( void ) +{ + char token[1024]; + + // some strings needs to be initialized here + sprintf( token, "Quit %s without\nsaving current game?", gMenu.m_gameinfo.title ); + MenuStrings[HINT_QUIT_ACTIVE] = StringCopy( token ); + + sprintf( token, "Learn how to play %s", gMenu.m_gameinfo.title ); + MenuStrings[HINT_HAZARD_COURSE] = StringCopy( token ); + + sprintf( token, "Play %s on the 'easy' skill setting", gMenu.m_gameinfo.title ); + MenuStrings[HINT_SKILL_EASY] = StringCopy( token ); + + sprintf( token, "Play %s on the 'medium' skill setting", gMenu.m_gameinfo.title ); + MenuStrings[HINT_SKILL_NORMAL] = StringCopy( token ); + + sprintf( token, "Play %s on the 'difficult' skill setting", gMenu.m_gameinfo.title ); + MenuStrings[HINT_SKILL_HARD] = StringCopy( token ); + + sprintf( token, "Quit playing %s", gMenu.m_gameinfo.title ); + MenuStrings[HINT_QUIT_BUTTON] = StringCopy( token ); + + sprintf( token, "Search for %s servers, configure character", gMenu.m_gameinfo.title ); + MenuStrings[HINT_MULTIPLAYER] = StringCopy( token ); +} + +void UI_LoadCustomStrings( void ) +{ + char *afile = (char *)LOAD_FILE( "gfx/shell/strings.lst", NULL ); + char *pfile = afile; + char token[1024]; + int string_num; + + UI_InitAliasStrings (); + + if( !afile ) + return; + + while(( pfile = COM_ParseFile( pfile, token )) != NULL ) + { + if( isdigit( token[0] )) + { + string_num = atoi( token ); + + // check for bad stiringnum + if( string_num < 0 ) continue; + if( string_num > ( HINT_MAXSTRINGS - 1 )) + continue; + } + else continue; // invalid declaration ? + + // parse new string + pfile = COM_ParseFile( pfile, token ); + MenuStrings[string_num] = StringCopy( token ); // replace default string with custom + } + + FREE_FILE( afile ); +} \ No newline at end of file diff --git a/mainui/menu_strings.h b/mainui/menu_strings.h new file mode 100644 index 00000000..882037b2 --- /dev/null +++ b/mainui/menu_strings.h @@ -0,0 +1,39 @@ +/* +menu_strings.h - custom menu strings +Copyright (C) 2011 Uncle Mike + +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 3 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. +*/ + +#define HINT_DISPLAYMODE 132 +#define HINT_REVERSE_MOUSE 171 +#define HINT_MOUSE_SENSE 184 +#define HINT_RESUME_GAME 188 +#define HINT_NEWGAME 189 +#define HINT_HAZARD_COURSE 190 +#define HINT_LOADGAME 191 +#define HINT_SAVELOADGAME 192 +#define HINT_CONFIGURATION 193 +#define HINT_QUIT_BUTTON 196 +#define HINT_MULTIPLAYER 198 +#define HINT_SKILL_EASY 200 +#define HINT_SKILL_NORMAL 201 +#define HINT_SKILL_HARD 202 +#define HINT_RESTART_HZ 234 +#define HINT_QUIT_ACTIVE 235 +#define HINT_QUIT 236 +#define HINT_RESTART_GAME 240 +#define HINT_PREVIEWS_TEXT 400 +#define HINT_PREVIEWS_CMD 402 // this buton will execute program or open HTML-window +#define HINT_CUSTOM_GAME 530 +#define HINT_MAXSTRINGS 551 // 550 strings allowed + +extern char *MenuStrings[HINT_MAXSTRINGS]; \ No newline at end of file diff --git a/mainui/menu_vidmodes.cpp b/mainui/menu_vidmodes.cpp index 9a40b3c2..9a7c3942 100644 --- a/mainui/menu_vidmodes.cpp +++ b/mainui/menu_vidmodes.cpp @@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "basemenu.h" #include "utils.h" #include "menu_btnsbmp_table.h" +#include "menu_strings.h" #define ART_BANNER "gfx/shell/head_vidmodes" @@ -54,6 +55,7 @@ static const char *uiVideoModes[] = "1024 x 600 (wide)", "1280 x 720 (wide)", "1360 x 768 (wide)", + "1366 x 768 (wide)", "1440 x 900 (wide)", "1680 x 1050 (wide)", "1920 x 1200 (wide)", @@ -216,7 +218,7 @@ static void UI_VidModes_Init( void ) uiVidModes.listCaption.generic.type = QMTYPE_BM_BUTTON; uiVidModes.listCaption.generic.flags = QMF_INACTIVE|QMF_SMALLFONT; uiVidModes.listCaption.generic.color = uiColorHelp; - uiVidModes.listCaption.generic.name = "Display mode"; + uiVidModes.listCaption.generic.name = MenuStrings[HINT_DISPLAYMODE]; uiVidModes.listCaption.generic.x = 400; uiVidModes.listCaption.generic.y = 270; diff --git a/mainui/menufont.H b/mainui/menufont.H new file mode 100644 index 00000000..af78b228 --- /dev/null +++ b/mainui/menufont.H @@ -0,0 +1,2553 @@ +/* +menufont.h - built-in menu font +Copyright (C) 2011 Uncle Mike + +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 3 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. +*/ + +#ifndef MENUFONT_H +#define MENUFONT_H + +const byte menufont_bmp[] = +{ + 0x42,0x4d,0x78,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0x00,0x00, + 0x00,0x28,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00, + 0x01,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x02,0x80,0x00,0x00,0x12, + 0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x11,0x11,0x00,0x22,0x22,0x22, + 0x00,0x33,0x33,0x33,0x00,0x44,0x44,0x44,0x00,0x55,0x55,0x55,0x00, + 0x66,0x66,0x66,0x00,0x77,0x77,0x77,0x00,0x88,0x88,0x88,0x00,0x99, + 0x99,0x99,0x00,0xaa,0xaa,0xaa,0x00,0xbb,0xbb,0xbb,0x00,0xcc,0xcc, + 0xcc,0x00,0xdd,0xdd,0xdd,0x00,0xee,0xee,0xee,0x00,0xff,0xff,0xff, + 0x00,0x21,0x1c,0xfb,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x00, + 0x00,0x11,0x11,0x11,0x11,0x11,0x11,0x10,0x01,0x11,0x11,0x11,0x11, + 0x11,0x9f,0xfb,0x41,0x11,0x11,0x11,0x11,0x10,0x01,0x6f,0xf3,0x00, + 0x01,0x11,0x11,0x10,0x00,0x11,0x11,0x00,0x01,0x11,0x11,0x10,0x00, + 0x00,0x00,0x38,0x51,0x11,0x11,0x11,0x11,0x11,0x10,0x00,0x11,0x11, + 0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x11,0x00,0x00,0x00,0x00, + 0x00,0x06,0x83,0x11,0x10,0x00,0x00,0x00,0x01,0x11,0x11,0x11,0x00, + 0x00,0x00,0x01,0x11,0x00,0x01,0x11,0x10,0x00,0x00,0x00,0x01,0x11, + 0x11,0x11,0x11,0x11,0x00,0x00,0x11,0x11,0x11,0x10,0x00,0x11,0x11, + 0x00,0x00,0x11,0x11,0x11,0x11,0x00,0x01,0x11,0x10,0x01,0x12,0x10, + 0x0c,0xfb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x57,0x73,0x00, + 0x00,0x00,0x00,0x00,0x00,0x37,0x72,0x00,0x00,0x00,0x00,0x00,0x7a, + 0xef,0xd1,0x00,0x00,0x00,0x00,0x16,0x72,0x5f,0xf2,0x47,0x40,0x00, + 0x00,0x04,0x77,0x10,0x02,0x77,0x40,0x00,0x00,0x05,0x77,0x77,0x77, + 0xbf,0xa0,0x00,0x00,0x00,0x00,0x00,0x05,0x75,0x00,0x00,0x02,0x77, + 0x77,0x77,0x77,0x77,0x77,0x20,0x02,0x77,0x77,0x77,0x77,0x77,0x7e, + 0xf5,0x00,0x04,0x77,0x77,0x77,0x40,0x00,0x00,0x02,0x77,0x77,0x77, + 0x51,0x00,0x57,0x50,0x00,0x05,0x77,0x77,0x77,0x30,0x00,0x00,0x00, + 0x00,0x02,0x67,0x73,0x00,0x00,0x00,0x05,0x75,0x00,0x00,0x47,0x75, + 0x10,0x00,0x00,0x00,0x67,0x60,0x00,0x27,0x72,0x01,0x10,0x0c,0xfa, + 0x15,0x75,0x00,0x00,0x00,0x00,0x00,0x4d,0xff,0xff,0x91,0x00,0x00, + 0x00,0x00,0x00,0x6f,0xf4,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xf6, + 0x00,0x00,0x00,0x01,0xcf,0xff,0xbf,0xfb,0xff,0xf8,0x00,0x00,0x04, + 0xff,0xa0,0x0a,0xff,0x40,0x00,0x00,0x0c,0xff,0xff,0xff,0xff,0xa0, + 0x00,0x00,0x00,0x00,0x00,0x0b,0xfc,0x00,0x00,0x05,0xff,0xff,0xff, + 0xff,0xff,0xff,0x50,0x05,0xff,0xff,0xff,0xff,0xff,0xff,0xf5,0x00, + 0x0a,0xff,0xff,0xff,0xfa,0x00,0x00,0x04,0xff,0xff,0xff,0xfd,0x30, + 0xcf,0xb0,0x00,0x0b,0xff,0xff,0xff,0xf9,0x00,0x00,0x00,0x00,0x6e, + 0xff,0xff,0x91,0x00,0x00,0x0b,0xfb,0x00,0x1b,0xff,0xff,0xd3,0x00, + 0x00,0x00,0x7f,0xf6,0x00,0x4f,0xf5,0x01,0x10,0x0c,0xfd,0xdf,0xff, + 0xc2,0x00,0x00,0x00,0x02,0xef,0xd7,0xaf,0xf7,0x00,0x00,0x00,0x00, + 0x00,0x6f,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x2f,0xfc,0x00,0x00, + 0x00,0x08,0xff,0x9a,0xff,0xff,0x8b,0xff,0x50,0x00,0x00,0x8f,0xf4, + 0x5f,0xf8,0x00,0x00,0x00,0x0c,0xfd,0x77,0x8e,0xfd,0x50,0x00,0x00, + 0x00,0x00,0x00,0x0a,0xfc,0x00,0x00,0x05,0xff,0x87,0x9f,0xf9,0x78, + 0xff,0x50,0x05,0xff,0x87,0x9f,0xf9,0x78,0xff,0xa2,0x00,0x09,0xfd, + 0x11,0x17,0xff,0x40,0x00,0x04,0xff,0x51,0x13,0xef,0xa0,0xbf,0xb0, + 0x00,0x0a,0xfc,0x11,0x18,0xff,0x30,0x00,0x00,0x03,0xff,0xd7,0xaf, + 0xf7,0x00,0x00,0x0b,0xfb,0x00,0x9f,0xf9,0x8e,0xfd,0x10,0x00,0x00, + 0x0b,0xfe,0x20,0x3f,0xf5,0x01,0x10,0x0c,0xff,0xc5,0x6e,0xfb,0x00, + 0x00,0x00,0x07,0xff,0x30,0x0c,0xfc,0x00,0x00,0x00,0x00,0x00,0x6f, + 0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x8f,0xff,0x40,0x00,0x00,0x1e, + 0xfa,0x00,0xbf,0xf8,0x01,0xdf,0xa0,0x00,0x00,0x1d,0xfd,0xef,0xd1, + 0x00,0x00,0x00,0x0c,0xfa,0x00,0x0b,0xfa,0x00,0x00,0x00,0x00,0x00, + 0x11,0x0a,0xfc,0x00,0x00,0x05,0xfe,0x00,0x3f,0xf3,0x01,0xff,0x50, + 0x05,0xff,0x10,0x3f,0xf3,0x00,0xef,0x40,0x00,0x09,0xfc,0x00,0x02, + 0xff,0x60,0x00,0x04,0xff,0x40,0x00,0xaf,0xc0,0xbf,0xb0,0x00,0x0a, + 0xfb,0x00,0x03,0xff,0x50,0x00,0x00,0x04,0xbd,0x30,0x0b,0xfd,0x10, + 0x00,0x0b,0xfa,0x01,0xff,0x80,0x04,0xff,0x60,0x00,0x00,0x03,0xef, + 0xa0,0x2f,0xf5,0x01,0x10,0x0c,0xfe,0x10,0x06,0xff,0x30,0x00,0x00, + 0x0a,0xfc,0x00,0x04,0x52,0x00,0x00,0x00,0x00,0x00,0x6f,0xf3,0x00, + 0x00,0x00,0x00,0x00,0x01,0xef,0xbf,0x90,0x00,0x00,0x3f,0xf5,0x00, + 0x6f,0xf3,0x00,0x9f,0xe1,0x00,0x00,0x04,0xff,0xff,0x40,0x00,0x00, + 0x00,0x0c,0xfa,0x00,0x0c,0xfa,0x00,0x00,0x00,0x00,0x2a,0xff,0xce, + 0xfc,0x00,0x00,0x05,0xff,0x10,0x3f,0xf3,0x02,0xff,0x50,0x05,0xff, + 0x20,0x3f,0xf3,0x01,0xff,0x50,0x00,0x09,0xfd,0x11,0x28,0xff,0x30, + 0x00,0x04,0xff,0x51,0x14,0xef,0x90,0xbf,0xb0,0x00,0x0a,0xfc,0x11, + 0x28,0xff,0x30,0x00,0x00,0x00,0x01,0x01,0x17,0xff,0x20,0x00,0x0b, + 0xfd,0x7a,0xff,0x40,0x01,0xdf,0x90,0x00,0x00,0x00,0x8f,0xfa,0x9f, + 0xf5,0x01,0x10,0x0c,0xfa,0x00,0x03,0xff,0x50,0x00,0x00,0x0b,0xfa, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6f,0xf3,0x00,0x00,0x00, + 0x00,0x00,0x06,0xfc,0x3f,0xf2,0x00,0x00,0x4f,0xf4,0x00,0x5f,0xf2, + 0x00,0x7f,0xf1,0x00,0x00,0x00,0xaf,0xf9,0x00,0x00,0x00,0x00,0x0c, + 0xfa,0x00,0x0c,0xfa,0x00,0x00,0x00,0x01,0xdf,0xe8,0x9e,0xfc,0x00, + 0x00,0x05,0xff,0x10,0x3f,0xf3,0x02,0xff,0x50,0x05,0xff,0x20,0x3f, + 0xf3,0x01,0xff,0x50,0x00,0x09,0xff,0xff,0xff,0xf9,0x00,0x00,0x04, + 0xff,0xff,0xff,0xfd,0x20,0xcf,0xb0,0x00,0x0a,0xff,0xff,0xff,0xf9, + 0x00,0x00,0x00,0x00,0x00,0x1f,0xff,0xff,0x30,0x00,0x0b,0xff,0xff, + 0xff,0x40,0x00,0xcf,0x90,0x00,0x00,0x07,0xff,0xff,0xff,0xf5,0x01, + 0x10,0x0c,0xfa,0x00,0x03,0xff,0x50,0x00,0x00,0x0a,0xfc,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x6f,0xf3,0x00,0x00,0x00,0x00,0x00, + 0x0c,0xf8,0x0b,0xf7,0x00,0x00,0x3f,0xf5,0x00,0x6f,0xf3,0x00,0x9f, + 0xd1,0x00,0x00,0x02,0xef,0xfc,0x10,0x00,0x00,0x00,0x0c,0xfa,0x00, + 0x0c,0xfa,0x00,0x00,0x00,0x05,0xff,0x40,0x0a,0xfc,0x00,0x00,0x05, + 0xff,0x10,0x3f,0xf3,0x02,0xff,0x50,0x05,0xff,0x20,0x3f,0xf3,0x01, + 0xff,0x50,0x00,0x09,0xfe,0x88,0x87,0x40,0x00,0x00,0x04,0xff,0xa8, + 0x88,0x61,0x00,0xcf,0xb0,0x00,0x0a,0xfe,0x88,0x87,0x40,0x00,0x00, + 0x00,0x00,0x00,0x07,0x8a,0xff,0x20,0x00,0x0b,0xfd,0x7a,0xff,0x40, + 0x01,0xdf,0x90,0x00,0x00,0x2f,0xf9,0x21,0x4f,0xf5,0x01,0x10,0x0c, + 0xfe,0x20,0x08,0xff,0x30,0x00,0x00,0x07,0xff,0x20,0x0b,0xb6,0x00, + 0x00,0x00,0x00,0x00,0x5f,0xf3,0x00,0x00,0x00,0x00,0x00,0x4f,0xf3, + 0x06,0xfd,0x10,0x00,0x1e,0xfa,0x00,0xbf,0xf8,0x01,0xdf,0xb0,0x00, + 0x00,0x0a,0xff,0xff,0x80,0x00,0x00,0x00,0x0c,0xfa,0x00,0x0c,0xfa, + 0x00,0x00,0x00,0x07,0xff,0x10,0x0a,0xfc,0x00,0x00,0x05,0xff,0x10, + 0x3f,0xf3,0x02,0xff,0x50,0x05,0xff,0x20,0x3f,0xf3,0x01,0xff,0x50, + 0x00,0x09,0xfc,0x00,0x00,0x00,0x00,0x00,0x04,0xff,0x40,0x00,0x00, + 0x00,0xcf,0xb0,0x00,0x0a,0xfb,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x36,0x20,0x08,0xfd,0x00,0x00,0x0b,0xfa,0x01,0xff,0x80,0x03,0xff, + 0x50,0x00,0x00,0x4f,0xf4,0x00,0x3f,0xf5,0x01,0x10,0x0c,0xff,0xd7, + 0x9f,0xfa,0x00,0x00,0x00,0x02,0xef,0xd7,0xbf,0xf7,0x00,0x00,0x00, + 0x02,0x77,0xaf,0xf9,0x77,0x10,0x00,0x00,0x00,0xaf,0xc0,0x02,0xff, + 0x50,0x00,0x07,0xff,0x9a,0xff,0xff,0x9b,0xff,0x50,0x00,0x00,0x6f, + 0xf7,0x8f,0xf3,0x00,0x00,0x00,0x0c,0xfa,0x00,0x0c,0xfa,0x00,0x00, + 0x00,0x08,0xff,0x10,0x0a,0xfc,0x00,0x00,0x05,0xff,0x10,0x3f,0xf3, + 0x02,0xff,0x50,0x05,0xff,0x20,0x3f,0xf3,0x01,0xff,0x50,0x04,0x7c, + 0xfd,0x00,0x00,0x00,0x00,0x00,0x04,0xff,0x50,0x00,0x00,0x00,0xcf, + 0xb0,0x00,0x0a,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0xd7, + 0x9f,0xf7,0x00,0x00,0x0b,0xfb,0x00,0x9f,0xf9,0x8d,0xfd,0x10,0x00, + 0x00,0x2f,0xf9,0x11,0x4f,0xf5,0x01,0x10,0x0c,0xfc,0xcf,0xff,0xa1, + 0x00,0x00,0x00,0x00,0x4d,0xff,0xff,0x90,0x00,0x00,0x00,0x05,0xff, + 0xff,0xff,0xff,0x30,0x00,0x00,0x03,0xff,0x70,0x00,0xaf,0xc0,0x00, + 0x01,0xaf,0xff,0xbf,0xfb,0xff,0xf9,0x00,0x00,0x03,0xff,0xc0,0x1e, + 0xfd,0x10,0x00,0x00,0x0c,0xfb,0x00,0x0c,0xfb,0x00,0x00,0x00,0x08, + 0xff,0x10,0x0b,0xfc,0x00,0x00,0x05,0xff,0x10,0x4f,0xf4,0x02,0xff, + 0x50,0x05,0xff,0x20,0x4f,0xf4,0x01,0xff,0x50,0x09,0xff,0xfd,0x00, + 0x00,0x00,0x00,0x00,0x04,0xff,0x50,0x00,0x00,0x00,0xcf,0xb0,0x00, + 0x0b,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6f,0xff,0xff,0x90, + 0x00,0x00,0x0b,0xfb,0x00,0x1a,0xff,0xff,0xc2,0x00,0x00,0x00,0x09, + 0xff,0xff,0xff,0xf5,0x01,0x10,0x05,0x73,0x16,0x75,0x00,0x00,0x00, + 0x00,0x00,0x01,0x67,0x73,0x00,0x00,0x00,0x00,0x02,0x77,0x77,0x77, + 0x77,0x10,0x00,0x00,0x03,0x87,0x20,0x00,0x37,0x71,0x00,0x00,0x05, + 0x73,0x5f,0xe2,0x47,0x50,0x00,0x00,0x04,0x87,0x30,0x04,0x78,0x20, + 0x00,0x00,0x06,0x75,0x00,0x06,0x75,0x00,0x00,0x00,0x04,0x77,0x10, + 0x05,0x76,0x00,0x00,0x02,0x77,0x10,0x27,0x72,0x01,0x77,0x20,0x02, + 0x77,0x10,0x27,0x72,0x01,0x77,0x20,0x04,0x77,0x76,0x00,0x00,0x00, + 0x00,0x00,0x02,0x77,0x20,0x00,0x00,0x00,0x67,0x50,0x00,0x05,0x76, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x67,0x73,0x00,0x00,0x00, + 0x05,0x75,0x00,0x00,0x47,0x75,0x10,0x00,0x00,0x00,0x00,0x48,0x88, + 0x87,0x72,0x01,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 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,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,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,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, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 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,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,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,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,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,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,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x01,0x76,0x00,0x00,0x00,0x17,0x71,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x10,0x00,0x27,0x74,0x04,0x76,0x00, + 0x00,0x00,0x00,0x00,0x47,0x74,0x00,0x00,0x00,0x00,0x02,0x77,0x88, + 0x88,0x72,0x00,0x00,0x00,0x00,0x27,0x72,0x00,0x00,0x00,0x00,0x02, + 0xff,0x00,0x00,0x00,0x0f,0xf1,0x00,0x00,0x00,0x00,0x47,0x75,0x10, + 0x00,0x00,0x03,0x87,0x20,0x37,0x71,0x04,0x77,0x10,0x00,0x00,0x00, + 0x47,0x86,0x20,0x00,0x00,0x00,0x02,0x77,0x20,0x01,0x77,0x20,0x00, + 0x00,0x03,0x77,0x10,0x02,0x77,0x20,0x00,0x00,0x02,0x77,0x20,0x37, + 0x83,0x00,0x00,0x00,0x27,0x75,0x00,0x00,0x57,0x50,0x00,0x00,0x27, + 0x70,0x06,0x72,0x04,0x75,0x00,0x00,0x02,0x77,0x20,0x02,0x77,0x20, + 0x00,0x00,0x00,0x00,0x47,0x74,0x00,0x00,0x00,0x00,0x00,0x67,0x50, + 0x01,0x77,0x40,0x01,0x10,0x04,0xef,0xff,0xbc,0xf9,0x00,0x00,0x00, + 0x00,0x2c,0xff,0xff,0xc2,0x00,0x00,0x00,0x04,0xff,0xff,0xff,0xfe, + 0x40,0x00,0x00,0x00,0x5f,0xf4,0x00,0x00,0x00,0x00,0x02,0xfe,0x55, + 0x55,0x55,0x5f,0xf1,0x00,0x00,0x00,0x2c,0xff,0xff,0xd3,0x00,0x00, + 0x02,0xff,0x90,0x6f,0xf3,0x0d,0xfc,0x10,0x00,0x00,0x2b,0xff,0xff, + 0xf6,0x00,0x00,0x00,0x05,0xff,0xa0,0x02,0xff,0x50,0x00,0x00,0x07, + 0xff,0x90,0x04,0xff,0x40,0x00,0x00,0x05,0xff,0x40,0xaf,0xf2,0x00, + 0x00,0x00,0x5f,0xff,0x70,0x00,0xbf,0xb0,0x00,0x00,0x4f,0xf0,0x3f, + 0xf9,0x08,0xfa,0x00,0x00,0x05,0xff,0x40,0x05,0xff,0x40,0x00,0x00, + 0x00,0x3c,0xff,0xff,0xc2,0x00,0x00,0x00,0x00,0xcf,0xb0,0x02,0xff, + 0x80,0x01,0x10,0x0c,0xff,0x99,0xff,0xf6,0x00,0x00,0x00,0x01,0xcf, + 0xf9,0x8e,0xfd,0x10,0x00,0x00,0x03,0xff,0x51,0x13,0xdf,0xb0,0x00, + 0x00,0x00,0x5f,0xf3,0x00,0x00,0x00,0x00,0x02,0xff,0xff,0xff,0xff, + 0xff,0xf1,0x00,0x00,0x00,0xbf,0xf9,0x8f,0xfc,0x10,0x00,0x00,0x7f, + 0xf1,0x5f,0xf2,0x4f,0xf4,0x00,0x00,0x00,0x9f,0xf4,0x1a,0xff,0x20, + 0x00,0x00,0x05,0xff,0xf5,0x02,0xff,0x50,0x00,0x00,0x06,0xff,0xf3, + 0x03,0xff,0x30,0x00,0x00,0x05,0xff,0x31,0xef,0x60,0x00,0x00,0x00, + 0x27,0xdf,0xc0,0x00,0xbf,0xb0,0x00,0x00,0x3f,0xf0,0x7f,0xfe,0x07, + 0xf9,0x00,0x00,0x05,0xff,0x30,0x05,0xff,0x30,0x00,0x00,0x01,0xdf, + 0xf8,0x8e,0xfd,0x10,0x00,0x00,0x00,0xcf,0xa0,0x02,0xff,0x70,0x01, + 0x10,0x1e,0xf9,0x00,0x6f,0xf6,0x00,0x00,0x00,0x05,0xff,0x60,0x04, + 0xff,0x70,0x00,0x00,0x03,0xff,0x40,0x00,0xaf,0xc0,0x00,0x00,0x00, + 0x5f,0xf3,0x00,0x00,0x00,0x00,0x01,0x7e,0xfc,0x77,0x7b,0xff,0x70, + 0x00,0x00,0x03,0xff,0x70,0x04,0x52,0x00,0x00,0x00,0x1e,0xf7,0x4f, + 0xf2,0xaf,0xb0,0x00,0x00,0x00,0x25,0x40,0x03,0xff,0x40,0x00,0x00, + 0x05,0xff,0xfd,0x12,0xff,0x50,0x00,0x00,0x06,0xff,0xfb,0x03,0xff, + 0x30,0x00,0x00,0x05,0xff,0x25,0xfd,0x10,0x00,0x00,0x00,0x00,0x8f, + 0xd1,0x00,0xbf,0xb0,0x00,0x00,0x3f,0xf1,0xcf,0xef,0x37,0xf9,0x00, + 0x00,0x05,0xff,0x30,0x05,0xff,0x30,0x00,0x00,0x07,0xff,0x40,0x03, + 0xff,0x70,0x00,0x00,0x00,0xcf,0xa0,0x02,0xff,0x70,0x01,0x10,0x0a, + 0xfd,0x30,0x3f,0xf6,0x00,0x00,0x00,0x08,0xfd,0x00,0x00,0xbf,0xb0, + 0x00,0x00,0x03,0xff,0x51,0x14,0xdf,0x80,0x00,0x00,0x00,0x5f,0xf3, + 0x00,0x00,0x00,0x00,0x00,0x06,0xfd,0x00,0x06,0xfe,0x00,0x00,0x00, + 0x06,0xff,0x31,0x10,0x01,0x00,0x00,0x00,0x04,0xee,0xbf,0xfb,0xfd, + 0x20,0x00,0x00,0x00,0x00,0x00,0x19,0xfe,0x20,0x00,0x00,0x05,0xff, + 0xdf,0x71,0xff,0x50,0x00,0x00,0x06,0xff,0xdf,0x53,0xff,0x30,0x00, + 0x00,0x05,0xff,0x5c,0xf6,0x00,0x00,0x00,0x00,0x00,0x8f,0xe1,0x00, + 0xbf,0xb0,0x00,0x00,0x3f,0xe4,0xfc,0x7f,0x87,0xf9,0x00,0x00,0x05, + 0xff,0x41,0x15,0xff,0x30,0x00,0x00,0x0a,0xfc,0x00,0x00,0xbf,0xb0, + 0x00,0x00,0x00,0xcf,0xa0,0x02,0xff,0x70,0x01,0x10,0x02,0xbf,0xfd, + 0xbf,0xf6,0x00,0x00,0x00,0x0a,0xfb,0x00,0x00,0xaf,0xc0,0x00,0x00, + 0x03,0xff,0xff,0xff,0xf9,0x10,0x00,0x00,0x00,0x5f,0xf3,0x00,0x00, + 0x00,0x00,0x00,0x01,0xef,0x40,0x06,0xff,0x10,0x00,0x00,0x07,0xff, + 0xff,0xff,0xfe,0x40,0x00,0x00,0x00,0x8f,0xff,0xff,0xf5,0x00,0x00, + 0x00,0x00,0x00,0x03,0xff,0xc3,0x00,0x00,0x00,0x05,0xff,0x5e,0xe4, + 0xef,0x50,0x00,0x00,0x07,0xfe,0x5f,0xd4,0xff,0x30,0x00,0x00,0x05, + 0xff,0xff,0x90,0x00,0x00,0x00,0x00,0x00,0x8f,0xd1,0x00,0xbf,0xb0, + 0x00,0x00,0x3f,0xe8,0xf8,0x2f,0xd9,0xf9,0x00,0x00,0x05,0xff,0xff, + 0xff,0xff,0x30,0x00,0x00,0x0b,0xfa,0x00,0x00,0xaf,0xc0,0x00,0x00, + 0x00,0xcf,0xa0,0x02,0xff,0x70,0x01,0x10,0x00,0x02,0x69,0xef,0xf6, + 0x00,0x00,0x00,0x0a,0xfd,0x00,0x00,0xbf,0xb0,0x00,0x00,0x03,0xff, + 0xa8,0x8c,0xfc,0x20,0x00,0x00,0x00,0x5f,0xf3,0x00,0x00,0x00,0x00, + 0x00,0x00,0xcf,0x60,0x06,0xfe,0x10,0x00,0x00,0x06,0xff,0x98,0x89, + 0xff,0x40,0x00,0x00,0x02,0xfc,0x7f,0xf5,0xfc,0x00,0x00,0x00,0x00, + 0x00,0x02,0x8e,0xd4,0x00,0x00,0x00,0x05,0xff,0x27,0xfc,0xff,0x50, + 0x00,0x00,0x06,0xfe,0x09,0xfb,0xff,0x30,0x00,0x00,0x05,0xff,0xbf, + 0xb1,0x00,0x00,0x00,0x00,0x00,0x8f,0xd1,0x00,0xbf,0xb0,0x00,0x00, + 0x3f,0xfd,0xf4,0x0b,0xfd,0xf9,0x00,0x00,0x05,0xff,0xff,0xff,0xff, + 0x30,0x00,0x00,0x0a,0xfc,0x00,0x00,0xbf,0xb0,0x00,0x00,0x00,0xcf, + 0xa0,0x02,0xff,0x70,0x01,0x10,0x01,0x45,0x00,0x4f,0xf5,0x00,0x00, + 0x00,0x0a,0xff,0x60,0x04,0xff,0x70,0x00,0x00,0x03,0xff,0x40,0x01, + 0xff,0x70,0x00,0x00,0x00,0x5f,0xf3,0x00,0x00,0x00,0x00,0x00,0x00, + 0xaf,0x80,0x06,0xff,0x10,0x00,0x00,0x03,0xff,0x50,0x06,0xfe,0x10, + 0x00,0x00,0x06,0xf6,0x4f,0xf2,0xaf,0x30,0x00,0x00,0x00,0x00,0x00, + 0x07,0xfc,0x00,0x00,0x00,0x05,0xff,0x21,0xdf,0xff,0x50,0x00,0x00, + 0x06,0xff,0x02,0xef,0xff,0x30,0x00,0x00,0x05,0xff,0x39,0xf4,0x00, + 0x00,0x00,0x00,0x00,0x8f,0xd0,0x00,0xaf,0xb0,0x00,0x00,0x3f,0xff, + 0xd1,0x07,0xff,0xf9,0x00,0x00,0x05,0xff,0x41,0x15,0xff,0x30,0x00, + 0x00,0x06,0xff,0x40,0x03,0xff,0x70,0x00,0x00,0x00,0xcf,0xa0,0x01, + 0xff,0x70,0x01,0x10,0x06,0xff,0x97,0xcf,0xf4,0x00,0x00,0x00,0x0a, + 0xfe,0xf9,0x8e,0xfd,0x10,0x00,0x00,0x03,0xff,0x51,0x15,0xff,0x70, + 0x00,0x00,0x00,0x5f,0xf9,0x77,0x71,0x00,0x00,0x00,0x00,0x9f,0xa4, + 0x49,0xfe,0x10,0x00,0x00,0x00,0xaf,0xe8,0x9f,0xf8,0x00,0x00,0x00, + 0x2c,0xf2,0x5f,0xf2,0x5f,0x91,0x00,0x00,0x00,0x2b,0xc3,0x1b,0xfb, + 0x00,0x00,0x00,0x05,0xff,0x30,0x5f,0xff,0x50,0x00,0x00,0x06,0xff, + 0x10,0x7f,0xff,0x30,0x00,0x00,0x05,0xff,0x33,0xfb,0x10,0x00,0x00, + 0x00,0x00,0x8f,0xe8,0x77,0xdf,0xb0,0x00,0x00,0x3f,0xff,0x90,0x02, + 0xff,0xf9,0x00,0x00,0x05,0xff,0x30,0x05,0xff,0x30,0x00,0x00,0x01, + 0xdf,0xf9,0x8e,0xfd,0x10,0x00,0x00,0x00,0xcf,0xd7,0x78,0xff,0x70, + 0x01,0x10,0x01,0xaf,0xff,0xff,0x90,0x00,0x00,0x00,0x08,0xf6,0xdf, + 0xff,0xc2,0x00,0x00,0x00,0x04,0xff,0xff,0xff,0xfd,0x20,0x00,0x00, + 0x00,0x5f,0xff,0xff,0xf1,0x00,0x00,0x00,0x00,0x9f,0xff,0xff,0xff, + 0x10,0x00,0x00,0x00,0x1b,0xff,0xff,0xa1,0x00,0x00,0x03,0xff,0xa0, + 0x6f,0xf3,0x1d,0xff,0x10,0x00,0x00,0x1b,0xff,0xff,0xe4,0x00,0x00, + 0x00,0x05,0xff,0x30,0x0b,0xff,0x50,0x00,0x00,0x07,0xff,0x10,0x0d, + 0xff,0x40,0x00,0x00,0x05,0xff,0x40,0xbf,0xf3,0x00,0x00,0x00,0x00, + 0x9f,0xff,0xff,0xff,0xb0,0x00,0x00,0x4f,0xff,0x40,0x00,0xcf,0xfa, + 0x00,0x00,0x05,0xff,0x40,0x05,0xff,0x40,0x00,0x00,0x00,0x2c,0xff, + 0xff,0xc2,0x00,0x00,0x00,0x00,0xcf,0xff,0xff,0xff,0x80,0x01,0x10, + 0x00,0x04,0x77,0x74,0x00,0x00,0x00,0x00,0x04,0xf8,0x15,0x64,0x00, + 0x00,0x00,0x00,0x02,0x77,0x88,0x88,0x61,0x00,0x00,0x00,0x00,0x27, + 0x77,0x77,0x71,0x00,0x00,0x00,0x00,0x47,0x77,0x77,0x77,0x10,0x00, + 0x00,0x00,0x00,0x57,0x74,0x00,0x00,0x00,0x02,0x86,0x10,0x37,0x71, + 0x02,0x77,0x10,0x00,0x00,0x00,0x37,0x86,0x20,0x00,0x00,0x00,0x02, + 0x77,0x10,0x02,0x77,0x20,0x00,0x00,0x03,0x77,0x38,0x53,0x77,0x20, + 0x00,0x00,0x02,0x77,0x20,0x17,0x81,0x00,0x00,0x00,0x00,0x47,0x77, + 0x77,0x77,0x50,0x00,0x00,0x27,0x77,0x10,0x00,0x47,0x75,0x00,0x00, + 0x02,0x77,0x20,0x02,0x77,0x20,0x00,0x00,0x00,0x00,0x47,0x74,0x00, + 0x00,0x00,0x00,0x00,0x67,0x77,0x77,0x77,0x40,0x01,0x10,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0xc7,0x67,0x73,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc9,0xd4,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x10,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x2c,0xff,0xff,0xff,0x30,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,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,0x50,0x34,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x37,0x77,0xaf,0x60,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,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,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,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,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x77,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x03,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,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, + 0x10,0x05,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x26,0x77, + 0x51,0x00,0x00,0x00,0x00,0x00,0x37,0x71,0x00,0x00,0x00,0x00,0x00, + 0x57,0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0x73,0x00,0x00, + 0x00,0x00,0x68,0x72,0x00,0x00,0x37,0x85,0x00,0x00,0x17,0x77,0x77, + 0x77,0x78,0xff,0x30,0x00,0x00,0x00,0x00,0x00,0x67,0x50,0x00,0x03, + 0x77,0x77,0x77,0x77,0x77,0x77,0x40,0x02,0x77,0x77,0x77,0x77,0x77, + 0x7b,0xf6,0x00,0x06,0x77,0x77,0x77,0x73,0x00,0x00,0x04,0x77,0x77, + 0x76,0x30,0x00,0x67,0x40,0x00,0x17,0x77,0x77,0x77,0x62,0x00,0x00, + 0x00,0x00,0x03,0x77,0x74,0x10,0x00,0x00,0x17,0x73,0x00,0x00,0x37, + 0x73,0x00,0x00,0x00,0x67,0x72,0x00,0x00,0x06,0x74,0x01,0x10,0x0b, + 0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0xff,0xff,0xfe,0x60, + 0x00,0x00,0x00,0x00,0x6f,0xf3,0x00,0x00,0x00,0x00,0x00,0xcf,0xfd, + 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xf8,0x10,0x00,0x00,0x00, + 0x6f,0xfb,0x00,0x00,0xcf,0xf5,0x00,0x00,0x3f,0xff,0xff,0xff,0xff, + 0xff,0x30,0x00,0x00,0x00,0x00,0x00,0xcf,0xb0,0x00,0x05,0xff,0xff, + 0xff,0xff,0xff,0xff,0x80,0x05,0xff,0xff,0xff,0xff,0xff,0xff,0xf6, + 0x00,0x0d,0xff,0xff,0xff,0xff,0x80,0x00,0x09,0xff,0xff,0xff,0xf7, + 0x00,0xdf,0x80,0x00,0x2f,0xff,0xff,0xff,0xff,0x60,0x00,0x00,0x02, + 0xbf,0xff,0xff,0xc3,0x00,0x00,0x2f,0xf7,0x00,0x19,0xff,0xff,0xb2, + 0x00,0x00,0x7f,0xfb,0x00,0x00,0x1e,0xf9,0x01,0x10,0x0a,0xfc,0x00, + 0x00,0x00,0x00,0x00,0x00,0x01,0xbf,0xfb,0x79,0xff,0xf5,0x00,0x00, + 0x00,0x00,0x6f,0xf3,0x00,0x00,0x00,0x00,0x00,0x57,0xdf,0xa0,0x00, + 0x00,0x00,0x00,0x04,0x9d,0xff,0xff,0xea,0x60,0x00,0x00,0x0a,0xff, + 0x60,0x07,0xff,0x90,0x00,0x00,0x3f,0xfa,0x77,0x77,0xbf,0xf8,0x10, + 0x00,0x00,0x00,0x00,0x00,0xcf,0xa0,0x00,0x05,0xfd,0x77,0x9f,0xf8, + 0x77,0xdf,0x60,0x05,0xfd,0x77,0x9f,0xf8,0x77,0xdf,0xb3,0x00,0x0c, + 0xfc,0x77,0x78,0xef,0xf5,0x00,0x08,0xfe,0x87,0x9f,0xff,0x30,0xdf, + 0x70,0x00,0x2f,0xfb,0x77,0x79,0xff,0xf3,0x00,0x00,0x2d,0xff,0xb7, + 0x9f,0xfe,0x30,0x00,0x2f,0xf6,0x00,0x9f,0xfb,0xaf,0xfd,0x10,0x00, + 0x0b,0xff,0x60,0x00,0x1d,0xf8,0x01,0x10,0x0a,0xfc,0x00,0x00,0x00, + 0x00,0x00,0x00,0x07,0xff,0x70,0x00,0x3f,0xfd,0x10,0x00,0x00,0x00, + 0x6f,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x2e,0xf3,0x00,0x00,0x00, + 0x00,0x6f,0xff,0xff,0xff,0xff,0xfb,0x10,0x00,0x02,0xef,0xe1,0x2f, + 0xfe,0x10,0x00,0x00,0x3f,0xf5,0x00,0x00,0x6f,0xf1,0x00,0x00,0x00, + 0x00,0x00,0x00,0xcf,0xa0,0x00,0x05,0xfb,0x00,0x2f,0xe1,0x00,0xaf, + 0x50,0x05,0xfb,0x00,0x2f,0xe1,0x00,0xaf,0x60,0x00,0x0d,0xf9,0x00, + 0x00,0x3f,0xfb,0x00,0x09,0xfd,0x00,0x05,0xff,0x80,0xcf,0x70,0x00, + 0x2f,0xf6,0x00,0x00,0x5f,0xf8,0x00,0x00,0x8f,0xf7,0x00,0x04,0xff, + 0xc0,0x00,0x2f,0xf7,0x04,0xff,0x80,0x06,0xff,0x80,0x00,0x03,0xff, + 0xe2,0x00,0x1d,0xf9,0x01,0x10,0x0a,0xfb,0x00,0x00,0x00,0x00,0x00, + 0x00,0x1d,0xfc,0x00,0x00,0x08,0xa4,0x00,0x00,0x00,0x00,0x6f,0xf3, + 0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0xf9,0x00,0x00,0x00,0x03,0xff, + 0xc3,0x3f,0xf7,0x28,0xff,0x70,0x00,0x00,0x6f,0xfa,0xaf,0xf5,0x00, + 0x00,0x00,0x3f,0xf6,0x00,0x00,0x6f,0xf2,0x00,0x00,0x00,0x00,0x11, + 0x00,0xbf,0xa0,0x00,0x05,0xfb,0x00,0x2f,0xe2,0x00,0xaf,0x60,0x05, + 0xfb,0x00,0x2f,0xe2,0x00,0xaf,0x60,0x00,0x0d,0xf9,0x00,0x00,0x0c, + 0xfc,0x00,0x08,0xfd,0x10,0x01,0xff,0x90,0xcf,0x70,0x00,0x2f,0xf7, + 0x00,0x00,0x1f,0xf9,0x00,0x00,0x27,0xb1,0x00,0x00,0x8f,0xf3,0x00, + 0x2f,0xf6,0x0a,0xfd,0x10,0x00,0xcf,0xd1,0x00,0x00,0x7f,0xfb,0x00, + 0x1d,0xf9,0x01,0x10,0x0a,0xfe,0x87,0x77,0x40,0x00,0x00,0x00,0x3f, + 0xf9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6f,0xf3,0x00,0x00, + 0x00,0x00,0x00,0x00,0x6f,0xfe,0x20,0x00,0x00,0x08,0xff,0x20,0x2f, + 0xf6,0x00,0xaf,0xd1,0x00,0x00,0x0b,0xff,0xff,0xa0,0x00,0x00,0x00, + 0x3f,0xf6,0x00,0x00,0x7f,0xf2,0x00,0x00,0x00,0x6b,0xff,0xd9,0xdf, + 0xa0,0x00,0x05,0xfb,0x00,0x2f,0xe2,0x00,0xaf,0x60,0x05,0xfb,0x00, + 0x2f,0xe2,0x00,0xaf,0x60,0x00,0x0d,0xf9,0x00,0x00,0x3f,0xfa,0x00, + 0x09,0xfd,0x00,0x05,0xff,0x80,0xdf,0x70,0x00,0x2f,0xf6,0x00,0x00, + 0x5f,0xf7,0x00,0x00,0x00,0x00,0x01,0x11,0x5f,0xf6,0x00,0x2f,0xf7, + 0x1d,0xf9,0x00,0x00,0x8f,0xf3,0x00,0x00,0x08,0xff,0x92,0x1e,0xf8, + 0x01,0x10,0x0a,0xff,0xff,0xff,0xfc,0x20,0x00,0x00,0x3f,0xf7,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6f,0xf3,0x00,0x00,0x00,0x00, + 0x00,0x01,0xdf,0xff,0x70,0x00,0x00,0x0b,0xfc,0x00,0x2f,0xf6,0x00, + 0x7f,0xf2,0x00,0x00,0x02,0xef,0xfe,0x20,0x00,0x00,0x00,0x3f,0xf6, + 0x00,0x00,0x7f,0xf2,0x00,0x00,0x09,0xff,0xff,0xff,0xff,0xa0,0x00, + 0x05,0xfb,0x00,0x2f,0xe2,0x00,0xaf,0x60,0x05,0xfb,0x00,0x2f,0xe2, + 0x00,0xaf,0x60,0x00,0x0c,0xfc,0x77,0x79,0xef,0xf5,0x00,0x08,0xff, + 0x87,0x9f,0xff,0x20,0xdf,0x70,0x00,0x2f,0xfb,0x77,0x79,0xff,0xf2, + 0x00,0x00,0x00,0x00,0x4f,0xff,0xff,0xf8,0x00,0x2f,0xff,0xff,0xf8, + 0x00,0x00,0x6f,0xf4,0x00,0x00,0x17,0xef,0xff,0xff,0xf9,0x01,0x10, + 0x0a,0xfe,0x87,0x7c,0xff,0xb0,0x00,0x00,0x3f,0xf7,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x6f,0xf3,0x00,0x00,0x00,0x00,0x00,0x07, + 0xfd,0x7f,0xe1,0x00,0x00,0x0b,0xfc,0x00,0x2f,0xf6,0x00,0x7f,0xf2, + 0x00,0x00,0x00,0xbf,0xfa,0x00,0x00,0x00,0x00,0x3f,0xf6,0x00,0x00, + 0x6f,0xf2,0x00,0x00,0x3f,0xfb,0x21,0x16,0xef,0xa0,0x00,0x05,0xfb, + 0x00,0x2f,0xe2,0x00,0xaf,0x60,0x05,0xfb,0x00,0x2f,0xe2,0x00,0xaf, + 0x60,0x00,0x0d,0xff,0xff,0xff,0xff,0x70,0x00,0x08,0xff,0xff,0xff, + 0xe5,0x00,0xdf,0x70,0x00,0x2f,0xff,0xff,0xff,0xfe,0x50,0x00,0x00, + 0x00,0x00,0x4f,0xff,0xff,0xf8,0x00,0x2f,0xff,0xff,0xf7,0x00,0x00, + 0x6f,0xf4,0x00,0x02,0xdf,0xff,0xef,0xff,0xf9,0x01,0x10,0x0a,0xfb, + 0x00,0x00,0xbf,0xf2,0x00,0x00,0x2f,0xf8,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x6f,0xf3,0x00,0x00,0x00,0x00,0x00,0x1e,0xf8,0x1e, + 0xf6,0x00,0x00,0x08,0xff,0x20,0x2f,0xf6,0x00,0xaf,0xd1,0x00,0x00, + 0x04,0xff,0xff,0x40,0x00,0x00,0x00,0x3f,0xf6,0x00,0x00,0x7f,0xf2, + 0x00,0x00,0x5f,0xf3,0x00,0x00,0xbf,0xa0,0x00,0x05,0xfb,0x00,0x2f, + 0xe2,0x00,0xaf,0x60,0x05,0xfb,0x00,0x2f,0xe2,0x00,0xaf,0x60,0x00, + 0x0c,0xfc,0x77,0x77,0x62,0x00,0x00,0x09,0xfe,0x87,0x75,0x20,0x00, + 0xdf,0x70,0x00,0x2f,0xfb,0x77,0x77,0x51,0x00,0x00,0x00,0x00,0x00, + 0x01,0x11,0x5f,0xf6,0x00,0x2f,0xf7,0x1d,0xf9,0x00,0x00,0x8f,0xf3, + 0x00,0x0a,0xff,0x61,0x11,0x2e,0xf8,0x01,0x10,0x0a,0xfc,0x00,0x00, + 0x7f,0xf4,0x00,0x00,0x0c,0xfc,0x00,0x00,0x04,0x52,0x00,0x00,0x00, + 0x00,0x6f,0xf3,0x00,0x00,0x00,0x00,0x00,0x7f,0xf2,0x08,0xfd,0x10, + 0x00,0x03,0xff,0xc3,0x3f,0xf7,0x28,0xff,0x70,0x00,0x00,0x1d,0xff, + 0xff,0xc1,0x00,0x00,0x00,0x3f,0xf6,0x00,0x00,0x6f,0xf2,0x00,0x00, + 0x6f,0xf3,0x00,0x00,0xcf,0xa0,0x00,0x05,0xfb,0x00,0x2f,0xe2,0x00, + 0xaf,0x60,0x05,0xfb,0x00,0x2f,0xe2,0x00,0xaf,0x60,0x00,0x0d,0xf9, + 0x00,0x00,0x00,0x00,0x00,0x08,0xfd,0x00,0x00,0x00,0x00,0xdf,0x70, + 0x00,0x2f,0xf6,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x60,0x00,0x00, + 0x8f,0xf3,0x00,0x2f,0xf6,0x0a,0xfd,0x00,0x00,0xcf,0xd1,0x00,0x1d, + 0xfb,0x00,0x00,0x0d,0xf9,0x01,0x10,0x0a,0xfb,0x00,0x00,0xbf,0xf3, + 0x00,0x00,0x06,0xff,0x70,0x00,0x2e,0xfc,0x00,0x00,0x00,0x00,0x5f, + 0xf2,0x00,0x00,0x00,0x00,0x02,0xef,0x90,0x03,0xff,0x50,0x00,0x00, + 0x6f,0xff,0xff,0xff,0xff,0xfb,0x10,0x00,0x00,0x8f,0xf7,0x7f,0xf7, + 0x00,0x00,0x00,0x3f,0xf6,0x00,0x00,0x7f,0xf2,0x00,0x00,0x6f,0xf3, + 0x00,0x00,0xcf,0xa0,0x00,0x05,0xfb,0x00,0x2f,0xe2,0x00,0xaf,0x60, + 0x05,0xfb,0x00,0x2f,0xe2,0x00,0xaf,0x60,0x00,0x0c,0xf9,0x00,0x00, + 0x00,0x00,0x00,0x08,0xfd,0x10,0x00,0x00,0x00,0xcf,0x70,0x00,0x2f, + 0xf7,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0xf7,0x00,0x04,0xff,0xb0, + 0x00,0x2f,0xf6,0x04,0xff,0x70,0x07,0xff,0x80,0x00,0x1d,0xfd,0x10, + 0x00,0x0d,0xf8,0x01,0x10,0x0a,0xfe,0x87,0x7b,0xff,0xc0,0x00,0x00, + 0x01,0xbf,0xfb,0x79,0xef,0xf5,0x00,0x00,0x27,0x77,0xaf,0xf9,0x77, + 0x60,0x00,0x00,0x08,0xff,0x30,0x00,0xbf,0xc0,0x00,0x00,0x03,0x9d, + 0xff,0xff,0xea,0x60,0x00,0x00,0x03,0xff,0xc0,0x1d,0xff,0x30,0x00, + 0x00,0x3f,0xf6,0x00,0x00,0x6f,0xf2,0x00,0x00,0x6f,0xf3,0x00,0x00, + 0xcf,0xa0,0x00,0x05,0xfb,0x00,0x2f,0xe2,0x00,0xaf,0x60,0x05,0xfb, + 0x00,0x2f,0xe2,0x00,0xaf,0x60,0x04,0x8e,0xf9,0x00,0x00,0x00,0x00, + 0x00,0x08,0xfd,0x10,0x00,0x00,0x00,0xcf,0x70,0x00,0x2f,0xf6,0x00, + 0x00,0x00,0x00,0x00,0x00,0x2d,0xff,0xa7,0x9f,0xfe,0x20,0x00,0x2f, + 0xf7,0x00,0x9f,0xfb,0xbf,0xfd,0x10,0x00,0x08,0xff,0xb7,0x77,0x8e, + 0xf8,0x01,0x10,0x0b,0xff,0xff,0xff,0xfd,0x20,0x00,0x00,0x00,0x19, + 0xff,0xff,0xfd,0x50,0x00,0x00,0x4f,0xff,0xff,0xff,0xff,0xf1,0x00, + 0x00,0x3f,0xfa,0x00,0x00,0x5f,0xf5,0x00,0x00,0x00,0x01,0x3f,0xf8, + 0x10,0x00,0x00,0x00,0x1d,0xff,0x30,0x04,0xff,0xd1,0x00,0x00,0x3f, + 0xf6,0x00,0x00,0x7f,0xf2,0x00,0x00,0x6f,0xf3,0x00,0x00,0xcf,0xb0, + 0x00,0x05,0xfc,0x00,0x3f,0xf2,0x00,0xbf,0x60,0x05,0xfc,0x00,0x3f, + 0xf2,0x00,0xbf,0x70,0x09,0xff,0xfa,0x00,0x00,0x00,0x00,0x00,0x09, + 0xff,0x10,0x00,0x00,0x00,0xdf,0x80,0x00,0x2f,0xf7,0x00,0x00,0x00, + 0x00,0x00,0x00,0x02,0xbf,0xff,0xff,0xc3,0x00,0x00,0x2f,0xf7,0x00, + 0x19,0xff,0xff,0xb2,0x00,0x00,0x01,0xbf,0xff,0xff,0xff,0xf9,0x01, + 0x10,0x05,0x77,0x77,0x77,0x51,0x00,0x00,0x00,0x00,0x00,0x26,0x77, + 0x51,0x00,0x00,0x00,0x27,0x77,0x77,0x77,0x77,0x60,0x00,0x00,0x38, + 0x72,0x00,0x00,0x17,0x74,0x00,0x00,0x00,0x00,0x17,0x73,0x00,0x00, + 0x00,0x00,0x28,0x75,0x00,0x00,0x57,0x82,0x00,0x00,0x17,0x73,0x00, + 0x00,0x37,0x71,0x00,0x00,0x37,0x71,0x00,0x00,0x67,0x50,0x00,0x03, + 0x75,0x00,0x17,0x71,0x00,0x57,0x30,0x03,0x75,0x00,0x17,0x71,0x00, + 0x57,0x30,0x04,0x77,0x75,0x00,0x00,0x00,0x00,0x00,0x04,0x76,0x00, + 0x00,0x00,0x00,0x67,0x40,0x00,0x17,0x73,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x03,0x77,0x74,0x00,0x00,0x00,0x17,0x73,0x00,0x00,0x37, + 0x73,0x00,0x00,0x00,0x00,0x04,0x77,0x77,0x77,0x74,0x01,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,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,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,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x04,0x74,0x00,0x00,0x00,0x02,0x76,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x13,0x87,0x20,0x00,0x00,0x04, + 0x78,0x20,0x00,0x17,0x77,0x77,0x77,0x62,0x00,0x00,0x00,0x27,0x77, + 0x77,0x77,0x62,0x00,0x00,0x00,0x01,0x77,0x40,0x00,0x00,0x00,0x00, + 0x09,0xf9,0x00,0x00,0x00,0x04,0xfe,0x00,0x00,0x05,0x77,0x77,0x77, + 0x77,0x71,0x00,0x28,0x74,0x00,0x27,0x71,0x00,0x67,0x70,0x00,0x00, + 0x03,0x77,0x75,0x20,0x00,0x00,0x00,0x27,0x74,0x00,0x00,0x37,0x71, + 0x00,0x00,0x27,0x73,0x00,0x00,0x37,0x71,0x00,0x00,0x01,0x77,0x30, + 0x00,0x67,0x82,0x00,0x00,0x57,0x73,0x00,0x00,0x27,0x72,0x00,0x02, + 0x77,0x10,0x27,0x72,0x01,0x77,0x30,0x00,0x05,0x76,0x00,0x00,0x17, + 0x74,0x00,0x00,0x00,0x02,0x67,0x76,0x20,0x00,0x00,0x00,0x17,0x73, + 0x00,0x00,0x37,0x71,0x01,0x03,0xff,0x70,0x00,0x00,0x0c,0xff,0x20, + 0x00,0x2f,0xff,0xff,0xff,0xff,0x60,0x00,0x00,0x4f,0xff,0xff,0xff, + 0xff,0x70,0x00,0x00,0x01,0xff,0x80,0x00,0x00,0x00,0x00,0x08,0xfc, + 0x77,0x77,0x77,0x7a,0xfd,0x00,0x00,0x0b,0xff,0xff,0xff,0xff,0xf3, + 0x00,0x1e,0xfd,0x10,0x5f,0xf2,0x03,0xff,0xa0,0x00,0x02,0xbf,0xff, + 0xff,0xf7,0x00,0x00,0x00,0x4f,0xff,0x20,0x00,0x6f,0xf3,0x00,0x00, + 0x4f,0xfd,0x10,0x00,0x7f,0xf1,0x00,0x00,0x02,0xff,0x60,0x03,0xff, + 0xd1,0x00,0x00,0xcf,0xff,0x40,0x00,0x5f,0xf4,0x00,0x05,0xff,0x30, + 0x6f,0xf7,0x02,0xff,0x60,0x00,0x0b,0xfc,0x00,0x00,0x1f,0xf8,0x00, + 0x00,0x01,0x9f,0xff,0xff,0xf9,0x10,0x00,0x00,0x3f,0xf6,0x00,0x00, + 0x7f,0xf2,0x01,0x10,0xcf,0xc0,0x00,0x00,0x2f,0xf9,0x00,0x00,0x2f, + 0xfb,0x77,0x79,0xff,0xf3,0x00,0x00,0x3f,0xfa,0x77,0x78,0xef,0xf4, + 0x00,0x00,0x01,0xef,0x70,0x00,0x00,0x00,0x00,0x09,0xff,0xff,0xff, + 0xff,0xff,0xfd,0x00,0x00,0x0a,0xfe,0x87,0x77,0x77,0x71,0x00,0x06, + 0xff,0x50,0x4f,0xe2,0x09,0xff,0x30,0x00,0x0a,0xff,0xb7,0x8e,0xff, + 0x50,0x00,0x00,0x3f,0xff,0xa0,0x00,0x6f,0xf3,0x00,0x00,0x4f,0xff, + 0x80,0x00,0x7f,0xf1,0x00,0x00,0x02,0xff,0x60,0x09,0xff,0x50,0x00, + 0x00,0x58,0xff,0x90,0x00,0x5f,0xf4,0x00,0x05,0xff,0x30,0xaf,0xfa, + 0x02,0xff,0x60,0x00,0x0a,0xfc,0x00,0x00,0x1e,0xf7,0x00,0x00,0x1b, + 0xff,0xc8,0x7c,0xff,0xb1,0x00,0x00,0x3f,0xf6,0x00,0x00,0x7f,0xf2, + 0x01,0x10,0x6f,0xf8,0x77,0x77,0xbf,0xf4,0x00,0x00,0x2f,0xf6,0x00, + 0x00,0x5f,0xf8,0x00,0x00,0x3f,0xf4,0x00,0x00,0x3f,0xf9,0x00,0x00, + 0x01,0xef,0x70,0x00,0x00,0x00,0x00,0x04,0xaf,0xfa,0x77,0x77,0xdf, + 0xd6,0x00,0x00,0x0a,0xfb,0x00,0x00,0x00,0x00,0x00,0x01,0xdf,0xc0, + 0x4f,0xe1,0x1e,0xfa,0x00,0x00,0x1b,0xfa,0x00,0x03,0xef,0xa0,0x00, + 0x00,0x3f,0xff,0xf4,0x00,0x6f,0xf3,0x00,0x00,0x4f,0xff,0xf3,0x00, + 0x6f,0xe1,0x00,0x00,0x02,0xff,0x60,0x2f,0xfc,0x00,0x00,0x00,0x00, + 0xbf,0xa0,0x00,0x5f,0xf4,0x00,0x05,0xff,0x30,0xdf,0xfe,0x12,0xff, + 0x60,0x00,0x0a,0xfc,0x00,0x00,0x1e,0xf7,0x00,0x00,0x7f,0xf9,0x10, + 0x00,0x9f,0xf6,0x00,0x00,0x3f,0xf6,0x00,0x00,0x7f,0xf2,0x01,0x10, + 0x2f,0xff,0xff,0xff,0xff,0xd1,0x00,0x00,0x2f,0xf6,0x00,0x00,0x2f, + 0xf9,0x00,0x00,0x3f,0xf5,0x00,0x00,0x0e,0xfa,0x00,0x00,0x01,0xef, + 0x70,0x00,0x00,0x00,0x00,0x00,0x1f,0xf8,0x00,0x00,0xaf,0xa0,0x00, + 0x00,0x0a,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0xf3,0x3f,0xe1, + 0x8f,0xf4,0x00,0x00,0x00,0x32,0x00,0x00,0xdf,0xb0,0x00,0x00,0x3f, + 0xff,0xfd,0x10,0x6f,0xf3,0x00,0x00,0x4f,0xff,0xfb,0x00,0x6f,0xe1, + 0x00,0x00,0x02,0xff,0x50,0xaf,0xf5,0x00,0x00,0x00,0x00,0xbf,0xb0, + 0x00,0x5f,0xf4,0x00,0x05,0xff,0x32,0xff,0xff,0x32,0xff,0x60,0x00, + 0x0a,0xfc,0x00,0x00,0x1e,0xf7,0x00,0x00,0xdf,0xd1,0x00,0x00,0x1d, + 0xfd,0x00,0x00,0x3f,0xf6,0x00,0x00,0x6f,0xf2,0x01,0x10,0x0a,0xfe, + 0x87,0x79,0xff,0x90,0x00,0x00,0x2f,0xf6,0x00,0x00,0x5f,0xf8,0x00, + 0x00,0x3f,0xf4,0x00,0x00,0x4f,0xf8,0x00,0x00,0x01,0xef,0x70,0x00, + 0x00,0x00,0x00,0x00,0x0b,0xfb,0x00,0x00,0xbf,0xb0,0x00,0x00,0x0a, + 0xfb,0x00,0x00,0x00,0x00,0x00,0x00,0x1d,0xfb,0x6f,0xe5,0xef,0xa0, + 0x00,0x00,0x00,0x00,0x01,0x28,0xff,0x80,0x00,0x00,0x3f,0xfa,0xff, + 0x70,0x6f,0xf3,0x00,0x00,0x4f,0xfa,0xff,0x60,0x6f,0xe1,0x00,0x00, + 0x02,0xff,0x65,0xff,0xb0,0x00,0x00,0x00,0x00,0xbf,0xb0,0x00,0x5f, + 0xf4,0x00,0x05,0xff,0x35,0xfc,0xbf,0x72,0xff,0x60,0x00,0x0a,0xfb, + 0x00,0x00,0x0e,0xf7,0x00,0x02,0xff,0x90,0x00,0x00,0x09,0xff,0x20, + 0x00,0x3f,0xf6,0x00,0x00,0x7f,0xf2,0x01,0x10,0x05,0xff,0x20,0x06, + 0xff,0x40,0x00,0x00,0x2f,0xfb,0x77,0x79,0xff,0xf2,0x00,0x00,0x3f, + 0xfa,0x77,0x79,0xef,0xd2,0x00,0x00,0x01,0xef,0x70,0x00,0x00,0x00, + 0x00,0x00,0x08,0xfe,0x10,0x00,0xbf,0xb0,0x00,0x00,0x0a,0xfe,0x87, + 0x77,0x77,0x30,0x00,0x00,0x04,0xef,0xff,0xff,0xfc,0x20,0x00,0x00, + 0x00,0x00,0x1e,0xff,0xfb,0x10,0x00,0x00,0x3f,0xf4,0xaf,0xf2,0x5f, + 0xf3,0x00,0x00,0x4f,0xf4,0xcf,0xe1,0x6f,0xe1,0x00,0x00,0x02,0xff, + 0xff,0xfc,0x20,0x00,0x00,0x00,0x00,0xbf,0xb0,0x00,0x5f,0xf4,0x00, + 0x05,0xff,0x38,0xf7,0x6f,0xa3,0xff,0x60,0x00,0x0a,0xfe,0x87,0x77, + 0x8f,0xf7,0x00,0x04,0xff,0x70,0x00,0x00,0x07,0xff,0x40,0x00,0x3f, + 0xf6,0x00,0x00,0x6f,0xf2,0x01,0x10,0x01,0xef,0x70,0x0c,0xfd,0x00, + 0x00,0x00,0x2f,0xff,0xff,0xff,0xfe,0x50,0x00,0x00,0x3f,0xff,0xff, + 0xff,0xfc,0x20,0x00,0x00,0x01,0xff,0x70,0x00,0x00,0x00,0x00,0x00, + 0x06,0xff,0x20,0x00,0xbf,0xb0,0x00,0x00,0x0a,0xff,0xff,0xff,0xff, + 0x60,0x00,0x00,0x01,0xbf,0xff,0xff,0xf7,0x00,0x00,0x00,0x00,0x00, + 0x1e,0xff,0xb0,0x00,0x00,0x00,0x3f,0xf4,0x2f,0xfa,0x5f,0xf3,0x00, + 0x00,0x4f,0xf3,0x3f,0xf8,0x6f,0xf1,0x00,0x00,0x02,0xff,0xff,0xf7, + 0x00,0x00,0x00,0x00,0x00,0xbf,0xb0,0x00,0x5f,0xf4,0x00,0x05,0xff, + 0x5b,0xf3,0x2f,0xd4,0xff,0x60,0x00,0x0a,0xff,0xff,0xff,0xff,0xf7, + 0x00,0x04,0xff,0x70,0x00,0x00,0x07,0xff,0x30,0x00,0x3f,0xf6,0x00, + 0x00,0x6f,0xf2,0x01,0x10,0x00,0x9f,0xc0,0x3f,0xf8,0x00,0x00,0x00, + 0x2f,0xfb,0x77,0x77,0x62,0x00,0x00,0x00,0x3f,0xfa,0x77,0x79,0xfe, + 0x60,0x00,0x00,0x01,0xef,0x70,0x00,0x00,0x00,0x00,0x00,0x05,0xff, + 0x40,0x00,0xbf,0xb0,0x00,0x00,0x0a,0xfe,0x87,0x77,0x77,0x30,0x00, + 0x00,0x06,0xfc,0x6f,0xe5,0xef,0x30,0x00,0x00,0x00,0x00,0x01,0x3c, + 0xf8,0x00,0x00,0x00,0x3f,0xf5,0x08,0xff,0xbf,0xf3,0x00,0x00,0x4f, + 0xf3,0x09,0xfe,0xbf,0xf1,0x00,0x00,0x02,0xff,0x66,0xff,0x30,0x00, + 0x00,0x00,0x00,0xbf,0xb0,0x00,0x5f,0xf4,0x00,0x05,0xff,0x7f,0xe1, + 0x0d,0xf7,0xff,0x60,0x00,0x0a,0xfe,0x87,0x77,0x8f,0xf7,0x00,0x02, + 0xff,0x90,0x00,0x00,0x09,0xff,0x20,0x00,0x3f,0xf6,0x00,0x00,0x6f, + 0xf2,0x01,0x10,0x00,0x4f,0xf2,0x7f,0xf3,0x00,0x00,0x00,0x2f,0xf6, + 0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xf4,0x00,0x00,0x8f,0xe1,0x00, + 0x00,0x01,0xff,0x70,0x00,0x00,0x00,0x00,0x00,0x04,0xff,0x40,0x00, + 0xbf,0xb0,0x00,0x00,0x0a,0xfb,0x00,0x00,0x00,0x00,0x00,0x00,0x0c, + 0xf4,0x3f,0xe1,0x9f,0x80,0x00,0x00,0x00,0x00,0x00,0x03,0xff,0x30, + 0x00,0x00,0x3f,0xf5,0x01,0xdf,0xff,0xf3,0x00,0x00,0x4f,0xf3,0x02, + 0xef,0xff,0xe1,0x00,0x00,0x02,0xff,0x50,0xcf,0x80,0x00,0x00,0x00, + 0x00,0xbf,0xb0,0x00,0x5f,0xf4,0x00,0x05,0xff,0xbf,0xa0,0x09,0xfa, + 0xff,0x60,0x00,0x0a,0xfb,0x00,0x00,0x0e,0xf7,0x00,0x00,0xdf,0xd1, + 0x00,0x00,0x1d,0xfc,0x00,0x00,0x3f,0xf6,0x00,0x00,0x7f,0xf2,0x01, + 0x10,0x00,0x0d,0xf8,0xbf,0xc0,0x00,0x00,0x00,0x2f,0xf6,0x00,0x00, + 0x00,0x00,0x00,0x00,0x3f,0xf4,0x00,0x00,0x7f,0xf2,0x00,0x00,0x01, + 0xff,0x70,0x00,0x00,0x00,0x00,0x00,0x03,0xff,0x40,0x00,0xaf,0xb0, + 0x00,0x00,0x0a,0xfb,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0xe1,0x4f, + 0xe1,0x3f,0xd1,0x00,0x00,0x07,0xcb,0x10,0x06,0xff,0x50,0x00,0x00, + 0x3f,0xf5,0x00,0x5f,0xff,0xf3,0x00,0x00,0x4f,0xf3,0x00,0x6f,0xff, + 0xe1,0x00,0x00,0x02,0xff,0x60,0x6f,0xe1,0x00,0x00,0x00,0x00,0xbf, + 0xa0,0x00,0x4f,0xf4,0x00,0x05,0xff,0xff,0x60,0x05,0xfe,0xff,0x60, + 0x00,0x0a,0xfc,0x00,0x00,0x1e,0xf7,0x00,0x00,0x6f,0xf9,0x00,0x00, + 0x8f,0xf6,0x00,0x00,0x3f,0xf5,0x00,0x00,0x6f,0xf2,0x01,0x10,0x00, + 0x08,0xfe,0xff,0x70,0x00,0x00,0x00,0x2f,0xfb,0x77,0x77,0x77,0x40, + 0x00,0x00,0x3f,0xfa,0x77,0x79,0xff,0xc1,0x00,0x00,0x01,0xff,0xb7, + 0x77,0x77,0x50,0x00,0x00,0x03,0xff,0xa7,0x77,0xdf,0xb0,0x00,0x00, + 0x0a,0xfe,0x87,0x77,0x77,0x60,0x00,0x28,0xdf,0x80,0x4f,0xe1,0x0c, + 0xfb,0x60,0x00,0x08,0xff,0xc7,0x9f,0xfe,0x10,0x00,0x00,0x3f,0xf5, + 0x00,0x0a,0xff,0xf3,0x00,0x00,0x4f,0xf3,0x00,0x0c,0xff,0xf1,0x00, + 0x00,0x02,0xff,0x60,0x1e,0xfc,0x72,0x00,0x00,0x00,0xbf,0xd7,0x77, + 0xaf,0xf4,0x00,0x05,0xff,0xff,0x30,0x02,0xff,0xff,0x60,0x00,0x0a, + 0xfc,0x00,0x00,0x1f,0xf7,0x00,0x00,0x1b,0xff,0xc7,0x7c,0xff,0xb1, + 0x00,0x00,0x3f,0xfa,0x77,0x77,0xbf,0xf2,0x01,0x10,0x00,0x03,0xff, + 0xff,0x20,0x00,0x00,0x00,0x2f,0xff,0xff,0xff,0xff,0x90,0x00,0x00, + 0x4f,0xff,0xff,0xff,0xfd,0x30,0x00,0x00,0x01,0xff,0xff,0xff,0xff, + 0xc0,0x00,0x00,0x04,0xff,0xff,0xff,0xff,0xb0,0x00,0x00,0x0b,0xff, + 0xff,0xff,0xff,0xe1,0x00,0x4f,0xfd,0x20,0x5f,0xf2,0x04,0xef,0xf1, + 0x00,0x01,0x9f,0xff,0xff,0xd4,0x00,0x00,0x00,0x4f,0xf5,0x00,0x02, + 0xff,0xf3,0x00,0x00,0x4f,0xf3,0x01,0x13,0xff,0xf1,0x00,0x00,0x02, + 0xff,0x60,0x05,0xff,0xf4,0x00,0x00,0x00,0xbf,0xff,0xff,0xff,0xf4, + 0x00,0x05,0xff,0xfd,0x00,0x00,0xcf,0xff,0x60,0x00,0x0b,0xfc,0x00, + 0x00,0x1f,0xf8,0x00,0x00,0x01,0x9f,0xff,0xff,0xf8,0x10,0x00,0x00, + 0x3f,0xff,0xff,0xff,0xff,0xf2,0x01,0x10,0x00,0x00,0x67,0x76,0x00, + 0x00,0x00,0x00,0x17,0x77,0x77,0x77,0x77,0x40,0x00,0x00,0x27,0x77, + 0x77,0x77,0x51,0x00,0x00,0x00,0x01,0x77,0x77,0x77,0x77,0x50,0x00, + 0x00,0x02,0x77,0x77,0x77,0x77,0x50,0x00,0x00,0x05,0x77,0x77,0x77, + 0x77,0x60,0x00,0x27,0x61,0x00,0x27,0x71,0x00,0x27,0x70,0x00,0x00, + 0x03,0x67,0x75,0x10,0x00,0x00,0x00,0x27,0x72,0x00,0x00,0x57,0x71, + 0x00,0x00,0x27,0x73,0xae,0xd4,0x57,0x71,0x00,0x00,0x01,0x77,0x30, + 0x00,0x36,0x72,0x00,0x00,0x00,0x57,0x77,0x77,0x77,0x72,0x00,0x02, + 0x77,0x75,0x00,0x00,0x47,0x77,0x30,0x00,0x05,0x76,0x00,0x00,0x17, + 0x74,0x00,0x00,0x00,0x02,0x67,0x76,0x20,0x00,0x00,0x00,0x17,0x77, + 0x77,0x77,0x77,0x71,0x01,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x06,0xc1,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,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,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,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, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x04,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,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,0x10,0x00,0x00,0x16,0x76,0x10,0x00,0x00,0x00,0x00,0x00,0x03, + 0x77,0x10,0x00,0x00,0x00,0x04,0x77,0x77,0x77,0x77,0x10,0x00,0x00, + 0x00,0x00,0x37,0x76,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0x71, + 0x00,0x00,0x00,0x00,0x00,0x47,0x74,0x00,0x00,0x00,0x00,0x00,0x01, + 0x57,0x73,0x00,0x00,0x00,0x00,0x00,0x17,0x73,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x47,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x73, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x0a,0xd2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0x71,0x00,0x00,0x01,0x10, + 0x00,0x03,0xdf,0xff,0xd2,0x00,0x00,0x00,0x00,0x00,0x07,0xff,0x20, + 0x00,0x00,0x00,0x06,0xff,0xff,0xff,0xff,0x30,0x00,0x00,0x00,0x07, + 0xff,0xff,0xe5,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0xf2,0x00,0x00, + 0x00,0x00,0x1b,0xff,0xff,0xc2,0x00,0x00,0x00,0x00,0x2c,0xff,0xff, + 0x80,0x00,0x00,0x00,0x00,0x1f,0xf6,0x00,0x00,0x00,0x00,0x00,0x00, + 0x2c,0xff,0xff,0xc2,0x00,0x00,0x00,0x00,0x09,0xff,0xff,0xa1,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xd8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x3f,0xf3,0x00,0x00,0x01,0x10,0x00,0x1d, + 0xfd,0x7d,0xfb,0x00,0x00,0x00,0x00,0x00,0x06,0xff,0x20,0x00,0x00, + 0x00,0x01,0xdf,0xfe,0xee,0xee,0x20,0x00,0x00,0x00,0x6f,0xfc,0x7d, + 0xff,0x30,0x00,0x00,0x01,0x11,0x11,0x7f,0xf3,0x10,0x00,0x00,0x00, + 0x9f,0xf9,0x8f,0xfb,0x00,0x00,0x00,0x00,0xcf,0xf8,0xaf,0xf6,0x00, + 0x00,0x00,0x00,0x0c,0xf8,0x00,0x00,0x00,0x00,0x00,0x01,0xcf,0xf9, + 0x9f,0xfb,0x00,0x00,0x00,0x00,0x6f,0xfa,0x8f,0xfa,0x00,0x00,0x00, + 0x00,0x00,0x27,0x72,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xda,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4a,0x30,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xa4,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x2e,0xe2,0x00,0x00,0x01,0x10,0x00,0x5f,0xf3,0x04, + 0xff,0x30,0x00,0x00,0x00,0x00,0x07,0xff,0x20,0x00,0x00,0x00,0x00, + 0x5f,0xf7,0x11,0x11,0x00,0x00,0x00,0x00,0xcf,0xe1,0x02,0xef,0x90, + 0x00,0x00,0x09,0xef,0xff,0xff,0xff,0x70,0x00,0x00,0x02,0xff,0xa0, + 0x06,0xff,0x40,0x00,0x00,0x04,0xff,0x60,0x0c,0xfb,0x00,0x00,0x00, + 0x00,0x0a,0xfa,0x00,0x00,0x00,0x00,0x00,0x03,0xff,0x70,0x08,0xff, + 0x20,0x00,0x00,0x00,0x6c,0xc0,0x06,0xff,0x30,0x00,0x00,0x00,0x00, + 0x4f,0xf4,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0xfa,0x00,0x00,0x00, + 0x00,0x00,0x00,0x01,0x5c,0xff,0x30,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x03,0xff,0xc5,0x10,0x00,0x00,0x00,0x00,0x00, + 0x00,0x02,0x20,0x00,0x00,0x01,0x10,0x00,0x8f,0xd0,0x01,0xef,0x60, + 0x00,0x00,0x00,0x00,0x06,0xff,0x20,0x00,0x00,0x00,0x00,0x07,0xff, + 0x60,0x00,0x00,0x00,0x00,0x00,0x36,0x50,0x00,0xcf,0xb0,0x00,0x00, + 0x0a,0xff,0xff,0xff,0xff,0x70,0x00,0x00,0x01,0x47,0x20,0x02,0xff, + 0x60,0x00,0x00,0x08,0xff,0x20,0x09,0xfd,0x10,0x00,0x00,0x00,0x06, + 0xfe,0x10,0x00,0x00,0x00,0x00,0x04,0xff,0x30,0x04,0xff,0x40,0x00, + 0x00,0x00,0x00,0x11,0x11,0xff,0x70,0x00,0x00,0x00,0x00,0x4e,0xf4, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0xfa,0x00,0x00,0x00,0x00,0x00, + 0x02,0x7d,0xff,0xc5,0x00,0x00,0x00,0x02,0x77,0x77,0x77,0x77,0x50, + 0x00,0x00,0x00,0x5c,0xff,0xd7,0x20,0x00,0x00,0x00,0x00,0x00,0x2e, + 0xe2,0x00,0x00,0x01,0x10,0x00,0xaf,0xb0,0x00,0xdf,0x80,0x00,0x00, + 0x00,0x00,0x06,0xff,0x20,0x00,0x00,0x00,0x00,0x00,0x8f,0xf8,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xef,0x90,0x00,0x00,0x05,0xfe, + 0x21,0x7f,0xf3,0x10,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x60,0x00, + 0x00,0x0a,0xff,0x20,0x0a,0xfd,0x00,0x00,0x00,0x00,0x02,0xff,0x40, + 0x00,0x00,0x00,0x00,0x02,0xff,0x70,0x08,0xff,0x20,0x00,0x00,0x00, + 0x03,0xbf,0xd7,0xef,0x90,0x00,0x00,0x00,0x00,0x01,0x10,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0x11,0x00,0x00,0x00,0x00,0x03,0x9e,0xff, + 0xc5,0x00,0x00,0x00,0x00,0x04,0xff,0xff,0xff,0xff,0xc0,0x00,0x00, + 0x00,0x00,0x5c,0xff,0xe9,0x30,0x00,0x00,0x00,0x00,0x1f,0xf7,0x00, + 0x00,0x01,0x10,0x00,0xaf,0xb0,0x00,0xcf,0x90,0x00,0x00,0x00,0x00, + 0x06,0xff,0x20,0x00,0x00,0x00,0x00,0x00,0x07,0xff,0x90,0x00,0x00, + 0x00,0x00,0x00,0x05,0x7c,0xfd,0x20,0x00,0x00,0x00,0x9f,0x90,0x6f, + 0xf2,0x00,0x00,0x00,0x00,0x9e,0x92,0x2a,0xff,0x30,0x00,0x00,0x0b, + 0xff,0x91,0x4e,0xfa,0x00,0x00,0x00,0x00,0x00,0xaf,0x90,0x00,0x00, + 0x00,0x00,0x00,0x7f,0xf8,0x9f,0xf7,0x00,0x00,0x00,0x00,0x3e,0xff, + 0xff,0xff,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0xff,0xc4,0x00,0x00, + 0x00,0x00,0x00,0x02,0x77,0x77,0x77,0x77,0x50,0x00,0x00,0x00,0x00, + 0x00,0x4b,0xff,0xa0,0x00,0x00,0x00,0x00,0x09,0xff,0x70,0x00,0x01, + 0x10,0x00,0xaf,0xb0,0x00,0xcf,0x90,0x00,0x00,0x00,0x00,0x07,0xff, + 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0xf6,0x00,0x00,0x00,0x00, + 0x00,0x08,0xff,0xc1,0x00,0x00,0x00,0x00,0x2e,0xf3,0x6f,0xf2,0x00, + 0x00,0x00,0x00,0xbf,0xff,0xff,0xf8,0x00,0x00,0x00,0x0b,0xff,0xff, + 0xff,0xe2,0x00,0x00,0x00,0x00,0x00,0x4f,0xf2,0x00,0x00,0x00,0x00, + 0x00,0x09,0xff,0xff,0x80,0x00,0x00,0x00,0x00,0xaf,0xe3,0x1a,0xff, + 0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0xff,0xb3,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3b, + 0xff,0xa0,0x00,0x00,0x00,0x00,0x01,0xaf,0xf8,0x00,0x01,0x10,0x00, + 0xaf,0xb0,0x01,0xdf,0x80,0x00,0x00,0x00,0x8a,0x26,0xff,0x20,0x00, + 0x00,0x00,0x00,0x00,0x00,0x0b,0xfd,0x00,0x00,0x00,0x00,0x00,0x03, + 0x9f,0xf7,0x00,0x00,0x00,0x00,0x06,0xfc,0x7f,0xf2,0x00,0x00,0x00, + 0x00,0x8f,0xed,0xfd,0x70,0x00,0x00,0x00,0x0a,0xfd,0x7e,0xfa,0x30, + 0x00,0x00,0x00,0x00,0x00,0x0b,0xf8,0x00,0x00,0x00,0x00,0x00,0x6e, + 0xe8,0x9f,0xe4,0x00,0x00,0x00,0x01,0xef,0x90,0x03,0xff,0x90,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x03,0x9e,0xff,0xb4,0x00,0x00,0x00,0x00,0x04, + 0xff,0xff,0xff,0xff,0xa0,0x00,0x00,0x00,0x00,0x4b,0xff,0xf9,0x30, + 0x00,0x00,0x00,0x00,0x00,0x08,0xff,0x60,0x01,0x10,0x00,0x8f,0xd0, + 0x01,0xef,0x60,0x00,0x00,0x00,0x8f,0xec,0xff,0x20,0x00,0x00,0x00, + 0x01,0x47,0x20,0x05,0xff,0x20,0x00,0x00,0x00,0x00,0x10,0x08,0xff, + 0x20,0x00,0x00,0x00,0x00,0xbf,0xef,0xf2,0x00,0x00,0x00,0x00,0x5f, + 0xd1,0x10,0x00,0x00,0x00,0x00,0x08,0xfe,0x11,0x11,0x00,0x00,0x00, + 0x00,0x00,0x00,0x03,0xff,0x30,0x00,0x00,0x00,0x01,0xdf,0x70,0x09, + 0xfb,0x00,0x00,0x00,0x01,0xef,0x80,0x02,0xff,0x70,0x00,0x00,0x00, + 0x00,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x11,0x00,0x00, + 0x00,0x00,0x00,0x02,0x7d,0xff,0xc5,0x00,0x00,0x00,0x04,0xff,0xff, + 0xff,0xff,0xa0,0x00,0x00,0x00,0x5c,0xff,0xd7,0x20,0x00,0x00,0x00, + 0x04,0x75,0x00,0x00,0xcf,0xb0,0x01,0x10,0x00,0x4f,0xf3,0x04,0xff, + 0x30,0x00,0x00,0x00,0x18,0xff,0xff,0x20,0x00,0x00,0x00,0x02,0xff, + 0x70,0x07,0xff,0x20,0x00,0x00,0x00,0x6c,0xc0,0x07,0xff,0x30,0x00, + 0x00,0x00,0x00,0x2e,0xff,0xf2,0x00,0x00,0x00,0x00,0x3f,0xf3,0x11, + 0x11,0x00,0x00,0x00,0x04,0xff,0x60,0x1d,0xc6,0x00,0x00,0x00,0x01, + 0x11,0x11,0x8f,0xc1,0x00,0x00,0x00,0x01,0xff,0x70,0x09,0xfc,0x00, + 0x00,0x00,0x00,0xcf,0xb0,0x07,0xff,0x30,0x00,0x00,0x00,0x00,0x4e, + 0xf4,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0xea,0x00,0x00,0x00,0x00, + 0x00,0x00,0x01,0x5c,0xff,0x30,0x00,0x00,0x00,0x11,0x11,0x11,0x11, + 0x10,0x00,0x00,0x03,0xff,0xc5,0x10,0x00,0x00,0x00,0x00,0x07,0xff, + 0x30,0x01,0xdf,0xa0,0x01,0x10,0x00,0x1d,0xfd,0x7d,0xfb,0x00,0x00, + 0x00,0x00,0x00,0x5f,0xff,0x20,0x00,0x00,0x00,0x00,0xbf,0xf8,0x9f, + 0xfb,0x00,0x00,0x00,0x00,0x4f,0xfb,0x8e,0xfc,0x10,0x00,0x00,0x00, + 0x00,0x06,0xff,0xf2,0x00,0x00,0x00,0x00,0x1e,0xff,0xee,0xfc,0x00, + 0x00,0x00,0x00,0xbf,0xe8,0xbf,0xf4,0x00,0x00,0x00,0x0a,0xff,0xee, + 0xef,0xf8,0x00,0x00,0x00,0x00,0xbf,0xe8,0x9f,0xf8,0x00,0x00,0x00, + 0x00,0x6f,0xf9,0x8f,0xfb,0x00,0x00,0x00,0x00,0x00,0x4f,0xf4,0x00, + 0x00,0x00,0x00,0x00,0x00,0x0d,0xfb,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x4a,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x03,0xa4,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xdf,0xe8,0x7d, + 0xff,0x40,0x01,0x10,0x00,0x03,0xef,0xff,0xd2,0x00,0x00,0x00,0x00, + 0x00,0x06,0xff,0x20,0x00,0x00,0x00,0x00,0x2c,0xff,0xff,0xc2,0x00, + 0x00,0x00,0x00,0x07,0xff,0xff,0xd3,0x00,0x00,0x00,0x00,0x00,0x00, + 0xcf,0xf2,0x00,0x00,0x00,0x00,0x0c,0xff,0xff,0xfe,0x10,0x00,0x00, + 0x00,0x1b,0xff,0xff,0x80,0x00,0x00,0x00,0x0c,0xff,0xff,0xff,0xfb, + 0x00,0x00,0x00,0x00,0x2c,0xff,0xff,0xb1,0x00,0x00,0x00,0x00,0x08, + 0xff,0xff,0xb2,0x00,0x00,0x00,0x00,0x00,0x27,0x72,0x00,0x00,0x00, + 0x00,0x00,0x00,0x06,0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2c,0xff,0xff,0xe6,0x00, + 0x01,0x10,0x00,0x00,0x26,0x76,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + 0x77,0x10,0x00,0x00,0x00,0x00,0x00,0x47,0x75,0x10,0x00,0x00,0x00, + 0x00,0x00,0x37,0x75,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0x71, + 0x00,0x00,0x00,0x00,0x05,0x77,0x77,0x76,0x00,0x00,0x00,0x00,0x00, + 0x47,0x74,0x00,0x00,0x00,0x00,0x05,0x77,0x77,0x77,0x75,0x00,0x00, + 0x00,0x00,0x01,0x57,0x74,0x00,0x00,0x00,0x00,0x00,0x00,0x37,0x75, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x47,0x75,0x10,0x00,0x01,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,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,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,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x40,0x00,0x00,0x00,0x00,0x01, + 0x10,0x00,0x00,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x75,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x85,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x25,0x00,0x00,0x00,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,0x10,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x27,0x72,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x75,0x03,0x74,0x00,0x00, + 0x00,0x00,0x00,0x01,0x5e,0xd4,0x00,0x00,0x00,0x00,0x02,0xeb,0x00, + 0x00,0x6d,0xfb,0x20,0x00,0x00,0x26,0x77,0x51,0x00,0x51,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0xf5,0x00, + 0x00,0x00,0x00,0x00,0x00,0x01,0xdf,0x30,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x4f,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x27,0x72,0x00,0x00,0x00,0x00,0x00, + 0x04,0x73,0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x5f,0xf4,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x03,0xfe,0x04,0xfc,0x00,0x00,0x00,0x00, + 0x00,0x3d,0xff,0xff,0xb1,0x00,0x00,0x00,0x00,0x9f,0x50,0x03,0xfd, + 0x9f,0xb0,0x00,0x07,0xef,0xff,0xfd,0x6b,0xf9,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4f,0xc0,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x5f,0xb0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x04,0xf2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x4f,0xf4,0x00,0x00,0x00,0x00,0x00,0x05,0xf9, + 0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x4e,0xe3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xdf,0x10,0xee,0x00,0x00,0x00,0x00,0x01,0xdf, + 0xee,0xcc,0xfa,0x00,0x00,0x00,0x00,0x2f,0xc0,0x07,0xf7,0x0d,0xf2, + 0x00,0x5f,0xfc,0x79,0xef,0xff,0xfa,0x10,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xaf,0x80,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x1e,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x06,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x28, + 0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x3f,0xf4,0x00,0x00,0x00,0x00,0x00,0x02,0xfc,0x00,0x00, + 0x00,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x02,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x06,0xdf,0xa7,0xef,0x97,0x50,0x00,0x00,0x03,0xff,0x5a,0x81, + 0xff,0x20,0x00,0x00,0x00,0x09,0xf5,0x08,0xf6,0x0c,0xf3,0x00,0xaf, + 0xd1,0x00,0x5f,0xff,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x02,0xff,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0b,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0e,0xf6,0x00,0x00,0x00,0x00,0x00,0x00,0x4f,0xf4,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x20,0x00,0x00,0x01, + 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0xa0, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e, + 0xff,0xff,0xff,0xff,0xc0,0x00,0x00,0x00,0x35,0x0b,0x81,0xff,0x30, + 0x00,0x00,0x00,0x02,0xfc,0x07,0xf7,0x0d,0xf2,0x00,0xaf,0xc0,0x01, + 0xcf,0xff,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x05,0xff,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xfc, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0c,0xf5,0x00,0x00,0x00,0x00,0x00,0x00,0x4f,0xf3,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x9f,0x50,0x00,0x00,0x01,0x10,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0xc0,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x9f,0xd7, + 0xaf,0xd7,0x50,0x00,0x00,0x00,0x00,0x0b,0xba,0xff,0x20,0x00,0x00, + 0x00,0x00,0x9f,0x42,0xfd,0x9f,0xb0,0x00,0x6f,0xf6,0x1b,0xff,0xaf, + 0xf2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08, + 0xfd,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xfe,0x10,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x1d,0xf6, + 0x11,0x10,0x00,0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x00,0x00,0x00, + 0x01,0x11,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x5f,0x90,0x00,0x00,0x01,0x10,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0xe1,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0xe0,0x2f,0xc0, + 0x00,0x00,0x00,0x00,0x02,0x9e,0xff,0xf8,0x00,0x00,0x00,0x58,0x61, + 0x2f,0xc0,0x6d,0xfb,0x20,0x00,0x0a,0xff,0xdf,0xf7,0x17,0x51,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0xfc,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xff,0x20,0x00,0x00,0x00, + 0x05,0xb1,0x4b,0x20,0x00,0x00,0x00,0x04,0xff,0xff,0xff,0xff,0xa0, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xff, + 0xff,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x2f,0xc0,0x00,0x00,0x01,0x10,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x2f,0xf1,0x00,0x00,0x00,0x00,0x00,0x00, + 0x11,0x10,0x11,0x10,0x00,0x00,0x01,0x1d,0xf3,0x1e,0xf3,0x10,0x00, + 0x00,0x00,0x3e,0xff,0xfc,0x60,0x00,0x00,0x08,0xff,0xfb,0x07,0xf5, + 0x01,0x10,0x00,0x00,0x00,0x6f,0xff,0xe2,0x00,0x00,0x00,0x00,0x00, + 0x00,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x08,0xfd,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x06,0xff,0x10,0x00,0x00,0x00,0x02,0xea, + 0xcc,0x10,0x00,0x00,0x00,0x04,0xff,0xff,0xff,0xff,0xa0,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xff,0xff,0x50, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0d,0xf2,0x00,0x00,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x3f,0xf2,0x00,0x00,0x00,0x00,0x00,0x00,0xce,0x90, + 0xae,0xa0,0x00,0x00,0x0c,0xff,0xff,0xff,0xff,0xa0,0x00,0x00,0x00, + 0xcf,0xee,0x90,0x00,0x00,0x00,0x1f,0xe2,0xbf,0x41,0xec,0x00,0x00, + 0x00,0x00,0x00,0x4f,0xff,0xfd,0x20,0x00,0x00,0x00,0x00,0x00,0x3e, + 0xe4,0x00,0x00,0x00,0x00,0x00,0x06,0xfe,0x10,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x08,0xfd,0x00,0x00,0x00,0x00,0x03,0x8f,0xf7,0x20, + 0x00,0x00,0x00,0x00,0x11,0x1d,0xf6,0x11,0x10,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x11,0x11,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0xf4, + 0x00,0x00,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x4f,0xf4,0x00,0x00,0x00,0x00,0x00,0x00,0xdf,0xa0,0xbf,0xc0, + 0x00,0x00,0x0c,0xff,0xff,0xff,0xff,0xa0,0x00,0x00,0x01,0xff,0x4a, + 0x90,0x00,0x00,0x00,0x4f,0xa0,0x7f,0x60,0x8f,0x50,0x00,0x00,0x00, + 0x00,0xcf,0xc3,0x9f,0xc0,0x00,0x00,0x00,0x00,0x00,0x3f,0xf5,0x00, + 0x00,0x00,0x00,0x00,0x02,0xff,0x30,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x0a,0xf9,0x00,0x00,0x00,0x00,0x2f,0xee,0xde,0xd1,0x00,0x00, + 0x00,0x00,0x00,0x0c,0xf5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0xf8,0x00,0x00, + 0x01,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5f, + 0xf5,0x00,0x00,0x00,0x00,0x00,0x00,0xcb,0x40,0xbc,0x50,0x00,0x00, + 0x01,0x14,0xfc,0x15,0xfb,0x10,0x00,0x00,0x01,0xff,0x4a,0x87,0xc7, + 0x00,0x00,0x4f,0xa0,0x7f,0x60,0x1e,0xc0,0x00,0x00,0x00,0x02,0xff, + 0x60,0x3f,0xf2,0x00,0x00,0x00,0x00,0x00,0x3f,0x92,0x00,0x00,0x00, + 0x00,0x00,0x00,0xbf,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1e, + 0xf4,0x00,0x00,0x00,0x00,0x04,0x2c,0x92,0x40,0x00,0x00,0x00,0x00, + 0x00,0x0e,0xf6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xfc,0x00,0x00,0x01,0x10, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6f,0xf5,0x00, + 0x00,0x00,0x00,0x00,0x00,0xba,0x00,0x9c,0x00,0x00,0x00,0x00,0x01, + 0xff,0x12,0xfd,0x00,0x00,0x00,0x00,0xbf,0xdd,0xde,0xf9,0x00,0x00, + 0x2f,0xd2,0xbf,0x40,0x08,0xf5,0x00,0x00,0x00,0x01,0xef,0xd7,0xcf, + 0xd1,0x00,0x00,0x00,0x00,0x00,0x1f,0x50,0x00,0x00,0x00,0x00,0x00, + 0x00,0x4f,0xd0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5f,0xb0,0x00, + 0x00,0x00,0x00,0x00,0x0d,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x06, + 0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xdf,0x10,0x00,0x01,0x10,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6f,0xf5,0x00,0x00,0x00, + 0x00,0x00,0x00,0x3e,0x80,0x2d,0xa0,0x00,0x00,0x00,0x00,0xcf,0x40, + 0xef,0x30,0x00,0x00,0x00,0x2c,0xff,0xff,0xb1,0x00,0x00,0x08,0xff, + 0xfb,0x10,0x01,0xfe,0x10,0x00,0x00,0x00,0x6f,0xff,0xfe,0x40,0x00, + 0x00,0x00,0x00,0x00,0x07,0xf4,0x00,0x00,0x00,0x00,0x00,0x00,0x0a, + 0xf6,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xdf,0x30,0x00,0x00,0x00, + 0x00,0x00,0x01,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xaf,0x50,0x00,0x01,0x10,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x37,0x72,0x00,0x00,0x00,0x00,0x00, + 0x00,0x03,0x40,0x02,0x50,0x00,0x00,0x00,0x00,0x57,0x30,0x57,0x20, + 0x00,0x00,0x00,0x01,0x5e,0xd5,0x00,0x00,0x00,0x00,0x58,0x61,0x00, + 0x00,0x58,0x20,0x00,0x00,0x00,0x02,0x77,0x62,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x75,0x00, + 0x00,0x00,0x00,0x00,0x00,0x02,0x85,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x37,0x30,0x00,0x01,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x05,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,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,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,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,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,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, + 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,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,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,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,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,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,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,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,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,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,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,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, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 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,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,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,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,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,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,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x0d,0xdd,0x20,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0c,0xdd,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x10,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xef, + 0xfc,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0xd0, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0f,0xff,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0e,0xff,0x40,0x00,0x00,0x00,0x0d,0xdd,0x20,0x00,0x00,0x00,0x00, + 0x01,0x9e,0xff,0xfc,0x50,0x00,0x00,0x00,0x00,0x03,0xdf,0xfe,0x20, + 0x00,0x00,0x00,0x02,0xcf,0xfa,0x4d,0xda,0x00,0x00,0x00,0x00,0x00, + 0x9d,0xd7,0x00,0x00,0x00,0x00,0x00,0x6d,0xd3,0x02,0xdd,0x60,0x00, + 0x00,0x2d,0xdd,0x40,0x0b,0xdd,0xa0,0x00,0x00,0x05,0xbb,0xff,0xf2, + 0x00,0x00,0x00,0x00,0x00,0x9d,0xdd,0xdd,0xdd,0x70,0x00,0x00,0x00, + 0x00,0x00,0x4c,0xff,0x50,0x00,0x00,0x00,0x00,0x0f,0xf0,0x00,0x00, + 0x00,0x00,0x00,0x5f,0xfc,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0f,0xff,0x33,0x54,0x10,0x00,0x00,0x00,0x00,0x03,0x54,0x1e,0xff, + 0x40,0x00,0x00,0x00,0x0f,0xff,0x30,0x00,0x00,0x00,0x00,0x0b,0xff, + 0xeb,0xef,0xf4,0x00,0x00,0x00,0x00,0x0b,0xff,0xff,0x10,0x00,0x00, + 0x00,0x0c,0xff,0xff,0xef,0xfb,0x00,0x00,0x00,0x00,0x01,0xff,0xfe, + 0x00,0x00,0x00,0x00,0x00,0xbf,0xf7,0x06,0xff,0xc0,0x00,0x00,0x06, + 0xff,0xe1,0x6f,0xff,0x20,0x00,0x00,0x00,0x00,0xaf,0xfa,0x00,0x00, + 0x00,0x00,0x00,0xaf,0xff,0xff,0xff,0x80,0x00,0x00,0x00,0x00,0x00, + 0xdf,0xff,0x50,0x00,0x00,0x00,0x00,0x0f,0xf0,0x00,0x00,0x00,0x00, + 0x00,0x5f,0xff,0xd0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x55,0x00,0x00,0x00,0x00,0x0f,0xff, + 0xdf,0xff,0xd2,0x00,0x00,0x00,0x01,0xbf,0xff,0xdf,0xff,0x40,0x00, + 0x00,0x00,0x0f,0xff,0x30,0x00,0x00,0x00,0x00,0x07,0x9a,0x30,0x5f, + 0xfa,0x00,0x00,0x00,0x00,0x0d,0xff,0x84,0x00,0x00,0x00,0x00,0x1f, + 0xff,0xb7,0xff,0xfb,0x00,0x00,0x00,0x00,0x07,0xff,0xff,0x50,0x00, + 0x00,0x00,0x01,0xff,0xfb,0x0c,0xff,0xf2,0x00,0x00,0x00,0xbf,0xfa, + 0xef,0xf6,0x00,0x00,0x00,0x00,0x00,0xdf,0xff,0x20,0x00,0x00,0x00, + 0x00,0x5f,0xff,0x94,0x44,0x20,0x00,0x00,0x00,0x00,0x00,0xff,0xf5, + 0x10,0x00,0x00,0x00,0x00,0x0f,0xf0,0x00,0x00,0x00,0x00,0x00,0x15, + 0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x5c,0xf7,0x00,0x00,0x00,0x00,0x0f,0xff,0xe9,0xef, + 0xfc,0x00,0x00,0x00,0x08,0xff,0xfa,0xdf,0xff,0x40,0x00,0x00,0x00, + 0x0f,0xff,0x30,0x00,0x00,0x00,0x00,0x00,0x15,0x9c,0xff,0xf8,0x00, + 0x00,0x00,0x00,0x0d,0xff,0x50,0x00,0x00,0x00,0x00,0x1f,0xff,0x20, + 0x8f,0xfb,0x00,0x00,0x00,0x00,0x0d,0xfd,0xef,0xc0,0x00,0x00,0x00, + 0x05,0xfd,0xff,0x2f,0xfd,0xf6,0x00,0x00,0x00,0x1e,0xff,0xff,0xb0, + 0x00,0x00,0x00,0x00,0x06,0xff,0xff,0x80,0x00,0x00,0x00,0x00,0x05, + 0xff,0xf5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xe0,0x00,0x00, + 0x00,0x00,0x00,0x0f,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0xf0, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x5c,0xff,0xf8,0x00,0x00,0x00,0x00,0x0f,0xff,0x50,0x3f,0xff,0x10, + 0x00,0x00,0x0d,0xff,0x60,0x1f,0xff,0x40,0x00,0x00,0x00,0x0f,0xff, + 0x40,0x00,0x00,0x00,0x00,0x03,0xef,0xff,0xff,0xc1,0x00,0x00,0x00, + 0x00,0x0d,0xff,0x50,0x00,0x00,0x00,0x00,0x1f,0xff,0x20,0x6f,0xfb, + 0x00,0x00,0x00,0x00,0x4f,0xf8,0x9f,0xf3,0x00,0x00,0x00,0x0b,0xf8, + 0xdf,0xaf,0xd8,0xfb,0x00,0x00,0x00,0x08,0xff,0xff,0x30,0x00,0x00, + 0x00,0x00,0x1e,0xfd,0xbf,0xf1,0x00,0x00,0x00,0x00,0x00,0x6f,0xff, + 0x40,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0xd0,0x00,0x00,0x00,0x00, + 0x00,0x0f,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0xdf,0xf2,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4c,0xff,0xff, + 0xff,0xee,0xe8,0x00,0x00,0x0f,0xff,0x30,0x1f,0xff,0x20,0x00,0x00, + 0x0d,0xff,0x50,0x0f,0xff,0x40,0x00,0x00,0x00,0x0f,0xff,0xa0,0x00, + 0x00,0x00,0x00,0x0a,0xff,0xc8,0x63,0x00,0x00,0x00,0x00,0x00,0x0d, + 0xff,0x50,0x00,0x00,0x00,0x00,0x1f,0xff,0x20,0x6f,0xfb,0x00,0x00, + 0x00,0x00,0xbf,0xf4,0x4f,0xf9,0x00,0x00,0x00,0x1f,0xf5,0x8f,0xff, + 0x84,0xff,0x10,0x00,0x00,0x2f,0xff,0xff,0xc0,0x00,0x00,0x00,0x00, + 0x7f,0xf7,0x5f,0xf7,0x00,0x00,0x00,0x00,0x00,0x06,0xff,0xf4,0x00, + 0x00,0x00,0x00,0x00,0x5e,0xff,0x90,0x00,0x00,0x00,0x00,0x00,0x0f, + 0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x9f,0xfe,0x50,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3a,0xff,0xff,0xfc,0x88, + 0x85,0x00,0x00,0x0f,0xff,0x91,0x7f,0xfe,0x00,0x00,0x00,0x0a,0xff, + 0xa1,0x5f,0xff,0x40,0x00,0x00,0x00,0x0f,0xff,0xfe,0xc0,0x00,0x00, + 0x00,0x0a,0xff,0x53,0xbc,0xb3,0x00,0x00,0x00,0x01,0xdf,0xff,0xed, + 0x10,0x00,0x00,0x00,0x1f,0xff,0x20,0x6f,0xfb,0x00,0x00,0x00,0x02, + 0xff,0xe0,0x0f,0xff,0x10,0x00,0x00,0x5f,0xf2,0x4f,0xff,0x41,0xff, + 0x50,0x00,0x00,0xcf,0xfa,0xdf,0xf7,0x00,0x00,0x00,0x01,0xef,0xf2, + 0x1f,0xfe,0x00,0x00,0x00,0x00,0x4a,0xaa,0xef,0xff,0x20,0x00,0x00, + 0x00,0x00,0x7f,0xfd,0x10,0x00,0x00,0x00,0x00,0x00,0x0f,0xf0,0x00, + 0x00,0x00,0x00,0x00,0x00,0x1d,0xff,0x70,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3a,0xff,0xf7,0x00,0x00,0x00, + 0x00,0x0f,0xff,0xff,0xff,0xf6,0x00,0x00,0x00,0x03,0xff,0xff,0xff, + 0xff,0x40,0x00,0x00,0x00,0x0f,0xff,0xcf,0xf3,0x00,0x00,0x00,0x03, + 0xff,0xff,0xff,0xc0,0x00,0x00,0x00,0x01,0xff,0xff,0xff,0x10,0x00, + 0x00,0x00,0x1f,0xff,0x20,0x6f,0xfb,0x00,0x00,0x00,0x08,0xff,0xa0, + 0x0a,0xff,0x70,0x00,0x00,0x9f,0xe0,0x1f,0xfe,0x10,0xdf,0xa0,0x00, + 0x08,0xff,0xf2,0x4f,0xff,0x30,0x00,0x00,0x08,0xff,0xb0,0x0a,0xff, + 0x60,0x00,0x00,0x00,0x5f,0xff,0xff,0xff,0x50,0x00,0x00,0x00,0x00, + 0x4d,0xff,0x90,0x00,0x00,0x00,0x00,0x00,0x0f,0xf0,0x00,0x00,0x00, + 0x00,0x00,0x00,0x9f,0xfd,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x3a,0xf7,0x00,0x00,0x00,0x00,0x0b, + 0xba,0x3a,0xdc,0x60,0x00,0x00,0x00,0x00,0x3b,0xdb,0x57,0xbb,0x30, + 0x00,0x00,0x00,0x06,0x66,0x18,0x82,0x00,0x00,0x00,0x00,0x27,0x99, + 0x85,0x00,0x00,0x00,0x00,0x00,0x6e,0xff,0x96,0x00,0x00,0x00,0x00, + 0x06,0x66,0x10,0x36,0x65,0x00,0x00,0x00,0x05,0x66,0x30,0x03,0x66, + 0x50,0x00,0x00,0x56,0x50,0x05,0x65,0x00,0x46,0x60,0x00,0x06,0x66, + 0x40,0x05,0x66,0x50,0x00,0x00,0x06,0x66,0x30,0x02,0x66,0x50,0x00, + 0x00,0x00,0x26,0x66,0x66,0x66,0x20,0x00,0x00,0x00,0x00,0x02,0xff, + 0xc0,0x00,0x00,0x00,0x00,0x00,0x0f,0xf0,0x00,0x00,0x00,0x00,0x00, + 0x00,0xcf,0xf2,0x00,0x00,0x00,0x00,0x01,0x55,0x10,0x55,0x10,0x00, + 0x00,0x00,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x0d,0xff,0x50,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xd0,0x00, + 0x00,0x00,0x00,0x00,0x0f,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0xdf, + 0xf0,0x00,0x00,0x00,0x00,0x04,0xff,0x43,0xff,0x50,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x02,0xaf,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xf5,0x10,0x00,0x00, + 0x00,0x00,0x0f,0xf0,0x00,0x00,0x00,0x00,0x00,0x15,0xff,0xf0,0x00, + 0x00,0x00,0x00,0x08,0xff,0x76,0xff,0x90,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x02,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0xff,0x50,0x00,0x00,0x00,0x00, + 0x0f,0xf0,0x00,0x00,0x00,0x00,0x00,0x5f,0xff,0xc0,0x00,0x00,0x00, + 0x00,0x09,0xff,0x87,0xff,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x3c,0xff,0x50,0x00,0x00,0x00,0x00,0x0c,0xc0, + 0x00,0x00,0x00,0x00,0x00,0x5f,0xfc,0x30,0x00,0x00,0x00,0x00,0x08, + 0xcc,0x76,0xcc,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 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,0x8d,0xff,0xfd,0x91,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x7f,0xfb,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x06,0xbc,0xb5,0x29,0x97,0x00,0x00,0x00, + 0x99,0x91,0x9c,0xa3,0x00,0x00,0x00,0x00,0x06,0xac,0xca,0x60,0x00, + 0x00,0x00,0x00,0x8f,0xfd,0x3d,0xdc,0x00,0x00,0x00,0x00,0x07,0xbc, + 0xca,0x60,0x00,0x00,0x00,0x00,0x09,0xdd,0x60,0x00,0x00,0x00,0x00, + 0x07,0xff,0xea,0xcf,0xfc,0x00,0x00,0x00,0x0b,0xdd,0x50,0x2d,0xdd, + 0x00,0x00,0x00,0x00,0x00,0xcd,0xd3,0x00,0x00,0x00,0x00,0x00,0x7f, + 0xff,0x90,0x00,0x00,0x00,0x00,0x01,0xdd,0xd2,0x02,0xdd,0xd6,0x00, + 0x00,0x00,0x00,0x0d,0xdd,0x30,0x00,0x00,0x00,0xdd,0xc0,0x1d,0xdc, + 0x01,0xdd,0xb0,0x00,0x01,0xdd,0xd2,0x06,0xdd,0xa0,0x00,0x00,0x00, + 0x05,0xac,0xc9,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x6f,0xff,0xff,0xef,0xf8,0x00,0x00,0x00,0xff,0xfd, + 0xff,0xff,0x40,0x00,0x00,0x01,0xcf,0xff,0xff,0xfb,0x00,0x00,0x00, + 0x07,0xff,0xff,0xef,0xfe,0x00,0x00,0x00,0x01,0xcf,0xff,0xff,0xfb, + 0x00,0x00,0x00,0x00,0x0a,0xff,0x70,0x00,0x00,0x00,0x00,0x06,0x86, + 0x30,0x1f,0xff,0x30,0x00,0x00,0x0c,0xff,0x50,0x3f,0xff,0x00,0x00, + 0x00,0x00,0x00,0xef,0xf4,0x00,0x00,0x00,0x00,0x00,0x1a,0xff,0xb0, + 0x00,0x00,0x00,0x00,0x01,0xff,0xf3,0x09,0xff,0xd0,0x00,0x00,0x00, + 0x00,0x0e,0xff,0x40,0x00,0x00,0x00,0xff,0xe0,0x1f,0xfd,0x01,0xff, + 0xd0,0x00,0x01,0xff,0xf2,0x06,0xff,0xb0,0x00,0x00,0x00,0xaf,0xff, + 0xff,0xf6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xaf,0xf9,0x03,0xef,0xf7,0x00,0x00,0x00,0xff,0xfe,0x8d,0xff, + 0xc0,0x00,0x00,0x08,0xff,0xe6,0x6e,0xff,0x60,0x00,0x00,0x0e,0xff, + 0xa4,0xcf,0xfe,0x00,0x00,0x00,0x07,0xff,0xc2,0x3b,0xb9,0x30,0x00, + 0x00,0x00,0x0a,0xff,0x70,0x00,0x00,0x00,0x00,0x00,0x5c,0xed,0x6e, + 0xff,0x40,0x00,0x00,0x0c,0xff,0x50,0x3f,0xff,0x00,0x00,0x00,0x00, + 0x00,0xef,0xf4,0x00,0x00,0x00,0x00,0x00,0x06,0xff,0xb0,0x00,0x00, + 0x00,0x00,0x01,0xff,0xf6,0x2f,0xff,0x40,0x00,0x00,0x00,0x00,0x0e, + 0xff,0x40,0x00,0x00,0x00,0xff,0xe0,0x1f,0xfd,0x01,0xff,0xd0,0x00, + 0x01,0xff,0xf2,0x06,0xff,0xb0,0x00,0x00,0x07,0xff,0xe6,0x7f,0xff, + 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f, + 0xfd,0x40,0xaf,0xf7,0x00,0x00,0x00,0xff,0xf5,0x03,0xff,0xf1,0x00, + 0x00,0x0d,0xff,0x60,0x04,0x86,0x30,0x00,0x00,0x2f,0xff,0x10,0x5f, + 0xfe,0x00,0x00,0x00,0x0d,0xff,0x84,0x44,0x44,0x20,0x00,0x00,0x00, + 0x0a,0xff,0x70,0x00,0x00,0x00,0x00,0x05,0xff,0xfd,0xff,0xff,0x40, + 0x00,0x00,0x0c,0xff,0x50,0x3f,0xff,0x00,0x00,0x00,0x00,0x00,0xef, + 0xf4,0x00,0x00,0x00,0x00,0x00,0x06,0xff,0xb0,0x00,0x00,0x00,0x00, + 0x01,0xff,0xff,0xdf,0xfb,0x00,0x00,0x00,0x00,0x00,0x0e,0xff,0x40, + 0x00,0x00,0x00,0xff,0xe0,0x1f,0xfd,0x01,0xff,0xd0,0x00,0x01,0xff, + 0xf2,0x06,0xff,0xb0,0x00,0x00,0x0c,0xff,0x60,0x0b,0xff,0x70,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0xef,0xff, + 0xef,0xf7,0x00,0x00,0x00,0xff,0xf3,0x01,0xff,0xf2,0x00,0x00,0x0e, + 0xff,0x40,0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0x00,0x4f,0xfe,0x00, + 0x00,0x00,0x0e,0xff,0xff,0xff,0xff,0xa0,0x00,0x00,0x00,0x0a,0xff, + 0x70,0x00,0x00,0x00,0x00,0x0c,0xff,0x70,0x2f,0xff,0x40,0x00,0x00, + 0x0c,0xff,0x60,0x3f,0xff,0x00,0x00,0x00,0x00,0x00,0xef,0xf4,0x00, + 0x00,0x00,0x00,0x00,0x06,0xff,0xb0,0x00,0x00,0x00,0x00,0x01,0xff, + 0xff,0xff,0xf2,0x00,0x00,0x00,0x00,0x00,0x0e,0xff,0x40,0x00,0x00, + 0x00,0xff,0xe0,0x1f,0xfd,0x01,0xff,0xd0,0x00,0x01,0xff,0xf2,0x06, + 0xff,0xb0,0x00,0x00,0x0e,0xff,0x40,0x08,0xff,0x90,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x6a,0xff,0xf7, + 0x00,0x00,0x00,0xff,0xf5,0x03,0xff,0xf1,0x00,0x00,0x0d,0xff,0x60, + 0x03,0x31,0x00,0x00,0x00,0x1f,0xff,0x40,0x7f,0xfe,0x00,0x00,0x00, + 0x0d,0xff,0x95,0x5c,0xff,0x80,0x00,0x00,0x00,0x0a,0xff,0x70,0x00, + 0x00,0x00,0x00,0x0e,0xff,0x40,0x0f,0xff,0x40,0x00,0x00,0x0c,0xff, + 0xa0,0x5f,0xff,0x00,0x00,0x00,0x00,0x00,0xef,0xf4,0x00,0x00,0x00, + 0x00,0x00,0x06,0xff,0xb0,0x00,0x00,0x00,0x00,0x01,0xff,0xff,0xff, + 0xa0,0x00,0x00,0x00,0x00,0x00,0x0e,0xff,0x40,0x00,0x00,0x00,0xff, + 0xf3,0x2f,0xff,0x23,0xff,0xd0,0x00,0x01,0xff,0xf6,0x09,0xff,0xb0, + 0x00,0x00,0x0d,0xff,0x60,0x0a,0xff,0x80,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x4c,0xed,0x21,0xbf,0xf6,0x00,0x00, + 0x00,0xff,0xfe,0x8d,0xff,0xd0,0x00,0x00,0x08,0xff,0xe5,0x5e,0xff, + 0x50,0x00,0x00,0x0c,0xff,0xfc,0xff,0xfe,0x00,0x00,0x00,0x08,0xff, + 0xb1,0x2e,0xff,0x40,0x00,0x00,0x00,0xcf,0xff,0xed,0x00,0x00,0x00, + 0x00,0x0d,0xff,0x91,0x6f,0xff,0x40,0x00,0x00,0x0c,0xff,0xfe,0xff, + 0xfe,0x00,0x00,0x00,0x00,0x00,0xef,0xf4,0x00,0x00,0x00,0x00,0x00, + 0x06,0xff,0xb0,0x00,0x00,0x00,0x00,0x01,0xff,0xf5,0xef,0xf8,0x00, + 0x00,0x00,0x00,0x00,0x0e,0xff,0x40,0x00,0x00,0x00,0xff,0xff,0xff, + 0xff,0xff,0xff,0xb0,0x00,0x01,0xff,0xff,0xef,0xff,0xa0,0x00,0x00, + 0x07,0xff,0xe5,0x6f,0xff,0x30,0x00,0x00,0x00,0x03,0x54,0x00,0x00, + 0x00,0x00,0x00,0x00,0x1e,0xff,0xff,0xff,0xe1,0x00,0x00,0x00,0xff, + 0xff,0xff,0xff,0x50,0x00,0x00,0x01,0xcf,0xff,0xff,0xfb,0x00,0x00, + 0x00,0x03,0xff,0xff,0xef,0xfe,0x00,0x00,0x00,0x01,0xcf,0xff,0xff, + 0xf9,0x00,0x00,0x00,0x00,0xdf,0xff,0xff,0x00,0x00,0x00,0x00,0x06, + 0xff,0xff,0xff,0xff,0x40,0x00,0x00,0x0c,0xff,0xcf,0xff,0xf7,0x00, + 0x00,0x00,0x00,0x00,0xef,0xf4,0x00,0x00,0x00,0x00,0x00,0x06,0xff, + 0xb0,0x00,0x00,0x00,0x00,0x01,0xff,0xf3,0x4f,0xff,0x80,0x00,0x00, + 0x00,0x00,0x0e,0xff,0x40,0x00,0x00,0x00,0xff,0xde,0xff,0xf9,0xef, + 0xff,0x50,0x00,0x01,0xff,0xea,0xff,0xff,0x40,0x00,0x00,0x00,0xbf, + 0xff,0xff,0xf8,0x00,0x00,0x00,0x00,0x0b,0xfc,0x00,0x00,0x00,0x00, + 0x00,0x00,0x02,0x8c,0xdd,0xc9,0x20,0x00,0x00,0x00,0xff,0xf5,0xad, + 0xb4,0x00,0x00,0x00,0x00,0x17,0xbd,0xdb,0x60,0x00,0x00,0x00,0x00, + 0x28,0x96,0x4f,0xfe,0x00,0x00,0x00,0x00,0x17,0xbd,0xdb,0x50,0x00, + 0x00,0x00,0x00,0x6d,0xff,0xb6,0x00,0x00,0x00,0x00,0x00,0x5b,0xdb, + 0x57,0xbb,0x20,0x00,0x00,0x0c,0xff,0x53,0x89,0x50,0x00,0x00,0x00, + 0x00,0x00,0x66,0x62,0x00,0x00,0x00,0x00,0x00,0x06,0xff,0xb0,0x00, + 0x00,0x00,0x00,0x01,0xff,0xf3,0x04,0x66,0x62,0x00,0x00,0x00,0x00, + 0x0e,0xff,0x40,0x00,0x00,0x00,0x66,0x51,0x89,0x60,0x28,0x95,0x00, + 0x00,0x00,0x66,0x60,0x59,0x93,0x00,0x00,0x00,0x00,0x06,0xbd,0xda, + 0x40,0x00,0x00,0x00,0x00,0x0f,0xff,0x10,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xf3,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x4f,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x09,0xff,0xb4,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x0c,0xff,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x88,0x82,0x00,0x00,0x00,0x00,0x00,0x01,0x33,0x20,0x00,0x00,0x00, + 0x00,0x01,0xff,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xff, + 0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x1f,0xff,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xf3,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4f,0xfe, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06, + 0xff,0xff,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x0c,0xff,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0xf4, + 0x00,0x00,0x00,0x00,0x00,0x06,0xff,0xb0,0x00,0x00,0x00,0x00,0x01, + 0xff,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xff,0x40,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x1c,0xcc,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xcc,0xc2,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x88,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6b,0xba, + 0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07, + 0x88,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x82,0x00,0x00, + 0x00,0x00,0x00,0x05,0xcc,0x90,0x00,0x00,0x00,0x00,0x01,0x88,0x81, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x88,0x20,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x0d,0xdd,0xda,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xad,0xdd,0xd0,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xbd,0xda,0x00,0x00,0x00,0x00,0x00,0x00,0x17, + 0xac,0xca,0x6d,0xfe,0x10,0x00,0x3d,0xdd,0x40,0x03,0xdd,0xda,0x00, + 0x00,0x00,0x04,0x9c,0xcc,0x94,0x00,0x00,0x00,0x00,0x0a,0xdd,0xb0, + 0x00,0x00,0x00,0x00,0x00,0x19,0xef,0xff,0xd8,0x00,0x00,0x00,0x00, + 0x00,0xad,0xdd,0x50,0x00,0x00,0x00,0x01,0xdd,0xc0,0x01,0xdd,0xc0, + 0x00,0x01,0xcd,0xdc,0x10,0x01,0xdd,0xdb,0x00,0x00,0x00,0x00,0x6d, + 0xdd,0x10,0x00,0x00,0x00,0x0d,0xdd,0xdd,0xdd,0xdd,0xdc,0x00,0x00, + 0x00,0x00,0x0f,0xff,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x9a,0x00, + 0x00,0x00,0x00,0x00,0xcf,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0, + 0x00,0x00,0xcf,0xfb,0x00,0x00,0x00,0x00,0x00,0x03,0xef,0xff,0xff, + 0xff,0xf6,0x00,0x00,0x4f,0xff,0x40,0x0b,0xff,0xf4,0x00,0x00,0x00, + 0x9f,0xff,0xff,0xff,0x90,0x00,0x00,0x00,0x0b,0xff,0xc0,0x00,0x00, + 0x00,0x00,0x01,0xdf,0xff,0xff,0xff,0xb0,0x00,0x00,0x00,0x02,0xff, + 0xff,0xb0,0x00,0x00,0x00,0x03,0xff,0xf2,0x04,0xff,0xf1,0x00,0x00, + 0x5f,0xff,0x80,0x0a,0xff,0xf4,0x00,0x00,0x00,0x00,0x7f,0xff,0x10, + 0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xfd,0x00,0x00,0x00,0x00, + 0x0f,0xff,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0xf9,0x00,0x00,0x00, + 0x00,0x00,0x67,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00, + 0xcf,0xfb,0x00,0x00,0x00,0x00,0x00,0x2e,0xff,0xfd,0xef,0xff,0xd1, + 0x00,0x00,0x4f,0xff,0x50,0x4f,0xff,0xc0,0x00,0x00,0x03,0xff,0xfc, + 0x79,0xff,0xf4,0x00,0x00,0x00,0x0b,0xff,0xc0,0x00,0x00,0x00,0x00, + 0x09,0xff,0xfd,0xae,0xff,0xf6,0x00,0x00,0x00,0x08,0xff,0xff,0xf2, + 0x00,0x00,0x00,0x05,0xff,0xf6,0x07,0xff,0xf4,0x00,0x00,0x0a,0xff, + 0xf3,0x4f,0xff,0x90,0x00,0x00,0x00,0x00,0x7f,0xff,0x10,0x00,0x00, + 0x00,0x0d,0xff,0xfb,0x88,0x88,0x87,0x00,0x00,0x00,0x00,0x0f,0xfe, + 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xf5,0x00,0x00,0x00,0x00,0x00, + 0x00,0xef,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0xfb, + 0x00,0x00,0x00,0x00,0x00,0x8f,0xff,0x55,0xef,0xff,0xf6,0x00,0x00, + 0x4f,0xff,0x50,0xcf,0xff,0x30,0x00,0x00,0x09,0xff,0xe1,0x00,0xcf, + 0xf9,0x00,0x00,0x00,0x0b,0xff,0xc0,0x00,0x00,0x00,0x00,0x0e,0xff, + 0xc0,0x01,0xef,0xfb,0x00,0x00,0x00,0x0d,0xff,0xdf,0xf7,0x00,0x00, + 0x00,0x08,0xff,0xf9,0x0a,0xff,0xf7,0x00,0x00,0x01,0xef,0xfc,0xdf, + 0xfe,0x10,0x00,0x00,0x00,0x00,0x7f,0xff,0x10,0x00,0x00,0x00,0x02, + 0xef,0xfe,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xfe,0x00,0x00, + 0x00,0x00,0x00,0x00,0x07,0xf2,0x00,0x00,0x00,0x00,0x00,0x00,0xef, + 0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0xfe,0x99,0x96, + 0x10,0x00,0x00,0xdf,0xfc,0x06,0xb2,0xef,0xfa,0x00,0x00,0x4f,0xff, + 0x79,0xff,0xf6,0x00,0x00,0x00,0x02,0x34,0x40,0x16,0xff,0xfa,0x00, + 0x00,0x00,0x0b,0xff,0xc0,0x00,0x00,0x00,0x00,0x1f,0xff,0x80,0x00, + 0xaf,0xfd,0x00,0x00,0x00,0x4f,0xff,0x5f,0xfd,0x00,0x00,0x00,0x0a, + 0xff,0xfc,0x0e,0xff,0xf9,0x00,0x00,0x00,0x5f,0xff,0xff,0xf4,0x00, + 0x00,0x00,0x00,0x00,0x7f,0xff,0x10,0x00,0x00,0x00,0x00,0x2e,0xff, + 0xe2,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xfe,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0b,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0xf0,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0xff,0xff,0xff,0xd1,0x00, + 0x00,0xff,0xf9,0x00,0x00,0xcf,0xfc,0x00,0x00,0x4f,0xff,0xff,0xff, + 0xd6,0x00,0x00,0x00,0x00,0x01,0x7c,0xff,0xff,0xf5,0x00,0x00,0x00, + 0x0b,0xff,0xc0,0x00,0x00,0x00,0x00,0x1f,0xff,0x70,0x00,0xaf,0xfd, + 0x00,0x00,0x00,0xaf,0xfa,0x1f,0xff,0x30,0x00,0x00,0x0e,0xfd,0xff, + 0x3f,0xfd,0xfc,0x00,0x00,0x00,0x0a,0xff,0xff,0xa0,0x00,0x00,0x00, + 0x00,0x01,0xdf,0xff,0x70,0x00,0x00,0x00,0x00,0x03,0xef,0xfe,0x20, + 0x00,0x00,0x00,0x00,0x00,0x0f,0xfe,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0f,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0xef,0xf0,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xcf,0xfe,0xac,0xff,0xf9,0x00,0x00,0xff, + 0xf8,0x00,0x00,0xcf,0xfc,0x00,0x00,0x4f,0xff,0xfe,0xff,0xff,0x70, + 0x00,0x00,0x00,0x5f,0xff,0xff,0xff,0x90,0x00,0x00,0x00,0x0b,0xff, + 0xc0,0x00,0x00,0x00,0x00,0x1f,0xff,0x70,0x00,0xaf,0xfd,0x00,0x00, + 0x01,0xff,0xf5,0x0a,0xff,0x90,0x00,0x00,0x1f,0xf8,0xff,0xaf,0xe8, + 0xff,0x00,0x00,0x00,0x08,0xff,0xff,0x90,0x00,0x00,0x00,0x00,0x08, + 0xff,0xff,0xf2,0x00,0x00,0x00,0x00,0x00,0x3e,0xff,0xd1,0x00,0x00, + 0x00,0x00,0x00,0x0f,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x60, + 0x00,0x00,0x00,0x00,0x00,0x00,0xef,0xf0,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xcf,0xfb,0x00,0xbf,0xfd,0x00,0x00,0xef,0xfb,0x00, + 0x00,0xef,0xfa,0x00,0x00,0x4f,0xff,0x50,0x1b,0xff,0xf0,0x00,0x00, + 0x01,0xff,0xff,0xfd,0x83,0x00,0x00,0x00,0x00,0x0b,0xff,0xc0,0x00, + 0x00,0x00,0x00,0x1f,0xff,0x70,0x00,0xaf,0xfd,0x00,0x00,0x06,0xff, + 0xf1,0x05,0xff,0xf1,0x00,0x00,0x4f,0xf5,0xcf,0xff,0xa6,0xff,0x20, + 0x00,0x00,0x3f,0xff,0xff,0xf4,0x00,0x00,0x00,0x00,0x3f,0xff,0xff, + 0xfc,0x00,0x00,0x00,0x00,0x00,0x03,0xff,0xfd,0x10,0x00,0x00,0x00, + 0x00,0x0f,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x20,0x00,0x00, + 0x00,0x00,0x00,0x00,0xef,0xf0,0x00,0x00,0x00,0x00,0x01,0xde,0xa0, + 0x0a,0xec,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xcf,0xfb,0x00,0xbf,0xfd,0x00,0x00,0x9f,0xff,0x30,0x05,0xff, + 0xf7,0x00,0x00,0x4f,0xff,0x50,0x09,0xff,0xf1,0x00,0x00,0x03,0xff, + 0xf6,0x11,0x98,0x72,0x00,0x01,0x44,0x4c,0xff,0xd4,0x44,0x20,0x00, + 0x00,0x1f,0xff,0x70,0x00,0xaf,0xfd,0x00,0x00,0x0c,0xff,0xb0,0x01, + 0xff,0xf5,0x00,0x00,0x6f,0xf3,0x8f,0xff,0x74,0xff,0x50,0x00,0x01, + 0xdf,0xfc,0xbf,0xfd,0x10,0x00,0x00,0x01,0xdf,0xfd,0x4f,0xff,0x70, + 0x00,0x00,0x00,0x00,0x00,0x4f,0xff,0xc1,0x00,0x00,0x00,0x00,0x0f, + 0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0xbe,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xef,0xf0,0x00,0x00,0x00,0x00,0x00,0x6f,0xf3,0x3f,0xf5, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf, + 0xfe,0xbd,0xff,0xfa,0x00,0x00,0x3f,0xff,0xfb,0xcf,0xff,0xe1,0x00, + 0x00,0x4f,0xff,0xdb,0xcf,0xff,0xe0,0x00,0x00,0x02,0xff,0xf5,0x29, + 0xff,0xf2,0x00,0x05,0xff,0xff,0xff,0xff,0xff,0x60,0x00,0x00,0x1f, + 0xff,0x70,0x00,0xaf,0xfd,0x00,0x00,0x2f,0xff,0x60,0x00,0xbf,0xfb, + 0x00,0x00,0x9f,0xf0,0x5f,0xff,0x42,0xff,0x80,0x00,0x08,0xff,0xf3, + 0x2f,0xff,0x80,0x00,0x00,0x08,0xff,0xf4,0x0a,0xff,0xf2,0x00,0x00, + 0x05,0xdd,0xdd,0xdf,0xff,0xf9,0x00,0x00,0x00,0x00,0x0f,0xfe,0x00, + 0x00,0x00,0x00,0x00,0x00,0xea,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xef,0xf0,0x00,0x00,0x00,0x00,0x00,0x0b,0xfb,0xbf,0xa0,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0xff,0xff, + 0xff,0xe2,0x00,0x00,0x06,0xff,0xff,0xff,0xff,0x40,0x00,0x00,0x4f, + 0xff,0xff,0xff,0xff,0x50,0x00,0x00,0x00,0x9f,0xff,0xff,0xff,0x90, + 0x00,0x05,0xff,0xff,0xff,0xff,0xff,0x60,0x00,0x00,0x1f,0xff,0x70, + 0x00,0xaf,0xfd,0x00,0x00,0x8f,0xff,0x10,0x00,0x6f,0xff,0x20,0x00, + 0xcf,0xd0,0x2f,0xff,0x00,0xff,0xa0,0x00,0x3f,0xff,0x90,0x08,0xff, + 0xf3,0x00,0x00,0x3f,0xff,0x90,0x02,0xff,0xfc,0x00,0x00,0x05,0xff, + 0xff,0xff,0xff,0xf9,0x00,0x00,0x00,0x00,0x0f,0xff,0x86,0x00,0x00, + 0x00,0x00,0x03,0xf6,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0xff,0xf0, + 0x00,0x00,0x00,0x00,0x00,0x02,0xff,0xfe,0x10,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x88,0x88,0x86,0x10, + 0x00,0x00,0x00,0x39,0xef,0xfd,0x92,0x00,0x00,0x00,0x28,0x88,0x88, + 0x88,0x62,0x00,0x00,0x00,0x00,0x06,0xcf,0xff,0xc6,0x00,0x00,0x03, + 0x88,0x88,0x88,0x88,0x88,0x40,0x00,0x00,0x18,0x88,0x40,0x00,0x68, + 0x87,0x00,0x00,0x78,0x87,0x00,0x00,0x18,0x88,0x30,0x00,0x88,0x60, + 0x08,0x87,0x00,0x78,0x70,0x00,0x68,0x88,0x10,0x01,0x88,0x86,0x00, + 0x00,0x68,0x88,0x10,0x00,0x58,0x88,0x30,0x00,0x03,0x88,0x88,0x88, + 0x88,0x85,0x00,0x00,0x00,0x00,0x0f,0xff,0xfc,0x00,0x00,0x00,0x00, + 0x06,0xf2,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0xff,0xf0,0x00,0x00, + 0x00,0x00,0x00,0x00,0x6f,0xf5,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x0c,0xcc,0xca,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xac,0xcc,0xc0,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,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,0x5a,0xbb,0x83,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3d,0xd8, + 0x67,0xbf,0xb1,0x00,0x00,0x8d,0xdd,0x10,0x00,0x1d,0xdd,0x80,0x00, + 0x0b,0xdd,0xdd,0xdd,0xc9,0x20,0x00,0x00,0x00,0x17,0xbc,0xca,0x50, + 0x00,0x00,0x00,0x0d,0xdd,0xdd,0xdb,0x71,0x00,0x00,0x00,0x4d,0xdd, + 0xdd,0xdd,0xdd,0x30,0x00,0x00,0x00,0xbd,0xda,0x00,0x00,0x00,0x00, + 0x00,0x00,0x17,0xac,0xcb,0x83,0x00,0x00,0x00,0x1d,0xdd,0x60,0x00, + 0x9d,0xdc,0x00,0x00,0x00,0x0d,0xdd,0x80,0x00,0x00,0x00,0x00,0x00, + 0x17,0xbc,0xc8,0x20,0x00,0x00,0x00,0x4d,0xdd,0x30,0x00,0xad,0xdd, + 0x70,0x00,0x01,0xdd,0xdd,0xdd,0xdd,0xd0,0x00,0x02,0xdd,0xa0,0x1d, + 0xda,0x01,0xdd,0xb0,0x00,0x0b,0xdd,0x60,0x00,0x6d,0xdd,0x20,0x00, + 0x00,0x17,0xac,0xca,0x61,0x00,0x00,0x00,0x02,0xe8,0x00,0x00,0x02, + 0xbc,0x10,0x00,0x3f,0xff,0x40,0x00,0x5f,0xff,0x30,0x00,0x0c,0xff, + 0xff,0xff,0xff,0xf2,0x00,0x00,0x04,0xef,0xff,0xff,0xfa,0x00,0x00, + 0x00,0x0f,0xff,0xff,0xff,0xfe,0x20,0x00,0x00,0x5f,0xff,0xff,0xff, + 0xff,0x40,0x00,0x00,0x00,0xcf,0xfb,0x00,0x00,0x00,0x00,0x00,0x03, + 0xef,0xff,0xff,0xff,0xa2,0x00,0x00,0x1f,0xff,0x70,0x00,0xaf,0xfd, + 0x00,0x00,0x00,0x0e,0xff,0x90,0x00,0x00,0x00,0x00,0x01,0xef,0xff, + 0xff,0xf3,0x00,0x00,0x00,0x5f,0xff,0x40,0x04,0xff,0xfe,0x10,0x00, + 0x01,0xff,0xff,0xff,0xff,0xf0,0x00,0x02,0xff,0xb0,0x5f,0xff,0x11, + 0xff,0xc0,0x00,0x0c,0xff,0x70,0x02,0xff,0xff,0x20,0x00,0x03,0xef, + 0xff,0xff,0xfd,0x20,0x00,0x00,0x0b,0x83,0xdf,0x89,0xfb,0x20,0x00, + 0x00,0x0d,0xff,0xff,0xff,0xff,0xfd,0x00,0x00,0x0c,0xff,0xe8,0x8b, + 0xff,0xf9,0x00,0x00,0x2e,0xff,0xfe,0xff,0xff,0x70,0x00,0x00,0x0f, + 0xff,0xeb,0xdf,0xff,0xc0,0x00,0x00,0x5f,0xff,0xcb,0xbb,0xbb,0x30, + 0x00,0x00,0x00,0xcf,0xfb,0x00,0x00,0x00,0x00,0x00,0x1e,0xff,0xfc, + 0xbe,0xff,0xf9,0x00,0x00,0x1f,0xff,0x70,0x00,0xaf,0xfd,0x00,0x00, + 0x00,0x0e,0xff,0x90,0x00,0x00,0x00,0x00,0x09,0xff,0xfe,0xff,0xfd, + 0x00,0x00,0x00,0x5f,0xff,0x40,0x0b,0xff,0xf5,0x00,0x00,0x01,0xff, + 0xff,0xee,0xee,0xe0,0x00,0x02,0xff,0xb0,0x9f,0xff,0x41,0xff,0xc0, + 0x00,0x0c,0xff,0x70,0x0c,0xff,0xff,0x20,0x00,0x2e,0xff,0xfd,0xef, + 0xff,0xd1,0x00,0x00,0x3f,0x2e,0xc3,0xbf,0xb8,0xe3,0x00,0x00,0x07, + 0xff,0xff,0xff,0xff,0xf7,0x00,0x00,0x0c,0xff,0xb0,0x00,0xdf,0xfb, + 0x00,0x00,0x8f,0xff,0x40,0x1b,0xff,0xe0,0x00,0x00,0x0f,0xff,0x80, + 0x08,0xff,0xf3,0x00,0x00,0x5f,0xff,0x40,0x00,0x00,0x00,0x00,0x00, + 0x00,0xcf,0xfb,0x00,0x00,0x00,0x00,0x00,0x8f,0xff,0x40,0x00,0xaf, + 0xf9,0x00,0x00,0x1f,0xff,0x70,0x00,0xaf,0xfd,0x00,0x00,0x00,0x0e, + 0xff,0x90,0x00,0x00,0x00,0x00,0x0e,0xff,0x90,0x8f,0xff,0x20,0x00, + 0x00,0x5f,0xff,0xc1,0x4f,0xff,0xc0,0x00,0x00,0x01,0xff,0xf7,0x00, + 0x00,0x00,0x00,0x02,0xff,0xb0,0xdf,0xff,0x81,0xff,0xc0,0x00,0x0c, + 0xff,0x70,0x7f,0xff,0xff,0x20,0x00,0x8f,0xff,0x50,0x07,0xff,0xf6, + 0x00,0x00,0x6b,0x4f,0x50,0x2f,0xa0,0x8c,0x00,0x00,0x02,0xff,0xfa, + 0x7a,0xff,0xf2,0x00,0x00,0x0c,0xff,0xc2,0x24,0xff,0xf8,0x00,0x00, + 0xdf,0xfb,0x00,0x02,0xe9,0x50,0x00,0x00,0x0f,0xff,0x80,0x02,0xff, + 0xf6,0x00,0x00,0x5f,0xff,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0xcf, + 0xfc,0x33,0x33,0x10,0x00,0x00,0xdf,0xfc,0x00,0x67,0xbf,0xf9,0x00, + 0x00,0x1f,0xff,0x94,0x44,0xcf,0xfd,0x00,0x00,0x00,0x0e,0xff,0x90, + 0x00,0x00,0x00,0x00,0x05,0x79,0x40,0x5f,0xff,0x30,0x00,0x00,0x5f, + 0xff,0xfc,0xcf,0xff,0x20,0x00,0x00,0x01,0xff,0xf7,0x00,0x00,0x00, + 0x00,0x02,0xff,0xb2,0xff,0xff,0xc1,0xff,0xc0,0x00,0x0c,0xff,0x73, + 0xff,0xff,0xff,0x20,0x00,0xdf,0xfb,0x00,0x00,0xef,0xfa,0x00,0x00, + 0x7a,0x5f,0x50,0x0d,0xd0,0x1f,0x20,0x00,0x00,0xbf,0xf8,0x09,0xff, + 0xb0,0x00,0x00,0x0c,0xff,0xff,0xff,0xff,0xb1,0x00,0x00,0xff,0xf9, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0x80,0x01,0xff,0xf7,0x00, + 0x00,0x5f,0xff,0xff,0xff,0xfa,0x00,0x00,0x00,0x00,0xcf,0xff,0xff, + 0xff,0x30,0x00,0x00,0xff,0xf9,0x00,0xcf,0xff,0xf9,0x00,0x00,0x1f, + 0xff,0xff,0xff,0xff,0xfd,0x00,0x00,0x00,0x0e,0xff,0x90,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x5f,0xff,0x40,0x00,0x00,0x5f,0xff,0xff, + 0xff,0xf8,0x00,0x00,0x00,0x01,0xff,0xf7,0x00,0x00,0x00,0x00,0x02, + 0xff,0xb5,0xff,0x8f,0xf2,0xff,0xc0,0x00,0x0c,0xff,0x8d,0xff,0xcf, + 0xff,0x20,0x00,0xff,0xf9,0x00,0x00,0xcf,0xfc,0x00,0x00,0x7a,0x3f, + 0x70,0x0a,0xf0,0x0d,0x50,0x00,0x00,0x5f,0xfc,0x0e,0xff,0x50,0x00, + 0x00,0x0c,0xff,0xff,0xff,0xfd,0x30,0x00,0x00,0xff,0xf8,0x00,0x00, + 0x00,0x00,0x00,0x00,0x0f,0xff,0x80,0x01,0xff,0xf7,0x00,0x00,0x5f, + 0xff,0xff,0xff,0xfa,0x00,0x00,0x00,0x00,0xcf,0xff,0xff,0xff,0x30, + 0x00,0x00,0xff,0xf9,0x00,0xbd,0xdd,0xd8,0x00,0x00,0x1f,0xff,0xff, + 0xff,0xff,0xfd,0x00,0x00,0x00,0x0e,0xff,0x90,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x5f,0xff,0x40,0x00,0x00,0x5f,0xff,0xff,0xff,0xe1, + 0x00,0x00,0x00,0x01,0xff,0xf7,0x00,0x00,0x00,0x00,0x02,0xff,0xb9, + 0xfd,0x2f,0xf6,0xff,0xc0,0x00,0x0c,0xff,0xef,0xfd,0x4f,0xff,0x20, + 0x00,0xff,0xf9,0x00,0x00,0xcf,0xfc,0x00,0x00,0x6c,0x0e,0xb0,0x09, + 0xf2,0x0d,0x50,0x00,0x00,0x1f,0xff,0x5f,0xff,0x10,0x00,0x00,0x0c, + 0xff,0xc1,0x18,0xff,0xe1,0x00,0x00,0xef,0xfa,0x00,0x01,0x20,0x00, + 0x00,0x00,0x0f,0xff,0x80,0x04,0xff,0xf5,0x00,0x00,0x5f,0xff,0x75, + 0x55,0x53,0x00,0x00,0x00,0x00,0xcf,0xfc,0x22,0x22,0x00,0x00,0x00, + 0xdf,0xfb,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0xff,0xc8,0x88,0xdf, + 0xfd,0x00,0x00,0x00,0x0e,0xff,0x90,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x5f,0xff,0x40,0x00,0x00,0x5f,0xff,0xcf,0xff,0xb0,0x00,0x00, + 0x00,0x01,0xff,0xf7,0x00,0x00,0x00,0x00,0x02,0xff,0xbe,0xf9,0x0e, + 0xfa,0xff,0xc0,0x00,0x0c,0xff,0xff,0xf4,0x3f,0xff,0x20,0x00,0xef, + 0xfb,0x00,0x00,0xef,0xfb,0x00,0x00,0x2f,0x28,0xf3,0x0c,0xf4,0x0f, + 0x30,0x00,0x00,0x09,0xff,0xef,0xf9,0x00,0x00,0x00,0x0c,0xff,0xb0, + 0x05,0xff,0xf3,0x00,0x00,0xaf,0xff,0x20,0x07,0xfe,0x90,0x00,0x00, + 0x0f,0xff,0x91,0x3c,0xff,0xf1,0x00,0x00,0x5f,0xff,0x40,0x00,0x00, + 0x00,0x00,0x00,0x00,0xcf,0xfb,0x00,0x00,0x00,0x00,0x00,0x9f,0xff, + 0x20,0x02,0xc9,0x62,0x00,0x00,0x1f,0xff,0x70,0x00,0xaf,0xfd,0x00, + 0x00,0x00,0x0e,0xff,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5f, + 0xff,0x40,0x00,0x00,0x5f,0xff,0x4a,0xff,0xfa,0x00,0x00,0x00,0x01, + 0xff,0xf7,0x00,0x00,0x00,0x00,0x02,0xff,0xef,0xf5,0x09,0xfe,0xff, + 0xc0,0x00,0x0c,0xff,0xff,0x80,0x3f,0xff,0x20,0x00,0x9f,0xff,0x30, + 0x06,0xff,0xf7,0x00,0x00,0x0a,0xa0,0xbf,0xea,0xf6,0x5e,0x10,0x00, + 0x00,0x03,0xff,0xff,0xf4,0x00,0x00,0x00,0x0c,0xff,0xeb,0xcf,0xff, + 0xf2,0x00,0x00,0x3f,0xff,0xfa,0xbf,0xff,0x80,0x00,0x00,0x0f,0xff, + 0xff,0xff,0xff,0x90,0x00,0x00,0x5f,0xff,0xed,0xdd,0xdd,0x20,0x00, + 0x00,0x00,0xcf,0xff,0xdd,0xdd,0xd0,0x00,0x00,0x2f,0xff,0xe9,0x8e, + 0xff,0xf3,0x00,0x00,0x1f,0xff,0x70,0x00,0xaf,0xfd,0x00,0x00,0x00, + 0x0e,0xff,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5f,0xff,0x40, + 0x00,0x00,0x5f,0xff,0x41,0xcf,0xff,0x90,0x00,0x00,0x01,0xff,0xf7, + 0x00,0x00,0x00,0x00,0x02,0xff,0xff,0xf1,0x05,0xff,0xff,0xc0,0x00, + 0x0c,0xff,0xfd,0x10,0x3f,0xff,0x20,0x00,0x3f,0xff,0xfb,0xcf,0xff, + 0xe1,0x00,0x00,0x02,0xe9,0x13,0x30,0x14,0xe6,0x00,0x00,0x00,0x00, + 0xdf,0xff,0xe0,0x00,0x00,0x00,0x0c,0xff,0xff,0xff,0xff,0x90,0x00, + 0x00,0x06,0xff,0xff,0xff,0xfc,0x10,0x00,0x00,0x0f,0xff,0xff,0xff, + 0xfa,0x10,0x00,0x00,0x5f,0xff,0xff,0xff,0xff,0x20,0x00,0x00,0x00, + 0xcf,0xff,0xff,0xff,0xe0,0x00,0x00,0x05,0xff,0xff,0xff,0xff,0x90, + 0x00,0x00,0x1f,0xff,0x70,0x00,0xaf,0xfd,0x00,0x00,0x00,0x0e,0xff, + 0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5f,0xff,0x40,0x00,0x00, + 0x5f,0xff,0x40,0x1e,0xff,0xf9,0x00,0x00,0x01,0xff,0xf7,0x00,0x00, + 0x00,0x00,0x02,0xff,0xff,0xc0,0x01,0xff,0xff,0xc0,0x00,0x0c,0xff, + 0xf3,0x00,0x3f,0xff,0x20,0x00,0x06,0xff,0xff,0xff,0xff,0x40,0x00, + 0x00,0x00,0x3d,0xe9,0x77,0xbf,0x70,0x00,0x00,0x00,0x00,0x58,0x88, + 0x50,0x00,0x00,0x00,0x07,0x88,0x88,0x88,0x84,0x00,0x00,0x00,0x00, + 0x3a,0xef,0xfc,0x71,0x00,0x00,0x00,0x08,0x88,0x88,0x87,0x30,0x00, + 0x00,0x00,0x38,0x88,0x88,0x88,0x88,0x10,0x00,0x00,0x00,0x78,0x88, + 0x88,0x88,0x80,0x00,0x00,0x00,0x29,0xdf,0xff,0xc6,0x00,0x00,0x00, + 0x18,0x88,0x40,0x00,0x68,0x87,0x00,0x00,0x00,0x08,0x88,0x50,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x4c,0xcc,0x30,0x00,0x00,0x38,0x88, + 0x20,0x03,0x88,0x88,0x30,0x00,0x01,0x88,0x84,0x00,0x00,0x00,0x00, + 0x01,0x88,0x88,0x50,0x00,0x78,0x88,0x70,0x00,0x07,0x88,0x50,0x00, + 0x28,0x88,0x10,0x00,0x00,0x39,0xef,0xfd,0x92,0x00,0x00,0x00,0x00, + 0x00,0x5a,0xbb,0x82,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x10,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0x00,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x18,0xcc,0xb7,0x10,0x00,0x00,0x00,0x00, + 0x00,0x08,0xdd,0x80,0x00,0x00,0x00,0x0a,0xdd,0xdd,0xdd,0xdd,0xa0, + 0x00,0x00,0x00,0x2b,0xff,0xfe,0x81,0x00,0x00,0x00,0x00,0x00,0x02, + 0xdd,0x80,0x00,0x00,0x00,0x00,0x3b,0xff,0xfd,0x70,0x00,0x00,0x00, + 0x00,0x07,0xdf,0xfe,0x91,0x00,0x00,0x00,0x00,0x07,0xdd,0x80,0x00, + 0x00,0x00,0x00,0x00,0x39,0xbc,0xc9,0x40,0x00,0x00,0x00,0x00,0x18, + 0xbc,0xb7,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xbf,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x69,0x95,0x00,0x00, + 0x00,0x00,0x02,0xef,0xff,0xff,0xc1,0x00,0x00,0x00,0x00,0x00,0x09, + 0xff,0x90,0x00,0x00,0x00,0x07,0xff,0xff,0xff,0xff,0xb0,0x00,0x00, + 0x02,0xef,0xfe,0xff,0xfc,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x90, + 0x00,0x00,0x00,0x03,0xff,0xfe,0xff,0xfa,0x00,0x00,0x00,0x00,0x9f, + 0xff,0xff,0xfd,0x00,0x00,0x00,0x00,0x06,0xff,0xb0,0x00,0x00,0x00, + 0x00,0x04,0xff,0xff,0xff,0xf7,0x00,0x00,0x00,0x01,0xdf,0xff,0xff, + 0xe2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x0b,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x71, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xaf,0xf7,0x00,0x00,0x00,0x00, + 0x0a,0xff,0xc6,0xef,0xf7,0x00,0x00,0x00,0x00,0x00,0x09,0xff,0x90, + 0x00,0x00,0x00,0x01,0xef,0xff,0xbb,0xbb,0x80,0x00,0x00,0x0b,0xff, + 0xa0,0x1e,0xff,0x50,0x00,0x00,0xbb,0xbb,0xbc,0xff,0xeb,0x10,0x00, + 0x00,0x0c,0xff,0xa0,0x1e,0xff,0x30,0x00,0x00,0x03,0xff,0xe2,0x1b, + 0xff,0x60,0x00,0x00,0x00,0x03,0xff,0xe0,0x00,0x00,0x00,0x00,0x0d, + 0xff,0xb2,0x8f,0xff,0x10,0x00,0x00,0x08,0xff,0xd2,0x8f,0xfc,0x00, + 0x00,0x00,0x00,0x29,0x99,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x9c, + 0xf5,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xef,0x00,0x00,0x00,0x00, + 0x01,0x11,0x11,0x11,0x11,0x00,0x00,0x00,0x00,0x00,0xfe,0x60,0x00, + 0x00,0x00,0x00,0x00,0x00,0xaf,0xf7,0x00,0x00,0x00,0x00,0x1f,0xff, + 0x20,0x6f,0xfc,0x00,0x00,0x00,0x00,0x00,0x09,0xff,0x90,0x00,0x00, + 0x00,0x00,0x4f,0xff,0x90,0x00,0x00,0x00,0x00,0x03,0x57,0x30,0x0a, + 0xff,0x80,0x00,0x00,0xef,0xff,0xff,0xff,0xff,0x10,0x00,0x00,0x02, + 0x45,0x20,0x0a,0xff,0x80,0x00,0x00,0x08,0xff,0x90,0x06,0xff,0x90, + 0x00,0x00,0x00,0x00,0xef,0xf2,0x00,0x00,0x00,0x00,0x1f,0xff,0x20, + 0x0e,0xff,0x40,0x00,0x00,0x00,0x13,0x20,0x1f,0xff,0x20,0x00,0x00, + 0x00,0x4f,0xff,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xf5,0x00, + 0x00,0x00,0x00,0x00,0x06,0xdf,0xff,0x00,0x00,0x00,0x00,0x0b,0xff, + 0xff,0xff,0xfb,0x00,0x00,0x00,0x00,0x00,0xff,0xfd,0x60,0x00,0x00, + 0x00,0x00,0x00,0x23,0x31,0x00,0x00,0x00,0x00,0x3f,0xff,0x00,0x3f, + 0xff,0x00,0x00,0x00,0x00,0x00,0x09,0xff,0x90,0x00,0x00,0x00,0x00, + 0x04,0xff,0xfd,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0xff,0x70, + 0x00,0x00,0xef,0xfb,0xbc,0xff,0xeb,0x10,0x00,0x00,0x00,0x00,0x00, + 0x0b,0xff,0x80,0x00,0x00,0x0b,0xff,0x90,0x07,0xff,0x90,0x00,0x00, + 0x00,0x00,0x8f,0xf7,0x00,0x00,0x00,0x00,0x0f,0xff,0x40,0x1f,0xff, + 0x30,0x00,0x00,0x00,0x29,0xcb,0x4d,0xff,0x60,0x00,0x00,0x00,0x4f, + 0xff,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xf5,0x00,0x00,0x00, + 0x00,0x05,0xdf,0xff,0xb4,0x00,0x00,0x00,0x00,0x0b,0xff,0xff,0xff, + 0xfb,0x00,0x00,0x00,0x00,0x00,0x4c,0xff,0xfd,0x50,0x00,0x00,0x00, + 0x00,0x8f,0xf7,0x00,0x00,0x00,0x00,0x4f,0xfd,0x00,0x2f,0xff,0x10, + 0x00,0x00,0x00,0x00,0x09,0xff,0x90,0x00,0x00,0x00,0x00,0x00,0x2d, + 0xff,0xf4,0x00,0x00,0x00,0x00,0x00,0x2c,0xef,0xfe,0x10,0x00,0x00, + 0x6f,0xf7,0x02,0xff,0x90,0x00,0x00,0x00,0x05,0xcf,0xb4,0x6f,0xff, + 0x40,0x00,0x00,0x0c,0xff,0xf6,0x5e,0xff,0x50,0x00,0x00,0x00,0x00, + 0x2f,0xfd,0x00,0x00,0x00,0x00,0x08,0xff,0xd7,0xcf,0xfb,0x00,0x00, + 0x00,0x02,0xef,0xff,0xfe,0xff,0x70,0x00,0x00,0x00,0x28,0x88,0x10, + 0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x83,0x00,0x00,0x00,0x00,0x0e, + 0xff,0xb4,0x00,0x00,0x00,0x00,0x00,0x05,0x66,0x66,0x66,0x65,0x00, + 0x00,0x00,0x00,0x00,0x00,0x4b,0xff,0xe0,0x00,0x00,0x00,0x00,0x6f, + 0xfe,0x20,0x00,0x00,0x00,0x5f,0xfd,0x00,0x2f,0xff,0x10,0x00,0x00, + 0x00,0xb6,0x09,0xff,0x90,0x00,0x00,0x00,0x00,0x00,0x01,0xaf,0xff, + 0x20,0x00,0x00,0x00,0x00,0x1f,0xff,0xc1,0x00,0x00,0x00,0x08,0xff, + 0x42,0xff,0x90,0x00,0x00,0x00,0x05,0xff,0xff,0xff,0xfa,0x00,0x00, + 0x00,0x0c,0xff,0xef,0xff,0xfa,0x00,0x00,0x00,0x00,0x00,0x08,0xff, + 0x60,0x00,0x00,0x00,0x00,0x9f,0xff,0xff,0xd1,0x00,0x00,0x00,0x0a, + 0xff,0xa3,0x8f,0xff,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0xff,0x82, + 0x00,0x00,0x00,0x00,0x00,0x03,0x44,0x44,0x44,0x43,0x00,0x00,0x00, + 0x00,0x00,0x00,0x28,0xff,0xe0,0x00,0x00,0x00,0x00,0x0b,0xff,0xe4, + 0x00,0x00,0x00,0x4f,0xfe,0x00,0x2f,0xff,0x00,0x00,0x00,0x00,0xef, + 0xdc,0xff,0x90,0x00,0x00,0x00,0x00,0x01,0x10,0x0c,0xff,0x80,0x00, + 0x00,0x00,0x00,0x05,0xbf,0xf8,0x00,0x00,0x00,0x00,0xbf,0xf5,0xff, + 0x90,0x00,0x00,0x00,0x03,0xff,0xc9,0xba,0x60,0x00,0x00,0x00,0x0a, + 0xff,0x86,0xbb,0x60,0x00,0x00,0x00,0x00,0x00,0x01,0xdf,0xe2,0x00, + 0x00,0x00,0x04,0xff,0xd7,0xcf,0xf7,0x00,0x00,0x00,0x0e,0xff,0x20, + 0x0e,0xff,0x60,0x00,0x00,0x00,0x27,0x77,0x10,0x00,0x00,0x00,0x00, + 0x00,0x00,0x77,0x73,0x00,0x00,0x00,0x00,0x07,0xef,0xff,0x92,0x00, + 0x00,0x00,0x00,0x0b,0xff,0xff,0xff,0xfb,0x00,0x00,0x00,0x00,0x00, + 0x29,0xff,0xfe,0x70,0x00,0x00,0x00,0x00,0x00,0x9f,0xff,0x20,0x00, + 0x00,0x2f,0xff,0x10,0x5f,0xfc,0x00,0x00,0x00,0x00,0xcf,0xff,0xff, + 0x90,0x00,0x00,0x00,0x07,0xff,0xc0,0x08,0xff,0xa0,0x00,0x00,0x03, + 0x69,0x40,0x2f,0xff,0x00,0x00,0x00,0x00,0x1c,0xff,0xff,0x90,0x00, + 0x00,0x00,0x01,0xff,0xc1,0x11,0x11,0x00,0x00,0x00,0x07,0xff,0xb0, + 0x04,0x31,0x00,0x00,0x00,0x01,0x22,0x22,0x5f,0xfc,0x10,0x00,0x00, + 0x0a,0xff,0x50,0x2f,0xfe,0x00,0x00,0x00,0x0e,0xff,0x10,0x0e,0xff, + 0x30,0x00,0x00,0x00,0x4f,0xff,0x20,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xf5,0x00,0x00,0x00,0x00,0x00,0x18,0xff,0xff,0x00,0x00,0x00, + 0x00,0x0b,0xff,0xff,0xff,0xfb,0x00,0x00,0x00,0x00,0x00,0xff,0xff, + 0x81,0x00,0x00,0x00,0x01,0xce,0xf1,0x0d,0xff,0x60,0x00,0x00,0x0d, + 0xff,0x82,0xcf,0xf8,0x00,0x00,0x00,0x00,0x04,0xdf,0xff,0x90,0x00, + 0x00,0x00,0x03,0xff,0xf9,0x8f,0xff,0x70,0x00,0x00,0x07,0xff,0xc4, + 0x9f,0xfe,0x00,0x00,0x00,0x00,0x02,0xef,0xff,0x90,0x00,0x00,0x00, + 0x00,0xef,0xff,0xff,0xff,0x00,0x00,0x00,0x01,0xff,0xf5,0x5f,0xff, + 0x30,0x00,0x00,0x08,0xff,0xff,0xff,0xff,0xa0,0x00,0x00,0x09,0xff, + 0x80,0x6f,0xfd,0x00,0x00,0x00,0x0a,0xff,0x80,0x6f,0xfd,0x00,0x00, + 0x00,0x00,0x4f,0xff,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xf5, + 0x00,0x00,0x00,0x00,0x00,0x00,0x29,0xff,0x00,0x00,0x00,0x00,0x03, + 0x44,0x44,0x44,0x43,0x00,0x00,0x00,0x00,0x00,0xff,0x92,0x00,0x00, + 0x00,0x00,0x00,0xef,0xfb,0x7f,0xff,0x50,0x00,0x00,0x04,0xff,0xff, + 0xff,0xe1,0x00,0x00,0x00,0x00,0x00,0x1c,0xff,0x90,0x00,0x00,0x00, + 0x00,0x9f,0xff,0xff,0xfc,0x10,0x00,0x00,0x01,0xcf,0xff,0xff,0xf5, + 0x00,0x00,0x00,0x00,0x00,0x3f,0xff,0x90,0x00,0x00,0x00,0x00,0xbf, + 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x5f,0xff,0xff,0xf8,0x00,0x00, + 0x00,0x08,0xff,0xff,0xff,0xff,0xb0,0x00,0x00,0x03,0xff,0xff,0xff, + 0xf6,0x00,0x00,0x00,0x02,0xff,0xff,0xff,0xf4,0x00,0x00,0x00,0x00, + 0x2a,0xaa,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xaa,0xa4,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x2a,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x00,0x00,0x00,0x00,0x00, + 0x00,0x6f,0xff,0xff,0xfc,0x00,0x00,0x00,0x00,0x4b,0xef,0xea,0x20, + 0x00,0x00,0x00,0x00,0x00,0x03,0xbb,0x70,0x00,0x00,0x00,0x00,0x05, + 0x9b,0xba,0x61,0x00,0x00,0x00,0x00,0x06,0xab,0xb9,0x30,0x00,0x00, + 0x00,0x00,0x00,0x05,0xbb,0x70,0x00,0x00,0x00,0x00,0x58,0x88,0x88, + 0x88,0x00,0x00,0x00,0x00,0x02,0x8b,0xba,0x50,0x00,0x00,0x00,0x05, + 0x88,0x88,0x88,0x88,0x60,0x00,0x00,0x00,0x3a,0xef,0xec,0x50,0x00, + 0x00,0x00,0x00,0x2a,0xef,0xeb,0x30,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05, + 0xcf,0xfd,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x07,0xf9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0xf7,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x95,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x22,0x20,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xdd,0xd3,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xcc,0x13,0xcc, + 0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x80,0x00,0x00,0x00,0x00,0x00, + 0x9e,0x10,0x00,0x6d,0xec,0x40,0x00,0x01,0x7b,0xcc,0xa6,0x11,0x83, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2f,0xf2, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xff,0x20,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x01,0xef,0x60,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xff,0xf2,0x00,0x00,0x00, + 0x00,0x00,0x08,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xef,0xf4,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x31,0xff,0x20,0x00, + 0x00,0x00,0x00,0x02,0x5b,0xc6,0x20,0x00,0x00,0x00,0x00,0x2f,0x80, + 0x04,0xfe,0x6f,0xf2,0x00,0x2e,0xff,0xff,0xff,0xee,0xfe,0x20,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xbf,0xc0,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0xb0,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x26,0x62,0x00,0x00,0x00, + 0x00,0x00,0x00,0x1e,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x04,0xff,0xf2,0x00,0x00,0x00,0x00,0x00, + 0x06,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xde,0xe3,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x01,0xcf,0x71,0xef,0x61,0x10,0x00,0x00, + 0x00,0x8f,0xff,0xff,0xf9,0x00,0x00,0x00,0x00,0x08,0xf2,0x09,0xf8, + 0x0b,0xf7,0x00,0xaf,0xfe,0x54,0x9f,0xff,0xfd,0x30,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xff,0x70,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x7f,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x4f,0xf4,0x00,0x00,0x00,0x00,0x00, + 0x02,0x9d,0xf2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x04,0xff,0xf2,0x00,0x00,0x00,0x00,0x00,0x03,0xf6, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x24,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x0b,0xff,0xff,0xff,0xff,0xb0,0x00,0x00,0x06,0xff, + 0xfc,0xcc,0xff,0x70,0x00,0x00,0x00,0x01,0xea,0x0a,0xf8,0x0b,0xf7, + 0x00,0xcf,0xf5,0x01,0xaf,0xff,0xf1,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x08,0xff,0x30,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x3f,0xf8,0x00,0x00,0x00,0x00,0x04,0x90,0xa2,0x00,0x00, + 0x00,0x00,0x00,0x00,0x4f,0xf4,0x00,0x00,0x00,0x00,0x00,0x04,0xff, + 0xf2,0x00,0x00,0x00,0x00,0x00,0x01,0x33,0x33,0x10,0x00,0x00,0x00, + 0x00,0x00,0x11,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xea,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x8f,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x0b,0xff,0xff,0xff,0xff,0xb0,0x00,0x00,0x08,0xce,0x87,0x92, + 0xff,0xd0,0x00,0x00,0x00,0x00,0x7f,0x36,0xfc,0x4e,0xf3,0x00,0x9f, + 0xfa,0x1c,0xff,0xff,0xf7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0b,0xff,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x1f,0xfb,0x00,0x00,0x00,0x00,0x09,0xf8,0xf6,0x00,0x00,0x00,0x00, + 0x02,0x66,0x9f,0xf9,0x66,0x20,0x00,0x00,0x00,0x04,0xff,0xf2,0x00, + 0x00,0x00,0x00,0x00,0x05,0xff,0xff,0x40,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xae,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9f,0xe0, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x4f,0xf2,0x5f,0xf2,0x10,0x00,0x00,0x00,0x00,0x08,0xba,0xff,0xc0, + 0x00,0x00,0x00,0x00,0x0d,0xb0,0x8f,0xff,0x60,0x00,0x1d,0xff,0xff, + 0xfe,0x3c,0xa5,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0d,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xfd, + 0x00,0x00,0x00,0x00,0x14,0xdf,0xc4,0x10,0x00,0x00,0x00,0x04,0xff, + 0xff,0xff,0xff,0x40,0x00,0x00,0x00,0x02,0x88,0x81,0x00,0x00,0x00, + 0x00,0x00,0x05,0xff,0xff,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x20,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xbf,0xf1,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xf3, + 0x1f,0xf2,0x00,0x00,0x00,0x00,0x06,0xbf,0xff,0xff,0x60,0x00,0x00, + 0x6b,0xb7,0x15,0xf4,0x01,0x20,0x00,0x00,0x01,0x9f,0xff,0xf6,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xfd,0x00,0x00, + 0x00,0x00,0x5f,0xef,0xdf,0x40,0x00,0x00,0x00,0x04,0xff,0xff,0xff, + 0xff,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x02,0x55,0x55,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x3f,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xdf,0xf3,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0xff,0xff,0xff,0xff, + 0xb0,0x00,0x00,0x00,0xbf,0xff,0xff,0xc5,0x00,0x00,0x07,0xfd,0xbf, + 0xa0,0xcd,0x00,0x00,0x00,0x00,0x00,0x8f,0xff,0xff,0x70,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0xff,0x10,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0xfb,0x00,0x00,0x00,0x00, + 0x15,0x4f,0x25,0x10,0x00,0x00,0x00,0x00,0x11,0x4f,0xf4,0x11,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0f,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xff,0xf5,0x00,0x00,0x00,0x00,0x00,0x15, + 0x51,0x05,0x51,0x00,0x00,0x00,0x0b,0xff,0xff,0xff,0xff,0xb0,0x00, + 0x00,0x04,0xff,0xfd,0xb2,0x00,0x00,0x00,0x0e,0xf4,0x1f,0xf2,0x4f, + 0x60,0x00,0x00,0x00,0x01,0xff,0xe2,0x9f,0xf3,0x00,0x00,0x00,0x00, + 0x00,0x35,0x40,0x00,0x00,0x00,0x00,0x08,0xff,0x40,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x4f,0xf8,0x00,0x00,0x00,0x00,0x00,0x4b, + 0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x4f,0xf4,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0b,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x01,0xff,0xf5,0x00,0x00,0x00,0x00,0x00,0x4f,0xf4,0x3f, + 0xf5,0x00,0x00,0x00,0x02,0x37,0xfd,0x38,0xfc,0x20,0x00,0x00,0x05, + 0xff,0xa7,0x95,0x75,0x20,0x00,0x0f,0xf3,0x0f,0xf2,0x0b,0xe1,0x00, + 0x00,0x00,0x01,0xff,0xc0,0x3f,0xf6,0x00,0x00,0x00,0x00,0x00,0xbf, + 0xc0,0x00,0x00,0x00,0x00,0x03,0xff,0x70,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x7f,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x4f,0xf4,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xf2, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x01,0xff,0xf5,0x00,0x00,0x00,0x00,0x00,0x8f,0xf7,0x6f,0xf9,0x00, + 0x00,0x00,0x00,0x03,0xff,0x14,0xfe,0x00,0x00,0x00,0x01,0xff,0xfc, + 0xdf,0xff,0x40,0x00,0x0b,0xf7,0x4f,0xe1,0x02,0xf7,0x00,0x00,0x00, + 0x00,0xcf,0xfc,0xef,0xf2,0x00,0x00,0x00,0x00,0x00,0xff,0xf1,0x00, + 0x00,0x00,0x00,0x00,0xbf,0xd0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xcf,0xb0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x01,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,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xf6,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x88, + 0x83,0x00,0x00,0x00,0x00,0x00,0x9f,0xf8,0x7f,0xfa,0x00,0x00,0x00, + 0x00,0x00,0xff,0x31,0xff,0x20,0x00,0x00,0x00,0x4d,0xff,0xff,0xe6, + 0x00,0x00,0x02,0xdf,0xfe,0x40,0x00,0x9e,0x10,0x00,0x00,0x00,0x19, + 0xef,0xfb,0x40,0x00,0x00,0x00,0x00,0x01,0xff,0xf2,0x00,0x00,0x00, + 0x00,0x00,0x3f,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xff, + 0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x8c,0xc7,0x6c,0xc8,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3a,0xb3,0x10,0x00,0x00, + 0x00,0x03,0x31,0x00,0x00,0x14,0x10,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x01,0xcc,0xc1,0x00,0x00,0x00,0x00,0x00, + 0x07,0xfa,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0a,0xf7,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff, + 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x0f,0xff,0xff,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xff,0xff,0xf0,0x0f,0xff,0xff,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0xff,0xf0,0x00,0x07,0xbf,0xff,0xff,0xff,0xff,0xf0, + 0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff, + 0xfb,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x00, + 0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x0f,0xff,0xff,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0xff,0xf0,0x0f,0xff,0xff,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xf0,0x00,0xbf,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff, + 0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xfb, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xff,0xff,0x00,0x00,0x0f,0xff,0xff,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xf0,0x0f,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, + 0xf0,0x07,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff, + 0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0x70,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff, + 0xff,0x00,0x00,0x0f,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, + 0xf0,0x0f,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xf0,0x0b, + 0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff, + 0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xb0,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xaf,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff, + 0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xfa,0x00,0x00,0x00,0x00, + 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00, + 0x00,0x0f,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xf0,0x0f, + 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xf0,0x0f,0xff,0xff, + 0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0, + 0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xaf, + 0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff, + 0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xfa,0x00,0x00,0x00,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x0f, + 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xf0,0x0f,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xf0,0x0f,0xff,0xff,0xb0,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0b,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x0a,0xff,0xff,0xff, + 0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f, + 0xff,0xff,0xff,0xff,0xff,0xff,0xa2,0x00,0x00,0xff,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x0f,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xf0,0x0f,0xff,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xff,0xff,0xf0,0x0f,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff, + 0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff, + 0xff,0xff,0xff,0xff,0xf2,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x0f,0xff,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xff,0xff,0xf0,0x0f,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xff,0xff,0xf0,0x0f,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff, + 0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0, + 0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff, + 0xff,0xff,0xf2,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0xff,0x00,0x00,0x0f,0xff,0xff,0xb0,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0b,0xff,0xff,0xf0,0x0f,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff, + 0xff,0xf0,0x0f,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xf0, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, + 0x00,0x00,0x00,0x0a,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff, + 0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff, + 0xa2,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f, + 0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff, + 0xff,0xf0,0x0f,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xf0, + 0x0f,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xf0,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xaf,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff, + 0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xfa,0x00,0x00, + 0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff, + 0x00,0x00,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff, + 0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xb0, + 0x0f,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xf0,0x0f,0xff, + 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xf0,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xaf,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff, + 0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xfa,0x00,0x00,0x00,0x00,0xff, + 0xff,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x00, + 0x07,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff, + 0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0x70,0x0f,0xff, + 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xf0,0x0f,0xff,0xff,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff, + 0xff,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xbf, + 0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff, + 0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xfb,0x00,0x0f,0xff,0xff,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xff,0xff,0xf0,0x0f,0xff,0xff,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xbf,0xff, + 0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f, + 0xff,0xff,0xff,0xff,0xfb,0x70,0x00,0x0f,0xff,0xff,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0xff,0xf0,0x0f,0xff,0xff,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff, + 0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xff, + 0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff, + 0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff, + 0xff,0xff,0xff,0xf0,0x00,0x00,0x7b,0xff,0xff,0xff,0xff,0xf0,0x0f, + 0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xfb, + 0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0f,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff, + 0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff, + 0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff, + 0xff,0xf0,0x00,0x0b,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff, + 0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xfb,0x00, + 0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0xff,0xff,0xff,0xff, + 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xff, + 0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff, + 0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0, + 0x00,0x7f,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff, + 0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0x70,0x0f,0xff, + 0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0xff,0xff,0xff,0xff,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xa0, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0, + 0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x22,0xbf, + 0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff, + 0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xb0,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xa0,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff, + 0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x22,0xff,0xff,0xff, + 0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f, + 0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xa0,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x0f,0xff, + 0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff, + 0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff, + 0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f, + 0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x22,0xff,0xff,0xff,0xff,0xff, + 0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff, + 0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xa0,0x00,0x00,0x00, + 0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00, + 0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x0f,0xff,0xff,0xff, + 0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f, + 0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff, + 0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff, + 0xff,0xff,0xff,0xff,0xf0,0x22,0xff,0xff,0xff,0xff,0xff,0xff,0xf0, + 0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff, + 0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff, + 0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xa0,0x00,0x00,0x00,0xff, + 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff, + 0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff, + 0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff, + 0xff,0xff,0xf0,0x22,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff, + 0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff, + 0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff, + 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f, + 0xff,0xff,0xff,0xff,0xff,0xa0,0x00,0x00,0x00,0x00,0xff,0xff,0x00, + 0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0, + 0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff, + 0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff, + 0xf0,0x22,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff, + 0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff, + 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff, + 0xff,0xff,0xa0,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00, + 0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff, + 0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff, + 0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x22, + 0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff, + 0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xa0, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff, + 0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xb0,0x0f, + 0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x22,0xff,0xff, + 0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0, + 0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xa0,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07, + 0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff, + 0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0x70,0x0f,0xff,0xff, + 0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x22,0xff,0xff,0xff,0xff, + 0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff, + 0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x0f,0xff,0xa0,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xbf,0xff, + 0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0, + 0x0f,0xff,0xff,0xff,0xff,0xff,0xfb,0x00,0x0f,0xff,0xff,0xff,0xff, + 0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xff, + 0xff,0xff,0xff,0xff,0xff,0xf0,0x22,0xff,0xff,0xff,0xff,0xff,0xff, + 0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff,0xff,0xff, + 0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x0f,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xbf,0xff,0xff, + 0xff,0xff,0xf0,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x0f,0xff, + 0xff,0xff,0xff,0xfb,0x70,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff, + 0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff, + 0xff,0xff,0xff,0xf0,0x22,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x0f,0xff,0xff,0xff,0xff,0xff, + 0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff, + 0xff,0xf0,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +}; + +#endif//MENUFONT_H \ No newline at end of file diff --git a/mainui/utils.cpp b/mainui/utils.cpp index 31dfb2ea..7e795697 100644 --- a/mainui/utils.cpp +++ b/mainui/utils.cpp @@ -97,6 +97,16 @@ void StringConcat( char *dst, const char *src, size_t size ) return; } +char *StringCopy( const char *input ) +{ + if( !input ) return NULL; + + char *out = (char *)MALLOC( strlen( input ) + 1 ); + strcpy( out, input ); + + return out; +} + /* ============ COM_FileBase diff --git a/mainui/utils.h b/mainui/utils.h index 2963a699..a560c6b7 100644 --- a/mainui/utils.h +++ b/mainui/utils.h @@ -117,5 +117,8 @@ extern int UI_FadeAlpha( int starttime, int endtime ); extern void StringConcat( char *dst, const char *src, size_t size ); // strncat safe prototype extern char *Info_ValueForKey( const char *s, const char *key ); extern int KEY_GetKey( const char *binding ); // ripped out from engine +extern char *StringCopy( const char *input ); // copy string into new memory + +extern void UI_LoadCustomStrings( void ); #endif//UTILS_H \ No newline at end of file