2016-09-14 18:01:13 +00:00
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Copyright(C) 2005-2016 Christoph Oelckers
|
|
|
|
// All rights reserved.
|
|
|
|
//
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 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 Lesser General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
|
|
// along with this program. If not, see http://www.gnu.org/licenses/
|
|
|
|
//
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
//
|
2013-06-23 07:49:34 +00:00
|
|
|
/*
|
|
|
|
** gl_data.cpp
|
|
|
|
** Maintenance data for GL renderer (mostly to handle rendering hacks)
|
|
|
|
**
|
2016-09-14 18:01:13 +00:00
|
|
|
**/
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
#include "gl/system/gl_system.h"
|
|
|
|
|
|
|
|
#include "doomtype.h"
|
|
|
|
#include "colormatcher.h"
|
|
|
|
#include "i_system.h"
|
|
|
|
#include "p_local.h"
|
2016-02-16 21:01:04 +00:00
|
|
|
#include "p_tags.h"
|
2013-06-23 07:49:34 +00:00
|
|
|
#include "p_lnspec.h"
|
|
|
|
#include "c_dispatch.h"
|
|
|
|
#include "r_sky.h"
|
|
|
|
#include "sc_man.h"
|
|
|
|
#include "w_wad.h"
|
|
|
|
#include "gi.h"
|
|
|
|
#include "g_level.h"
|
2016-12-05 21:22:46 +00:00
|
|
|
#include "doomstat.h"
|
|
|
|
#include "d_player.h"
|
2017-01-08 17:45:30 +00:00
|
|
|
#include "g_levellocals.h"
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2013-09-03 16:29:39 +00:00
|
|
|
#include "gl/system/gl_interface.h"
|
2013-06-23 07:49:34 +00:00
|
|
|
#include "gl/renderer/gl_renderer.h"
|
|
|
|
#include "gl/renderer/gl_lightdata.h"
|
|
|
|
#include "gl/data/gl_data.h"
|
|
|
|
#include "gl/dynlights/gl_dynlight.h"
|
|
|
|
#include "gl/dynlights/gl_glow.h"
|
|
|
|
#include "gl/models/gl_models.h"
|
|
|
|
#include "gl/utility/gl_clock.h"
|
|
|
|
#include "gl/shaders/gl_shader.h"
|
|
|
|
#include "gl/gl_functions.h"
|
|
|
|
|
|
|
|
GLRenderSettings glset;
|
|
|
|
|
|
|
|
EXTERN_CVAR(Int, gl_lightmode)
|
|
|
|
EXTERN_CVAR(Bool, gl_brightfog)
|
2016-12-06 11:58:45 +00:00
|
|
|
EXTERN_CVAR(Bool, gl_lightadditivesurfaces)
|
2016-12-07 22:17:18 +00:00
|
|
|
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
CUSTOM_CVAR(Bool, gl_notexturefill, false, 0)
|
|
|
|
{
|
|
|
|
glset.notexturefill = self;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void gl_CreateSections();
|
2018-02-21 22:12:46 +00:00
|
|
|
void AddAutoMaterials();
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Adjust sprite offsets for GL rendering (IWAD resources only)
|
|
|
|
//
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void AdjustSpriteOffsets()
|
|
|
|
{
|
2016-12-03 18:49:32 +00:00
|
|
|
int lump, lastlump = 0;
|
2017-02-14 21:03:46 +00:00
|
|
|
int sprid;
|
|
|
|
TMap<int, bool> donotprocess;
|
|
|
|
|
|
|
|
int numtex = Wads.GetNumLumps();
|
|
|
|
|
|
|
|
for (int i = 0; i < numtex; i++)
|
|
|
|
{
|
2017-10-21 08:10:36 +00:00
|
|
|
if (Wads.GetLumpFile(i) > Wads.GetIwadNum()) break; // we are past the IWAD
|
2017-09-13 08:19:03 +00:00
|
|
|
if (Wads.GetLumpNamespace(i) == ns_sprites && Wads.GetLumpFile(i) == Wads.GetIwadNum())
|
2017-02-14 21:03:46 +00:00
|
|
|
{
|
|
|
|
char str[9];
|
|
|
|
Wads.GetLumpName(str, i);
|
2017-02-27 00:58:21 +00:00
|
|
|
str[8] = 0;
|
2018-03-25 18:26:16 +00:00
|
|
|
FTextureID texid = TexMan.CheckForTexture(str, ETextureType::Sprite, 0);
|
2017-09-13 08:19:03 +00:00
|
|
|
if (texid.isValid() && Wads.GetLumpFile(TexMan[texid]->SourceLump) > Wads.GetIwadNum())
|
2017-02-14 21:03:46 +00:00
|
|
|
{
|
|
|
|
// This texture has been replaced by some PWAD.
|
|
|
|
memcpy(&sprid, str, 4);
|
|
|
|
donotprocess[sprid] = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-03 18:49:32 +00:00
|
|
|
while ((lump = Wads.FindLump("SPROFS", &lastlump, false)) != -1)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
FScanner sc;
|
|
|
|
sc.OpenLumpNum(lump);
|
2016-12-03 18:49:32 +00:00
|
|
|
sc.SetCMode(true);
|
2013-06-23 07:49:34 +00:00
|
|
|
GLRenderer->FlushTextures();
|
2013-12-09 10:34:26 +00:00
|
|
|
int ofslumpno = Wads.GetLumpFile(lump);
|
2013-06-23 07:49:34 +00:00
|
|
|
while (sc.GetString())
|
|
|
|
{
|
|
|
|
int x,y;
|
2016-12-03 18:49:32 +00:00
|
|
|
bool iwadonly = false;
|
2017-02-14 21:03:46 +00:00
|
|
|
bool forced = false;
|
2018-03-25 18:26:16 +00:00
|
|
|
FTextureID texno = TexMan.CheckForTexture(sc.String, ETextureType::Sprite);
|
2016-12-03 18:49:32 +00:00
|
|
|
sc.MustGetStringName(",");
|
|
|
|
sc.MustGetNumber();
|
2013-06-23 07:49:34 +00:00
|
|
|
x=sc.Number;
|
2016-12-03 18:49:32 +00:00
|
|
|
sc.MustGetStringName(",");
|
|
|
|
sc.MustGetNumber();
|
2013-06-23 07:49:34 +00:00
|
|
|
y=sc.Number;
|
2016-12-03 18:49:32 +00:00
|
|
|
if (sc.CheckString(","))
|
|
|
|
{
|
|
|
|
sc.MustGetString();
|
|
|
|
if (sc.Compare("iwad")) iwadonly = true;
|
2017-02-14 21:03:46 +00:00
|
|
|
if (sc.Compare("iwadforced")) forced = iwadonly = true;
|
2016-12-03 18:49:32 +00:00
|
|
|
}
|
2013-06-23 07:49:34 +00:00
|
|
|
if (texno.isValid())
|
|
|
|
{
|
|
|
|
FTexture * tex = TexMan[texno];
|
|
|
|
|
|
|
|
int lumpnum = tex->GetSourceLump();
|
2013-12-09 10:34:26 +00:00
|
|
|
// We only want to change texture offsets for sprites in the IWAD or the file this lump originated from.
|
2013-06-23 07:49:34 +00:00
|
|
|
if (lumpnum >= 0 && lumpnum < Wads.GetNumLumps())
|
|
|
|
{
|
|
|
|
int wadno = Wads.GetLumpFile(lumpnum);
|
2017-09-13 08:19:03 +00:00
|
|
|
if ((iwadonly && wadno==Wads.GetIwadNum()) || (!iwadonly && wadno == ofslumpno))
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2017-09-13 08:19:03 +00:00
|
|
|
if (wadno == Wads.GetIwadNum() && !forced && iwadonly)
|
2017-02-14 21:03:46 +00:00
|
|
|
{
|
|
|
|
memcpy(&sprid, &tex->Name[0], 4);
|
|
|
|
if (donotprocess.CheckKey(sprid)) continue; // do not alter sprites that only get partially replaced.
|
|
|
|
}
|
2013-06-23 07:49:34 +00:00
|
|
|
tex->LeftOffset=x;
|
|
|
|
tex->TopOffset=y;
|
|
|
|
tex->KillNative();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Portal identifier lists
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// MAPINFO stuff
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
struct FGLROptions : public FOptionalMapinfoData
|
|
|
|
{
|
|
|
|
FGLROptions()
|
|
|
|
{
|
|
|
|
identifier = "gl_renderer";
|
2014-12-31 22:01:06 +00:00
|
|
|
brightfog = false;
|
2013-06-23 07:49:34 +00:00
|
|
|
lightmode = -1;
|
|
|
|
notexturefill = -1;
|
|
|
|
skyrotatevector = FVector3(0,0,1);
|
|
|
|
skyrotatevector2 = FVector3(0,0,1);
|
2016-12-06 11:58:45 +00:00
|
|
|
lightadditivesurfaces = false;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
virtual FOptionalMapinfoData *Clone() const
|
|
|
|
{
|
|
|
|
FGLROptions *newopt = new FGLROptions;
|
|
|
|
newopt->identifier = identifier;
|
|
|
|
newopt->lightmode = lightmode;
|
|
|
|
newopt->notexturefill = notexturefill;
|
|
|
|
newopt->skyrotatevector = skyrotatevector;
|
|
|
|
newopt->skyrotatevector2 = skyrotatevector2;
|
2016-12-06 11:58:45 +00:00
|
|
|
newopt->lightadditivesurfaces = lightadditivesurfaces;
|
2013-06-23 07:49:34 +00:00
|
|
|
return newopt;
|
|
|
|
}
|
|
|
|
int lightmode;
|
|
|
|
int brightfog;
|
2016-12-06 11:58:45 +00:00
|
|
|
int8_t lightadditivesurfaces;
|
|
|
|
int8_t notexturefill;
|
2013-06-23 07:49:34 +00:00
|
|
|
FVector3 skyrotatevector;
|
|
|
|
FVector3 skyrotatevector2;
|
|
|
|
};
|
|
|
|
|
|
|
|
DEFINE_MAP_OPTION(brightfog, false)
|
|
|
|
{
|
|
|
|
FGLROptions *opt = info->GetOptData<FGLROptions>("gl_renderer");
|
|
|
|
parse.ParseAssign();
|
|
|
|
parse.sc.MustGetNumber();
|
|
|
|
opt->brightfog = parse.sc.Number;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFINE_MAP_OPTION(lightmode, false)
|
|
|
|
{
|
|
|
|
FGLROptions *opt = info->GetOptData<FGLROptions>("gl_renderer");
|
|
|
|
parse.ParseAssign();
|
|
|
|
parse.sc.MustGetNumber();
|
2017-03-08 17:47:52 +00:00
|
|
|
opt->lightmode = uint8_t(parse.sc.Number);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DEFINE_MAP_OPTION(notexturefill, false)
|
|
|
|
{
|
|
|
|
FGLROptions *opt = info->GetOptData<FGLROptions>("gl_renderer");
|
|
|
|
if (parse.CheckAssign())
|
|
|
|
{
|
|
|
|
parse.sc.MustGetNumber();
|
|
|
|
opt->notexturefill = !!parse.sc.Number;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
opt->notexturefill = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-06 11:58:45 +00:00
|
|
|
DEFINE_MAP_OPTION(lightadditivesurfaces, false)
|
|
|
|
{
|
|
|
|
FGLROptions *opt = info->GetOptData<FGLROptions>("gl_renderer");
|
|
|
|
if (parse.CheckAssign())
|
|
|
|
{
|
|
|
|
parse.sc.MustGetNumber();
|
|
|
|
opt->lightadditivesurfaces = !!parse.sc.Number;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
opt->lightadditivesurfaces = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-23 07:49:34 +00:00
|
|
|
DEFINE_MAP_OPTION(skyrotate, false)
|
|
|
|
{
|
|
|
|
FGLROptions *opt = info->GetOptData<FGLROptions>("gl_renderer");
|
|
|
|
|
|
|
|
parse.ParseAssign();
|
|
|
|
parse.sc.MustGetFloat();
|
|
|
|
opt->skyrotatevector.X = (float)parse.sc.Float;
|
|
|
|
if (parse.format_type == FMapInfoParser::FMT_New) parse.sc.MustGetStringName(",");
|
|
|
|
parse.sc.MustGetFloat();
|
|
|
|
opt->skyrotatevector.Y = (float)parse.sc.Float;
|
|
|
|
if (parse.format_type == FMapInfoParser::FMT_New) parse.sc.MustGetStringName(",");
|
|
|
|
parse.sc.MustGetFloat();
|
|
|
|
opt->skyrotatevector.Z = (float)parse.sc.Float;
|
|
|
|
opt->skyrotatevector.MakeUnit();
|
|
|
|
}
|
|
|
|
|
|
|
|
DEFINE_MAP_OPTION(skyrotate2, false)
|
|
|
|
{
|
|
|
|
FGLROptions *opt = info->GetOptData<FGLROptions>("gl_renderer");
|
|
|
|
|
|
|
|
parse.ParseAssign();
|
|
|
|
parse.sc.MustGetFloat();
|
|
|
|
opt->skyrotatevector2.X = (float)parse.sc.Float;
|
|
|
|
if (parse.format_type == FMapInfoParser::FMT_New) parse.sc.MustGetStringName(",");
|
|
|
|
parse.sc.MustGetFloat();
|
|
|
|
opt->skyrotatevector2.Y = (float)parse.sc.Float;
|
|
|
|
if (parse.format_type == FMapInfoParser::FMT_New) parse.sc.MustGetStringName(",");
|
|
|
|
parse.sc.MustGetFloat();
|
|
|
|
opt->skyrotatevector2.Z = (float)parse.sc.Float;
|
|
|
|
opt->skyrotatevector2.MakeUnit();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsLightmodeValid()
|
|
|
|
{
|
|
|
|
return (glset.map_lightmode >= 0 && glset.map_lightmode <= 4) || glset.map_lightmode == 8;
|
|
|
|
}
|
|
|
|
|
2016-12-07 22:17:18 +00:00
|
|
|
static void ResetOpts()
|
|
|
|
{
|
|
|
|
if (!IsLightmodeValid()) glset.lightmode = gl_lightmode;
|
|
|
|
else glset.lightmode = glset.map_lightmode;
|
|
|
|
if (glset.map_notexturefill == -1) glset.notexturefill = gl_notexturefill;
|
|
|
|
else glset.notexturefill = !!glset.map_notexturefill;
|
|
|
|
if (glset.map_brightfog == -1) glset.brightfog = gl_brightfog;
|
|
|
|
else glset.brightfog = !!glset.map_brightfog;
|
|
|
|
if (glset.map_lightadditivesurfaces == -1) glset.lightadditivesurfaces = gl_lightadditivesurfaces;
|
|
|
|
else glset.lightadditivesurfaces = !!glset.map_lightadditivesurfaces;
|
|
|
|
}
|
|
|
|
|
2013-06-23 07:49:34 +00:00
|
|
|
void InitGLRMapinfoData()
|
|
|
|
{
|
|
|
|
FGLROptions *opt = level.info->GetOptData<FGLROptions>("gl_renderer", false);
|
|
|
|
|
|
|
|
if (opt != NULL)
|
|
|
|
{
|
|
|
|
glset.map_lightmode = opt->lightmode;
|
2016-12-06 11:58:45 +00:00
|
|
|
glset.map_lightadditivesurfaces = opt->lightadditivesurfaces;
|
2013-06-23 07:49:34 +00:00
|
|
|
glset.map_brightfog = opt->brightfog;
|
|
|
|
glset.map_notexturefill = opt->notexturefill;
|
|
|
|
glset.skyrotatevector = opt->skyrotatevector;
|
|
|
|
glset.skyrotatevector2 = opt->skyrotatevector2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
glset.map_lightmode = -1;
|
2016-12-06 11:58:45 +00:00
|
|
|
glset.map_lightadditivesurfaces = -1;
|
2013-06-23 07:49:34 +00:00
|
|
|
glset.map_brightfog = -1;
|
|
|
|
glset.map_notexturefill = -1;
|
2016-12-07 22:17:18 +00:00
|
|
|
glset.skyrotatevector = FVector3(0, 0, 1);
|
|
|
|
glset.skyrotatevector2 = FVector3(0, 0, 1);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
2016-12-07 22:17:18 +00:00
|
|
|
ResetOpts();
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
CCMD(gl_resetmap)
|
|
|
|
{
|
2016-12-07 22:17:18 +00:00
|
|
|
ResetOpts();
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
2017-01-11 10:37:27 +00:00
|
|
|
// Recalculate all heights affecting this vertex.
|
2013-06-23 07:49:34 +00:00
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
void gl_RecalcVertexHeights(vertex_t * v)
|
|
|
|
{
|
|
|
|
int i,j,k;
|
|
|
|
float height;
|
|
|
|
|
|
|
|
v->numheights=0;
|
|
|
|
for(i=0;i<v->numsectors;i++)
|
|
|
|
{
|
|
|
|
for(j=0;j<2;j++)
|
|
|
|
{
|
2016-03-30 18:01:44 +00:00
|
|
|
if (j==0) height=v->sectors[i]->ceilingplane.ZatPoint(v);
|
|
|
|
else height=v->sectors[i]->floorplane.ZatPoint(v);
|
2013-06-23 07:49:34 +00:00
|
|
|
|
|
|
|
for(k=0;k<v->numheights;k++)
|
|
|
|
{
|
|
|
|
if (height == v->heightlist[k]) break;
|
|
|
|
if (height < v->heightlist[k])
|
|
|
|
{
|
|
|
|
memmove(&v->heightlist[k+1], &v->heightlist[k], sizeof(float) * (v->numheights-k));
|
|
|
|
v->heightlist[k]=height;
|
|
|
|
v->numheights++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (k==v->numheights) v->heightlist[v->numheights++]=height;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (v->numheights<=2) v->numheights=0; // is not in need of any special attention
|
|
|
|
v->dirty = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void gl_InitData()
|
|
|
|
{
|
|
|
|
AdjustSpriteOffsets();
|
2018-02-21 22:12:46 +00:00
|
|
|
AddAutoMaterials();
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// dumpgeometry
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
CCMD(dumpgeometry)
|
|
|
|
{
|
2017-01-07 18:32:24 +00:00
|
|
|
for(auto §or : level.sectors)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2017-01-07 18:32:24 +00:00
|
|
|
Printf(PRINT_LOG, "Sector %d\n", sector.sectornum);
|
|
|
|
for(int j=0;j<sector.subsectorcount;j++)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2017-01-07 18:32:24 +00:00
|
|
|
subsector_t * sub = sector.subsectors[j];
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2017-03-16 23:22:52 +00:00
|
|
|
Printf(PRINT_LOG, " Subsector %d - real sector = %d - %s\n", int(sub->Index()), sub->sector->sectornum, sub->hacked&1? "hacked":"");
|
2017-03-09 19:19:55 +00:00
|
|
|
for(uint32_t k=0;k<sub->numlines;k++)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
seg_t * seg = sub->firstline + k;
|
|
|
|
if (seg->linedef)
|
|
|
|
{
|
|
|
|
Printf(PRINT_LOG, " (%4.4f, %4.4f), (%4.4f, %4.4f) - seg %d, linedef %d, side %d",
|
2016-03-29 09:26:33 +00:00
|
|
|
seg->v1->fX(), seg->v1->fY(), seg->v2->fX(), seg->v2->fY(),
|
2017-03-16 20:33:13 +00:00
|
|
|
seg->Index(), seg->linedef->Index(), seg->sidedef != seg->linedef->sidedef[0]);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Printf(PRINT_LOG, " (%4.4f, %4.4f), (%4.4f, %4.4f) - seg %d, miniseg",
|
2017-03-16 20:33:13 +00:00
|
|
|
seg->v1->fX(), seg->v1->fY(), seg->v2->fX(), seg->v2->fY(), seg->Index());
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
if (seg->PartnerSeg)
|
|
|
|
{
|
|
|
|
subsector_t * sub2 = seg->PartnerSeg->Subsector;
|
|
|
|
Printf(PRINT_LOG, ", back sector = %d, real back sector = %d", sub2->render_sector->sectornum, seg->PartnerSeg->frontsector->sectornum);
|
|
|
|
}
|
|
|
|
else if (seg->backsector)
|
2017-01-07 18:32:24 +00:00
|
|
|
{
|
2013-06-23 07:49:34 +00:00
|
|
|
Printf(PRINT_LOG, ", back sector = %d (no partnerseg)", seg->backsector->sectornum);
|
|
|
|
}
|
|
|
|
|
|
|
|
Printf(PRINT_LOG, "\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|