2015-05-19 21:54:34 +00:00
|
|
|
//-------------------------------------------------------------------------
|
|
|
|
/*
|
|
|
|
Copyright (C) 1997, 2005 - 3D Realms Entertainment
|
|
|
|
|
|
|
|
This file is part of Shadow Warrior version 1.2
|
|
|
|
|
|
|
|
Shadow Warrior is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
|
|
|
Original Source: 1997 - Frank Maddin and Jim Norwood
|
|
|
|
Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
|
|
|
|
*/
|
|
|
|
//-------------------------------------------------------------------------
|
2019-10-09 16:09:05 +00:00
|
|
|
#include "ns.h"
|
|
|
|
|
2015-05-19 21:54:34 +00:00
|
|
|
#include "build.h"
|
|
|
|
|
|
|
|
#include "keys.h"
|
|
|
|
#include "names2.h"
|
|
|
|
#include "panel.h"
|
|
|
|
#include "game.h"
|
|
|
|
#include "mytypes.h"
|
|
|
|
#include "text.h"
|
|
|
|
|
|
|
|
#include "control.h"
|
2019-10-25 22:32:49 +00:00
|
|
|
#include "gamecontrol.h"
|
2015-05-19 21:54:34 +00:00
|
|
|
//#include "inv.h"
|
|
|
|
|
2019-10-09 16:09:05 +00:00
|
|
|
BEGIN_SW_NS
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
SWBOOL CheatInputMode = FALSE;
|
2015-05-19 21:54:34 +00:00
|
|
|
char CheatInputString[256];
|
2015-05-19 21:58:29 +00:00
|
|
|
SWBOOL EveryCheat = FALSE;
|
|
|
|
SWBOOL ResCheat = FALSE;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void ResCheatOn(PLAYERp UNUSED(pp), char *UNUSED(cheat_string))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
ResCheat = TRUE;
|
|
|
|
}
|
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void VoxCheat(PLAYERp UNUSED(pp), char *UNUSED(cheat_string))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
//gs.Voxel ^= 1;
|
|
|
|
}
|
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void RestartCheat(PLAYERp UNUSED(pp), char *UNUSED(cheat_string))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
ExitLevel = TRUE;
|
|
|
|
}
|
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void RoomCheat(PLAYERp UNUSED(pp), char *UNUSED(cheat_string))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2015-05-19 21:58:29 +00:00
|
|
|
extern SWBOOL FAF_DebugView;
|
2015-05-19 21:54:34 +00:00
|
|
|
FAF_DebugView ^= 1;
|
|
|
|
}
|
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void SecretCheat(PLAYERp UNUSED(pp), char *UNUSED(cheat_string))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2019-10-27 15:53:00 +00:00
|
|
|
hud_stats = !hud_stats;
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void NextCheat(PLAYERp UNUSED(pp), char *UNUSED(cheat_string))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
Level++;
|
|
|
|
ExitLevel = TRUE;
|
|
|
|
}
|
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void PrevCheat(PLAYERp UNUSED(pp), char *UNUSED(cheat_string))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
Level--;
|
|
|
|
ExitLevel = TRUE;
|
|
|
|
}
|
|
|
|
|
2015-05-19 22:03:30 +00:00
|
|
|
static int32_t showallmap;
|
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void MapCheat(PLAYERp pp, char *UNUSED(cheat_string))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2015-05-19 22:03:30 +00:00
|
|
|
showallmap ^= 1;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
2015-05-19 22:03:30 +00:00
|
|
|
if (showallmap)
|
2015-05-19 21:54:34 +00:00
|
|
|
MapSetAll2D(0);
|
|
|
|
else
|
|
|
|
MapSetAll2D(0xFF);
|
|
|
|
|
2015-05-19 22:03:30 +00:00
|
|
|
sprintf(ds, "SHOWALLMAP %s", showallmap ? "ON" : "OFF");
|
2015-05-19 21:54:34 +00:00
|
|
|
PutStringInfo(pp, ds);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void LocCheat(PLAYERp UNUSED(pp), char *UNUSED(cheat_string))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2015-05-19 21:58:29 +00:00
|
|
|
extern SWBOOL LocationInfo;
|
2015-05-19 21:54:34 +00:00
|
|
|
LocationInfo++;
|
|
|
|
if (LocationInfo > 2)
|
|
|
|
LocationInfo = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void WeaponCheat(PLAYERp UNUSED(pp), char *UNUSED(cheat_string))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
PLAYERp p;
|
|
|
|
short pnum;
|
|
|
|
unsigned int i;
|
|
|
|
USERp u;
|
|
|
|
|
|
|
|
TRAVERSE_CONNECT(pnum)
|
|
|
|
{
|
|
|
|
p = &Player[pnum];
|
|
|
|
u = User[p->PlayerSprite];
|
|
|
|
|
|
|
|
// ALL WEAPONS
|
|
|
|
if (!SW_SHAREWARE)
|
|
|
|
p->WpnFlags = 0xFFFFFFFF;
|
|
|
|
else
|
|
|
|
p->WpnFlags = 0x0000207F; // Disallows high weapon cheat in shareware
|
|
|
|
|
|
|
|
for (i = 0; i < SIZ(p->WpnAmmo); i++)
|
|
|
|
{
|
|
|
|
p->WpnAmmo[i] = DamageData[i].max_ammo;
|
|
|
|
}
|
|
|
|
|
|
|
|
PlayerUpdateWeapon(p, u->WeaponNum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void GodCheat(PLAYERp pp, char *UNUSED(cheat_string))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
//
|
|
|
|
// GOD mode
|
|
|
|
//
|
|
|
|
GodMode ^= 1;
|
|
|
|
|
|
|
|
sprintf(ds, "GOD MODE %s", GodMode ? "ON" : "OFF");
|
|
|
|
PutStringInfo(pp, ds);
|
|
|
|
}
|
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void ClipCheat(PLAYERp pp, char *UNUSED(cheat_string))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
FLIP(pp->Flags, PF_CLIP_CHEAT);
|
|
|
|
|
|
|
|
sprintf(ds, "NO CLIP MODE %s", TEST(pp->Flags, PF_CLIP_CHEAT) ? "ON" : "OFF");
|
|
|
|
PutStringInfo(pp, ds);
|
|
|
|
}
|
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void WarpCheat(PLAYERp pp, char *cheat_string)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
char *cp = cheat_string;
|
|
|
|
int episode_num;
|
|
|
|
int level_num;
|
|
|
|
|
|
|
|
cp += sizeof("swtrek")-1;
|
|
|
|
level_num = atol(cp);
|
|
|
|
|
|
|
|
//DSPRINTF(ds,"ep %d, lev %d",episode_num, level_num);
|
|
|
|
//MONO_PRINT(ds);
|
|
|
|
|
|
|
|
if (!SW_SHAREWARE)
|
|
|
|
{
|
|
|
|
if (level_num > 28 || level_num < 1)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (level_num > 4 || level_num < 1)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Level = level_num;
|
|
|
|
ExitLevel = TRUE;
|
|
|
|
|
|
|
|
sprintf(ds, "ENTERING %1d", Level);
|
|
|
|
PutStringInfo(pp, ds);
|
|
|
|
}
|
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void ItemCheat(PLAYERp pp, char *cheat_string)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
//
|
|
|
|
// Get all ITEMS
|
|
|
|
//
|
|
|
|
PLAYERp p;
|
|
|
|
short pnum;
|
|
|
|
short inv;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
PutStringInfo(pp, "ITEMS");
|
|
|
|
|
|
|
|
TRAVERSE_CONNECT(pnum)
|
|
|
|
{
|
|
|
|
p = &Player[pnum];
|
|
|
|
memset(p->HasKey, TRUE, sizeof(p->HasKey));
|
|
|
|
|
|
|
|
if (p->Wpn[WPN_UZI] && p->CurWpn == p->Wpn[WPN_UZI])
|
|
|
|
{
|
|
|
|
SET(p->Flags, PF_TWO_UZI);
|
|
|
|
SET(p->Flags, PF_PICKED_UP_AN_UZI);
|
|
|
|
InitWeaponUzi(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
p->WpnShotgunAuto = 50;
|
|
|
|
p->WpnRocketHeat = 5;
|
|
|
|
p->WpnRocketNuke = 1;
|
|
|
|
p->Armor = 100;
|
|
|
|
|
|
|
|
for (inv = 0; inv < MAX_INVENTORY; inv++)
|
|
|
|
{
|
|
|
|
p->InventoryPercent[inv] = 100;
|
|
|
|
//p->InventoryAmount[inv] = 1;
|
|
|
|
p->InventoryAmount[inv] = InventoryData[inv].MaxInv;
|
|
|
|
//PlayerUpdateInventory(p, inv);
|
|
|
|
}
|
|
|
|
|
|
|
|
PlayerUpdateInventory(p, p->InventoryNum);
|
|
|
|
//p->InventoryNum = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i=0; i<numsectors; i++)
|
|
|
|
{
|
|
|
|
if (SectUser[i] && SectUser[i]->stag == SECT_LOCK_DOOR)
|
|
|
|
SectUser[i]->number = 0; // unlock all doors of this type
|
|
|
|
}
|
|
|
|
|
|
|
|
WeaponCheat(pp, cheat_string);
|
|
|
|
PlayerUpdateKeys(pp);
|
|
|
|
}
|
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void EveryCheatToggle(PLAYERp pp, char *cheat_string)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
EveryCheat ^= 1;
|
|
|
|
|
|
|
|
WeaponCheat(pp, cheat_string);
|
|
|
|
GodCheat(pp, cheat_string);
|
|
|
|
ItemCheat(pp, cheat_string);
|
|
|
|
|
|
|
|
sprintf(ds, "EVERY CHEAT %s", EveryCheat ? "ON" : "OFF");
|
|
|
|
PutStringInfo(pp, ds);
|
|
|
|
}
|
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void SaveCheat(PLAYERp pp, char *UNUSED(cheat_string))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void GeorgeFunc(PLAYERp pp, char *UNUSED(cheat_string))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
PlayerSound(DIGI_TAUNTAI9,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_doppler|v3df_follow,pp);
|
|
|
|
}
|
|
|
|
|
2015-05-19 21:58:29 +00:00
|
|
|
void BlackburnFunc(PLAYERp pp, char *UNUSED(cheat_string))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
|
|
|
PlayerSound(DIGI_TAUNTAI3,&pp->posx,&pp->posy,&pp->posz,v3df_dontpan|v3df_doppler|v3df_follow,pp);
|
|
|
|
}
|
|
|
|
|
2019-04-08 06:25:22 +00:00
|
|
|
int cheatcmp(const char *str1, const char *str2, int len)
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2019-04-08 06:25:22 +00:00
|
|
|
const char *cp1 = str1;
|
|
|
|
const char *cp2 = str2;
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
if (*cp1 != *cp2)
|
|
|
|
{
|
|
|
|
if (!((*cp1 == '#' && isdigit(*cp2)) || (*cp2 == '#' && isdigit(*cp1))))
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp1++;
|
|
|
|
cp2++;
|
|
|
|
}
|
|
|
|
while (--len);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define CF_ALL BIT(0)
|
|
|
|
#define CF_NOTSW BIT(1)
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
2019-04-08 06:25:22 +00:00
|
|
|
const char *CheatInputCode;
|
2015-05-19 21:54:34 +00:00
|
|
|
void (*CheatInputFunc)(PLAYERp, char *);
|
|
|
|
char flags;
|
|
|
|
} CHEAT_INFO, *CHEAT_INFOp;
|
|
|
|
|
|
|
|
|
|
|
|
CHEAT_INFO ci[] =
|
|
|
|
{
|
|
|
|
{"swchan", GodCheat, 0},
|
|
|
|
{"swgimme", ItemCheat, 0},
|
|
|
|
{"swtrek##", WarpCheat, 0},
|
|
|
|
{"swgreed", EveryCheatToggle, 0},
|
|
|
|
{"swghost", ClipCheat, 0},
|
|
|
|
|
|
|
|
{"swstart", RestartCheat, 0},
|
|
|
|
|
|
|
|
{"swres", ResCheatOn, 0},
|
|
|
|
{"swloc", LocCheat, 0},
|
|
|
|
{"swmap", MapCheat, 0},
|
|
|
|
{"swsave", SaveCheat, CF_ALL},
|
|
|
|
{"swroom", RoomCheat, CF_NOTSW}, // Room above room dbug
|
|
|
|
#if DEBUG
|
|
|
|
{"swsecret", SecretCheat, CF_ALL},
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// !JIM! My simplified version of CheatInput which simply processes MessageInputString
|
|
|
|
void CheatInput(void)
|
|
|
|
{
|
2015-05-19 21:58:29 +00:00
|
|
|
static SWBOOL cur_show;
|
2015-05-19 21:54:34 +00:00
|
|
|
int ret;
|
2015-05-19 21:58:29 +00:00
|
|
|
SWBOOL match = FALSE;
|
2015-05-19 21:54:34 +00:00
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
//if (CommEnabled)
|
|
|
|
// return;
|
|
|
|
|
|
|
|
strcpy(CheatInputString,MessageInputString);
|
|
|
|
|
|
|
|
// make sure string is lower cased
|
|
|
|
Bstrlwr(CheatInputString);
|
|
|
|
|
|
|
|
// check for at least one single match
|
|
|
|
for (i = 0; i < SIZ(ci); i++)
|
|
|
|
{
|
|
|
|
// compare without the NULL
|
|
|
|
if (cheatcmp(CheatInputString, ci[i].CheatInputCode, strlen(CheatInputString)) == 0)
|
|
|
|
{
|
|
|
|
|
|
|
|
// if they are equal in length then its a complet match
|
|
|
|
if (strlen(CheatInputString) == strlen(ci[i].CheatInputCode))
|
|
|
|
{
|
|
|
|
match = TRUE;
|
|
|
|
CheatInputMode = FALSE;
|
|
|
|
|
|
|
|
if (TEST(ci[i].flags, CF_NOTSW) && SW_SHAREWARE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!TEST(ci[i].flags, CF_ALL))
|
|
|
|
{
|
|
|
|
if (CommEnabled)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (Skill >= 3)
|
|
|
|
{
|
|
|
|
PutStringInfo(Player, "You're too skillful to cheat\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ci[i].CheatInputFunc)
|
|
|
|
(*ci[i].CheatInputFunc)(Player, CheatInputString);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
match = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!match)
|
|
|
|
{
|
|
|
|
////DSPRINTF(ds,"Lost A Match %s", CheatInputString);
|
|
|
|
//MONO_PRINT(ds);
|
|
|
|
|
|
|
|
CheatInputMode = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* OLD CODE
|
|
|
|
void CheatInput(void)
|
|
|
|
{
|
2015-05-19 21:58:29 +00:00
|
|
|
static SWBOOL cur_show;
|
2015-05-19 21:54:34 +00:00
|
|
|
signed char MNU_InputString(char *, short);
|
|
|
|
int ret;
|
2015-05-19 21:58:29 +00:00
|
|
|
SWBOOL match = FALSE;
|
2015-05-19 21:54:34 +00:00
|
|
|
short i;
|
|
|
|
|
|
|
|
// don't use InputMode here - its set for CheatInputMode
|
|
|
|
if (MessageInputMode || MenuInputMode)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!CheatInputMode)
|
|
|
|
{
|
2019-11-03 23:53:55 +00:00
|
|
|
if (inputState.GetKeyStatus(KEYSC_S))
|
2015-05-19 21:54:34 +00:00
|
|
|
{
|
2019-11-03 23:53:55 +00:00
|
|
|
//inputState.GetKeyStatus(KEYSC_S) = FALSE;
|
2015-05-19 21:54:34 +00:00
|
|
|
CheatInputMode = TRUE;
|
|
|
|
strcpy(CheatInputString,"s");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (CheatInputMode)
|
|
|
|
{
|
|
|
|
// get new chars
|
|
|
|
ret = MNU_InputString(CheatInputString, 320-20);
|
|
|
|
|
|
|
|
// quick check input
|
|
|
|
switch (ret)
|
|
|
|
{
|
|
|
|
case FALSE: // Input finished (RETURN)
|
|
|
|
case -1: // Cancel Input (pressed ESC) or Err
|
|
|
|
CheatInputMode = FALSE;
|
2019-11-03 23:53:55 +00:00
|
|
|
inputState.keyFlushChars();
|
2015-05-19 21:54:34 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
case TRUE: // Got input
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// make sure string is lower cased
|
2019-11-08 04:23:06 +00:00
|
|
|
Bstrlwr(CheatInputString);
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
// check for at least one single match
|
|
|
|
for (i = 0; i < SIZ(ci); i++)
|
|
|
|
{
|
|
|
|
// compare without the NULL
|
|
|
|
if (cheatcmp(CheatInputString, ci[i].CheatInputCode, strlen(CheatInputString)) == 0)
|
|
|
|
{
|
|
|
|
////DSPRINTF(ds,"%s",CheatInputString);
|
|
|
|
//MONO_PRINT(ds);
|
|
|
|
|
|
|
|
// if they are equal in length then its a complet match
|
|
|
|
if (strlen(CheatInputString) == strlen(ci[i].CheatInputCode))
|
|
|
|
{
|
|
|
|
////DSPRINTF(ds,"Found A Match %s", CheatInputString);
|
|
|
|
//MONO_PRINT(ds);
|
|
|
|
|
|
|
|
match = TRUE;
|
|
|
|
|
|
|
|
CheatInputMode = FALSE;
|
2019-11-03 23:53:55 +00:00
|
|
|
inputState.keyFlushChars();
|
2015-05-19 21:54:34 +00:00
|
|
|
|
|
|
|
if (ci[i].CheatInputFunc)
|
|
|
|
(*ci[i].CheatInputFunc)(Player, CheatInputString);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
match = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!match)
|
|
|
|
{
|
|
|
|
////DSPRINTF(ds,"Lost A Match %s", CheatInputString);
|
|
|
|
//MONO_PRINT(ds);
|
|
|
|
|
|
|
|
CheatInputMode = FALSE;
|
2019-11-03 23:53:55 +00:00
|
|
|
inputState.keyFlushChars();
|
2015-05-19 21:54:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*/
|
2019-10-09 16:09:05 +00:00
|
|
|
END_SW_NS
|