2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-12-09 08:27:42 +00:00

ANIM fixes and explicit-endian refactor

This commit is contained in:
Jack Andersen
2015-08-13 17:00:51 -10:00
parent 5b38596595
commit b5d96f7040
20 changed files with 858 additions and 246 deletions

87
DataSpec/DNAMP2/ANCS.hpp Normal file
View File

@@ -0,0 +1,87 @@
#ifndef _DNAMP2_ANCS_HPP_
#define _DNAMP2_ANCS_HPP_
#include <map>
#include "../DNACommon/DNACommon.hpp"
#include "../DNACommon/ANCS.hpp"
#include "CMDLMaterials.hpp"
#include "BlenderConnection.hpp"
#include "CINF.hpp"
#include "CSKR.hpp"
#include "ANIM.hpp"
#include "../DNAMP1/ANCS.hpp"
namespace Retro
{
namespace DNAMP2
{
struct ANCS : BigYAML
{
using CINFType = CINF;
using CSKRType = CSKR;
using ANIMType = ANIM;
DECL_YAML
Value<atUint16> version;
DNAMP1::ANCS::CharacterSet characterSet;
DNAMP1::ANCS::AnimationSet animationSet;
void getCharacterResInfo(std::vector<DNAANCS::CharacterResInfo<UniqueID32>>& out) const
{
out.clear();
out.reserve(characterSet.characters.size());
for (const DNAMP1::ANCS::CharacterSet::CharacterInfo& ci : characterSet.characters)
{
out.emplace_back();
DNAANCS::CharacterResInfo<UniqueID32>& chOut = out.back();
chOut.name = ci.name;
chOut.cmdl = ci.cmdl;
chOut.cskr = ci.cskr;
chOut.cinf = ci.cinf;
}
}
void getAnimationResInfo(std::map<atUint32, std::pair<std::string, UniqueID32>>& out) const
{
out.clear();
for (const DNAMP1::ANCS::AnimationSet::Animation& ai : animationSet.animations)
ai.metaAnim.m_anim->gatherPrimitives(out);
}
static bool Extract(const SpecBase& dataSpec,
PAKEntryReadStream& rs,
const HECL::ProjectPath& outPath,
PAKRouter<PAKBridge>& pakRouter,
const DNAMP1::PAK::Entry& entry,
bool force)
{
ANCS ancs;
ancs.read(rs);
HECL::ProjectPath yamlPath = outPath.getWithExtension(_S(".yaml"));
if (force || yamlPath.getPathType() == HECL::ProjectPath::PT_NONE)
{
FILE* fp = HECL::Fopen(yamlPath.getAbsolutePath().c_str(), _S("wb"));
ancs.toYAMLFile(fp);
fclose(fp);
}
HECL::ProjectPath blendPath = outPath.getWithExtension(_S(".blend"));
if (force || blendPath.getPathType() == HECL::ProjectPath::PT_NONE)
{
HECL::BlenderConnection& conn = HECL::BlenderConnection::SharedConnection();
DNAANCS::ReadANCSToBlender<PAKRouter<PAKBridge>, ANCS, MaterialSet, 4>
(conn, ancs, blendPath, pakRouter, entry, dataSpec.getMasterShaderPath(), force);
return conn.saveBlend();
}
return true;
}
};
}
}
#endif // _DNAMP2_ANCS_HPP_

352
DataSpec/DNAMP2/ANIM.cpp Normal file
View File

@@ -0,0 +1,352 @@
#include "ANIM.hpp"
namespace Retro
{
namespace DNAMP2
{
void ANIM::IANIM::sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf) const
{
os.format("act.hecl_fps = round(%f)\n", (1.0f / mainInterval));
auto kit = chanKeys.begin();
for (const std::pair<atUint32, bool>& bone : bones)
{
os.format("bone_string = '%s'\n", cinf.getBoneNameFromId(bone.first)->c_str());
os << "action_group = act.groups.new(bone_string)\n"
"\n"
"rotCurves = []\n"
"rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=0, action_group=bone_string))\n"
"rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=1, action_group=bone_string))\n"
"rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=2, action_group=bone_string))\n"
"rotCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_quaternion', index=3, action_group=bone_string))\n"
"\n";
if (bone.second)
os << "bone_trans_head = (0.0,0.0,0.0)\n"
"if arm_obj.data.bones[bone_string].parent is not None:\n"
" bone_trans_head = Vector(arm_obj.data.bones[bone_string].head_local) - Vector(arm_obj.data.bones[bone_string].parent.head_local)\n"
"transCurves = []\n"
"transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=0, action_group=bone_string))\n"
"transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=1, action_group=bone_string))\n"
"transCurves.append(act.fcurves.new('pose.bones[\"'+bone_string+'\"].location', index=2, action_group=bone_string))\n"
"\n";
os << "crv = act.fcurves.new('pose.bones[\"'+bone_string+'\"].rotation_mode', action_group=bone_string)\n"
"crv.keyframe_points.add()\n"
"crv.keyframe_points[-1].co = (0, 0)\n"
"crv.keyframe_points[-1].interpolation = 'LINEAR'\n"
"\n";
const std::vector<DNAANIM::Value>& rotKeys = *kit++;
auto frameit = frames.begin();
for (const DNAANIM::Value& val : rotKeys)
{
atUint32 frame = *frameit++;
for (int c=0 ; c<4 ; ++c)
os.format("crv = rotCurves[%d]\n"
"crv.keyframe_points.add()\n"
"crv.keyframe_points[-1].interpolation = 'LINEAR'\n"
"crv.keyframe_points[-1].co = (%u, %f)\n",
c, frame, val.v4.vec[c]);
}
if (bone.second)
{
const std::vector<DNAANIM::Value>& transKeys = *kit++;
auto frameit = frames.begin();
for (const DNAANIM::Value& val : transKeys)
{
atUint32 frame = *frameit++;
for (int c=0 ; c<3 ; ++c)
os.format("crv = transCurves[%d]\n"
"crv.keyframe_points.add()\n"
"crv.keyframe_points[-1].interpolation = 'LINEAR'\n"
"crv.keyframe_points[-1].co = (%u, %f - bone_trans_head[%d])\n",
c, frame, val.v4.vec[c], c);
}
}
}
}
void ANIM::ANIM0::read(Athena::io::IStreamReader& reader)
{
Header head;
head.read(reader);
mainInterval = head.interval;
frames.clear();
frames.reserve(head.keyCount);
for (size_t k=0 ; k<head.keyCount ; ++k)
frames.push_back(k);
std::map<atUint8, atUint32> boneMap;
for (size_t b=0 ; b<head.boneSlotCount ; ++b)
{
atUint8 idx = reader.readUByte();
if (idx == 0xff)
continue;
boneMap[idx] = b;
}
atUint32 boneCount = reader.readUint32Big();
bones.clear();
bones.reserve(boneCount);
channels.clear();
for (size_t b=0 ; b<boneCount ; ++b)
{
bones.emplace_back(boneMap[b], false);
atUint8 idx = reader.readUByte();
channels.emplace_back();
DNAANIM::Channel& chan = channels.back();
chan.type = DNAANIM::Channel::ROTATION;
if (idx != 0xff)
{
bones.back().second = true;
channels.emplace_back();
DNAANIM::Channel& chan = channels.back();
chan.type = DNAANIM::Channel::TRANSLATION;
}
}
reader.readUint32Big();
chanKeys.clear();
chanKeys.reserve(channels.size());
for (const std::pair<atUint32, bool>& bone : bones)
{
chanKeys.emplace_back();
std::vector<DNAANIM::Value>& keys = chanKeys.back();
for (size_t k=0 ; k<head.keyCount ; ++k)
keys.emplace_back(reader.readVec4fBig());
if (bone.second)
chanKeys.emplace_back();
}
reader.readUint32Big();
auto kit = chanKeys.begin();
for (const std::pair<atUint32, bool>& bone : bones)
{
++kit;
if (bone.second)
{
std::vector<DNAANIM::Value>& keys = *kit++;
for (size_t k=0 ; k<head.keyCount ; ++k)
keys.emplace_back(reader.readVec3fBig());
}
}
evnt.read(reader);
}
void ANIM::ANIM0::write(Athena::io::IStreamWriter& writer) const
{
Header head;
head.unk0 = 0;
head.unk1 = 0;
head.unk2 = 0;
head.keyCount = frames.size();
head.duration = head.keyCount * mainInterval;
head.interval = mainInterval;
atUint32 maxId = 0;
for (const std::pair<atUint32, bool>& bone : bones)
maxId = MAX(maxId, bone.first);
head.boneSlotCount = maxId + 1;
head.write(writer);
for (size_t s=0 ; s<head.boneSlotCount ; ++s)
{
size_t boneIdx = 0;
bool found = false;
for (const std::pair<atUint32, bool>& bone : bones)
{
if (s == bone.first)
{
writer.writeUByte(boneIdx);
found = true;
break;
}
++boneIdx;
}
if (!found)
writer.writeUByte(0xff);
}
writer.writeUint32Big(bones.size());
size_t boneIdx = 0;
for (const std::pair<atUint32, bool>& bone : bones)
{
if (bone.second)
writer.writeUByte(boneIdx);
else
writer.writeUByte(0xff);
++boneIdx;
}
writer.writeUint32Big(bones.size() * head.keyCount);
auto cit = chanKeys.begin();
atUint32 transKeyCount = 0;
for (const std::pair<atUint32, bool>& bone : bones)
{
const std::vector<DNAANIM::Value>& keys = *cit++;
auto kit = keys.begin();
for (size_t k=0 ; k<head.keyCount ; ++k)
writer.writeVec4fBig((*kit++).v4);
if (bone.second)
{
transKeyCount += head.keyCount;
++cit;
}
}
writer.writeUint32Big(transKeyCount);
cit = chanKeys.begin();
for (const std::pair<atUint32, bool>& bone : bones)
{
++cit;
if (bone.second)
{
const std::vector<DNAANIM::Value>& keys = *cit++;
auto kit = keys.begin();
for (size_t k=0 ; k<head.keyCount ; ++k)
writer.writeVec3fBig((*kit++).v3);
}
}
evnt.write(writer);
}
void ANIM::ANIM2::read(Athena::io::IStreamReader& reader)
{
Header head;
head.read(reader);
evnt = head.evnt;
mainInterval = head.interval;
WordBitmap keyBmp;
keyBmp.read(reader, head.keyBitmapBitCount);
frames.clear();
atUint32 frameAccum = 0;
for (bool bit : keyBmp)
{
if (bit)
frames.push_back(frameAccum);
++frameAccum;
}
reader.seek(8);
bones.clear();
bones.reserve(head.boneChannelCount);
channels.clear();
channels.reserve(head.boneChannelCount);
size_t keyframeCount = 0;
for (size_t b=0 ; b<head.boneChannelCount ; ++b)
{
ChannelDesc desc;
desc.read(reader);
bones.emplace_back(desc.id, desc.keyCount2);
if (desc.keyCount1)
{
channels.emplace_back();
DNAANIM::Channel& chan = channels.back();
chan.type = DNAANIM::Channel::ROTATION;
chan.i[0] = desc.initRX;
chan.q[0] = desc.qRX;
chan.i[1] = desc.initRY;
chan.q[1] = desc.qRY;
chan.i[2] = desc.initRZ;
chan.q[2] = desc.qRZ;
}
keyframeCount = MAX(keyframeCount, desc.keyCount1);
if (desc.keyCount2)
{
channels.emplace_back();
DNAANIM::Channel& chan = channels.back();
chan.type = DNAANIM::Channel::TRANSLATION;
chan.i[0] = desc.initTX;
chan.q[0] = desc.qTX;
chan.i[1] = desc.initTY;
chan.q[1] = desc.qTY;
chan.i[2] = desc.initTZ;
chan.q[2] = desc.qTZ;
}
}
size_t bsSize = DNAANIM::ComputeBitstreamSize(keyframeCount, channels);
std::unique_ptr<atUint8[]> bsData = reader.readUBytes(bsSize);
DNAANIM::BitstreamReader bsReader;
chanKeys = bsReader.read(bsData.get(), keyframeCount, channels, head.rotDiv, head.translationMult);
}
void ANIM::ANIM2::write(Athena::io::IStreamWriter& writer) const
{
Header head;
head.evnt = evnt;
head.unk0 = 1;
head.interval = mainInterval;
head.unk1 = 3;
head.unk2 = 0;
head.unk3 = 1;
WordBitmap keyBmp;
size_t frameCount = 0;
for (atUint32 frame : frames)
{
while (keyBmp.getBit(frame))
++frame;
keyBmp.setBit(frame);
frameCount = frame + 1;
}
head.keyBitmapBitCount = frameCount;
head.duration = frameCount * mainInterval;
head.boneChannelCount = bones.size();
size_t keyframeCount = frames.size();
std::vector<DNAANIM::Channel> qChannels = channels;
DNAANIM::BitstreamWriter bsWriter;
size_t bsSize;
std::unique_ptr<atUint8[]> bsData = bsWriter.write(chanKeys, keyframeCount, qChannels,
head.rotDiv, head.translationMult, bsSize);
/* TODO: Figure out proper scratch size computation */
head.scratchSize = keyframeCount * channels.size() * 16;
head.write(writer);
keyBmp.write(writer);
writer.writeUint32Big(head.boneChannelCount);
writer.writeUint32Big(head.boneChannelCount);
auto cit = qChannels.begin();
for (const std::pair<atUint32, bool>& bone : bones)
{
ChannelDesc desc;
desc.id = bone.first;
DNAANIM::Channel& chan = *cit++;
desc.keyCount1 = keyframeCount;
desc.initRX = chan.i[0];
desc.qRX = chan.q[0];
desc.initRY = chan.i[1];
desc.qRY = chan.q[1];
desc.initRZ = chan.i[2];
desc.qRZ = chan.q[2];
if (bone.second)
{
DNAANIM::Channel& chan = *cit++;
desc.keyCount2 = keyframeCount;
desc.initTX = chan.i[0];
desc.qTX = chan.q[0];
desc.initTY = chan.i[1];
desc.qTY = chan.q[1];
desc.initTZ = chan.i[2];
desc.qTZ = chan.q[2];
}
desc.write(writer);
}
writer.writeUBytes(bsData.get(), bsSize);
}
}
}

174
DataSpec/DNAMP2/ANIM.hpp Normal file
View File

@@ -0,0 +1,174 @@
#ifndef _DNAMP2_ANIM_HPP_
#define _DNAMP2_ANIM_HPP_
#include "BlenderConnection.hpp"
#include "DNAMP2.hpp"
#include "../DNACommon/ANIM.hpp"
#include "CINF.hpp"
namespace Retro
{
namespace DNAMP2
{
struct ANIM : BigDNA
{
Delete expl;
struct IANIM : BigDNA
{
Delete expl;
atUint32 m_version;
IANIM(atUint32 version) : m_version(version) {}
std::vector<std::pair<atUint32, bool>> bones;
std::vector<atUint32> frames;
std::vector<DNAANIM::Channel> channels;
std::vector<std::vector<DNAANIM::Value>> chanKeys;
float mainInterval = 0.0;
UniqueID32 evnt;
void sendANIMToBlender(HECL::BlenderConnection::PyOutStream&, const CINF&) const;
};
struct ANIM0 : IANIM
{
DECL_EXPLICIT_DNA
ANIM0() : IANIM(0) {}
struct Header : BigDNA
{
DECL_DNA
Value<float> duration;
Value<atUint32> unk0;
Value<float> interval;
Value<atUint32> unk1;
Value<atUint32> keyCount;
Value<atUint32> unk2;
Value<atUint32> boneSlotCount;
};
};
struct ANIM2 : IANIM
{
DECL_EXPLICIT_DNA
ANIM2() : IANIM(2) {}
struct Header : BigDNA
{
DECL_DNA
Value<atUint32> scratchSize;
UniqueID32 evnt;
Value<atUint32> unk0;
Value<float> duration;
Value<float> interval;
Value<atUint32> unk1;
Value<atUint32> unk2;
Value<atUint32> rotDiv;
Value<float> translationMult;
Value<atUint32> boneChannelCount;
Value<atUint32> unk3;
Value<atUint32> keyBitmapBitCount;
};
struct ChannelDesc : BigDNA
{
Delete expl;
Value<atUint32> id = 0;
Value<atUint16> keyCount1 = 0;
Value<atUint16> initRX = 0;
Value<atUint8> qRX = 0;
Value<atUint16> initRY = 0;
Value<atUint8> qRY = 0;
Value<atUint16> initRZ = 0;
Value<atUint8> qRZ = 0;
Value<atUint16> keyCount2 = 0;
Value<atUint16> initTX = 0;
Value<atUint8> qTX = 0;
Value<atUint16> initTY = 0;
Value<atUint8> qTY = 0;
Value<atUint16> initTZ = 0;
Value<atUint8> qTZ = 0;
void read(Athena::io::IStreamReader& reader)
{
id = reader.readUint32Big();
keyCount1 = reader.readUint16Big();
initRX = reader.readUint16Big();
qRX = reader.readUByte();
initRY = reader.readUint16Big();
qRY = reader.readUByte();
initRZ = reader.readUint16Big();
qRZ = reader.readUByte();
keyCount2 = reader.readUint16Big();
if (keyCount2)
{
initTX = reader.readUint16Big();
qTX = reader.readUByte();
initTY = reader.readUint16Big();
qTY = reader.readUByte();
initTZ = reader.readUint16Big();
qTZ = reader.readUByte();
}
}
void write(Athena::io::IStreamWriter& writer) const
{
writer.writeUint32Big(id);
writer.writeUint16Big(keyCount1);
writer.writeUint16Big(initRX);
writer.writeUByte(qRX);
writer.writeUint16Big(initRY);
writer.writeUByte(qRY);
writer.writeUint16Big(initRZ);
writer.writeUByte(qRZ);
writer.writeUint16Big(keyCount2);
if (keyCount2)
{
writer.writeUint16Big(initTX);
writer.writeUByte(qTX);
writer.writeUint16Big(initTY);
writer.writeUByte(qTY);
writer.writeUint16Big(initTZ);
writer.writeUByte(qTZ);
}
}
};
};
std::unique_ptr<IANIM> m_anim;
void read(Athena::io::IStreamReader& reader)
{
atUint32 version = reader.readUint32Big();
switch (version)
{
case 0:
m_anim.reset(new struct ANIM0);
m_anim->read(reader);
break;
case 2:
m_anim.reset(new struct ANIM2);
m_anim->read(reader);
break;
default:
Log.report(LogVisor::Error, "unrecognized ANIM version");
break;
}
}
void write(Athena::io::IStreamWriter& writer) const
{
writer.writeUint32Big(m_anim->m_version);
m_anim->write(writer);
}
void sendANIMToBlender(HECL::BlenderConnection::PyOutStream& os, const CINF& cinf) const
{
m_anim->sendANIMToBlender(os, cinf);
}
};
}
}
#endif // _DNAMP2_ANIM_HPP_

View File

@@ -1,10 +1,13 @@
make_dnalist(liblist
MLVL
ANIM
ANCS
CMDLMaterials
CINF
CSKR)
add_library(DNAMP2
DNAMP2.hpp DNAMP2.cpp
${liblist}
ANIM.cpp
CMDL.hpp
STRG.hpp STRG.cpp)

View File

@@ -3,6 +3,7 @@
#include "STRG.hpp"
#include "MLVL.hpp"
#include "CMDL.hpp"
#include "ANCS.hpp"
#include "../DNACommon/TXTR.hpp"
namespace Retro
@@ -188,7 +189,9 @@ ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const DNAMP1::PAK::Entry& ent
case SBIG('TXTR'):
return {TXTR::Extract, nullptr, ".png"};
case SBIG('CMDL'):
return {nullptr, CMDL::Extract, ".blend", 1};
return {nullptr, CMDL::Extract, ".blend", 2};
case SBIG('ANCS'):
return {nullptr, ANCS::Extract, nullptr, 1};
}
return {};
}

View File

@@ -8,8 +8,8 @@ namespace DNAMP2
void STRG::_read(Athena::io::IStreamReader& reader)
{
atUint32 langCount = reader.readUint32();
atUint32 strCount = reader.readUint32();
atUint32 langCount = reader.readUint32Big();
atUint32 strCount = reader.readUint32Big();
std::vector<FourCC> readLangs;
readLangs.reserve(langCount);
@@ -21,8 +21,8 @@ void STRG::_read(Athena::io::IStreamReader& reader)
reader.seek(8);
}
atUint32 nameCount = reader.readUint32();
atUint32 nameTableSz = reader.readUint32();
atUint32 nameCount = reader.readUint32Big();
atUint32 nameTableSz = reader.readUint32Big();
std::unique_ptr<uint8_t[]> nameTableBuf(new uint8_t[nameTableSz]);
reader.readUBytesToBuf(nameTableBuf.get(), nameTableSz);
struct NameIdxEntry
@@ -43,7 +43,7 @@ void STRG::_read(Athena::io::IStreamReader& reader)
std::vector<std::wstring> strs;
reader.seek(strCount * 4);
for (atUint32 s=0 ; s<strCount ; ++s)
strs.emplace_back(reader.readWString());
strs.emplace_back(reader.readWStringBig());
langs.emplace_back(lang, strs);
}
@@ -55,12 +55,11 @@ void STRG::_read(Athena::io::IStreamReader& reader)
void STRG::read(Athena::io::IStreamReader& reader)
{
reader.setEndian(Athena::BigEndian);
atUint32 magic = reader.readUint32();
atUint32 magic = reader.readUint32Big();
if (magic != 0x87654321)
Log.report(LogVisor::Error, "invalid STRG magic");
atUint32 version = reader.readUint32();
atUint32 version = reader.readUint32Big();
if (version != 1)
Log.report(LogVisor::Error, "invalid STRG version");
@@ -69,18 +68,17 @@ void STRG::read(Athena::io::IStreamReader& reader)
void STRG::write(Athena::io::IStreamWriter& writer) const
{
writer.setEndian(Athena::BigEndian);
writer.writeUint32(0x87654321);
writer.writeUint32(1);
writer.writeUint32(langs.size());
writer.writeUint32Big(0x87654321);
writer.writeUint32Big(1);
writer.writeUint32Big(langs.size());
atUint32 strCount = STRG::count();
writer.writeUint32(strCount);
writer.writeUint32Big(strCount);
atUint32 offset = 0;
for (const std::pair<FourCC, std::vector<std::wstring>>& lang : langs)
{
lang.first.write(writer);
writer.writeUint32(offset);
writer.writeUint32Big(offset);
offset += strCount * 4 + 4;
atUint32 langStrCount = lang.second.size();
atUint32 tableSz = strCount * 4;
@@ -98,19 +96,19 @@ void STRG::write(Athena::io::IStreamWriter& writer) const
tableSz += 1;
}
}
writer.writeUint32(tableSz);
writer.writeUint32Big(tableSz);
}
atUint32 nameTableSz = names.size() * 8;
for (const std::pair<std::string, int32_t>& name : names)
nameTableSz += name.first.size() + 1;
writer.writeUint32(names.size());
writer.writeUint32(nameTableSz);
writer.writeUint32Big(names.size());
writer.writeUint32Big(nameTableSz);
offset = names.size() * 8;
for (const std::pair<std::string, int32_t>& name : names)
{
writer.writeUint32(offset);
writer.writeInt32(name.second);
writer.writeUint32Big(offset);
writer.writeInt32Big(name.second);
offset += name.first.size() + 1;
}
for (const std::pair<std::string, int32_t>& name : names)
@@ -122,7 +120,7 @@ void STRG::write(Athena::io::IStreamWriter& writer) const
atUint32 langStrCount = lang.second.size();
for (atUint32 s=0 ; s<strCount ; ++s)
{
writer.writeUint32(offset);
writer.writeUint32Big(offset);
if (s < langStrCount)
offset += lang.second[s].size() * 2 + 1;
else
@@ -132,7 +130,7 @@ void STRG::write(Athena::io::IStreamWriter& writer) const
for (atUint32 s=0 ; s<strCount ; ++s)
{
if (s < langStrCount)
writer.writeWString(lang.second[s]);
writer.writeWStringBig(lang.second[s]);
else
writer.writeUByte(0);
}