00003 不思议迷宫.0010.1.1:csb解析显示


00003 不思议迷宫.0010.1.1csb解析显示

游戏的csb文件在最新版的cocos2dx中无法直接使用(格式不对,无法解析)。在反编译libcocos2dlua.so中,查看cocos2dVersion函数:

const char*__fastcall cocos2d::cocos2dVersion(cocos2d *this)

{

  return "cocos2d-x3.3rc0";

}

它清楚地告诉我们,游戏是用cocos2d-x 3.3rc0开发的。

于是我就想办法下载cocos2d-x 3.3rc0。我先是从网上找,无果。后来突然发现自己实在是犯傻,因为cocos2dx是个开源项目,在github上有现成的,各个版本都有。于是就去github上下载了3.3rc0。但下载下来的压缩包只有50M,解压后也只有100M,一些东西都不全。仔细看了一下,原来还需要运行一下download-deps.py。然而运行后,在安装第二个依赖项时出错,报什么什么“cocos-binary-for-code-ide-3-lua-runtime-1.5 not a directory。同时,在cocos2d-x 3.3rc0的目录下发现一个deprecated-cocos-binary-for-code-ide-3-lua-runtime-1.5文件夹。原来是文件名不匹配。我以为改个名字就好,结果还不行。那我就手动安装吧。打开download-deps.py,看看相关的代码:

    print("==> Prepare to download luaruntime binaries")

    runtime_path =os.path.join(workpath, 'templates', 'lua-template-runtime', 'runtime')

   installer = CocosZipInstaller(workpath, os.path.join(runtime_path,'config.json'), os.path.join(runtime_path, 'version.json'))

    installer.run(workpath, runtime_path, opts.remove_downloaded,opts.force_update, opts.download_only)

安装到runtime_path这个目录。于是就把deprecated-cocos-binary-for-code-ide-3-lua-runtime-1.5下的内容剪切到cocos2d-x 3.3rc0/ templates/lua-template-runtime/runtime目录下,搞定。

接下来执行setup.py。结果发现搜索到的环境变量和已安装的cocos2dx有冲突,没敢继续,那就不执行了,不用cocos命令行创建工程了,改为自己手动拷贝。

建立起工程,执行,然后——解析错误。有点莫名其妙(现在想想,可能是中间某个步骤操作失误),又换成3.3rc1试了一下,发现终于可以了:

一些东西显示得不对,还需要调一调。先看看游戏是怎么弄的:

……

local frameWidth =cc.Director:getInstance():getOpenGLView():getFrameSize().width;

local frameHeight =cc.Director:getInstance():getOpenGLView():getFrameSize().height;

 

    -- 布局不使用缩放,而是代码自行实现自适应布局

    local w = frameWidth;

    local h =frameHeight;

   cc.Director:getInstance():getOpenGLView():setDesignResolutionSize(w, h,0);

……

 

function applicationScreenSizeChanged(width, height)

    ……

    local oldSize= cc.Director:getInstance():getOpenGLView():getFrameSize();

    ifoldSize.width ~= width or oldSize.height ~= height then

        ……

        localsize = cc.Director:getInstance():getOpenGLView():getDesignResolutionSize();

 

       cc.Director:getInstance():getOpenGLView():setFrameSize(width, height);

       cc.Director:getInstance():getOpenGLView():setDesignResolutionSize(size.width,size.height, 0);

       cc.Director:getInstance():setViewport();

    end

end

无论如何,DesignResolutionSize是保持不变的,为OpenGLView的初始FrameSize。示例中的位置该如何调整呢?还是先看看官方是怎么弄的:

functionUIDungeonMain:ctor(levelData, floor)

    ……

    local node =cc.CSLoader:createNode("layout/dungeon/DungeonMain.csb");

    self:addChild(node);

    ……

    self.panel = findChildByName(node,"CT1/panel");

    self.attackLabel =findChildByName(self.node, "CT2/atk_val");

    self.magicLabel =findChildByName(self.node, "CT2/magic_val");

    self.hpLabel = findChildByName(self.node,"CT2/hp_val");

    self.mpLabel = findChildByName(self.node,"CT2/mp_val");

    self.specialImage =findChildByName(self.node, "CT2/specil");

    self.gainImage = findChildByName(self.node,"CT2/gain");

    self.debuffsImage =findChildByName(self.node, "CT2/debuffs");

……

    resize(node);

……

end

resize这个函数很可能就是重点了:

-- 适配

resize = function(node)

    local w =AlignM.frameSize.width;

    local h =AlignM.frameSize.height;

   node:setContentSize(w, h);

 

    local scale;

    if h / w> 1.5 then

        scale =w / (DESIGN_WIDTH);

    else

        -- 在宽高比小于等于1.5时(如iphoneipad),需要略微比预定比例缩小些。 所以加了75像素

        scale =h / (DESIGN_HEIGHT + 75);

    end

 

    local topBg= findChildByName(node, "CT1/top_bg");

    localbottomBg = findChildByName(node, "CT1/bottom_bg");

    local mask =findChildByName(node, "CT1/mask");

    localnewWidth = w / scale;

   topBg:setScaleX(newWidth/topBg:getContentSize().width);

   bottomBg:setScaleX(newWidth/bottomBg:getContentSize().width);

   topBg:setScaleY(topBg:getScaleY());

   bottomBg:setScaleY(bottomBg:getScaleY());

   mask:setScaleX(newWidth/mask:getContentSize().width);

 

    local ct1 =findChildByName(node, "CT1");

   ct1:setPosition(w / 2, h / 2);

   ct1:setScale(scale);

 

    localscale2;

    if h / w>= 1.5 then

        scale2 =w / (DESIGN_WIDTH);

    else

        scale2 =h / (DESIGN_HEIGHT);

    end

 

    -- 底部菜单按原来适配规则缩放

    local ct2 =findChildByName(node, "CT2");

   ct2:setPosition(w / 2, 0);

   ct2:setScale(scale2);

    ……

end

AlignM.frameSize是什么?

frameSize =cc.Director:getInstance():getOpenGLView():getFrameSize();

DESIGN_WIDTHDESIGN_HEIGHT是什么?

DESIGN_WIDTH = 640;

DESIGN_HEIGHT = 960;

我想在我的cocos2dx-cpp工程中完美重现游戏的画面,于是我试图将lua代码转换成c++代码。在这么干了小半天之后,我就发现自己傻逼了:放着好好的lua代码不用,干嘛还转换成C++

如果没有额外的C++代码,或者有但很方便还原,甚至可以还原全部开发环境,进行重新打包,在AppStore上架。我就试了试:重建cocos2dx-lua工程,拷贝资源和lua代码,执行后断断续续地出现一个问题。

1. [LUA ERROR] [string" core/module/EventMgr.luac "]:19: attempt to call global 'get_daemon_data' (a nil value)get_daemon_data这个函数其实已经定义,在core/base/DaemonData.luac中。于是在EventMgr.luac中添加:require "core/base/DaemonData"

2. [LUA ERROR] [string"core/base/File.luac"]:5: module 'lfs' not foundcocos2dx 3.3rc1居然没有集成lfs。郁闷之余只好自己安装。到https://github.com/keplerproject/luafilesystem下载源码,将src目录下的lfs.hlfs.c这两个文件拷贝到工程目录下的/frameworks/runtime-src/Classes中(当然,拷贝到其他的目录中也可以,比如/frameworks/cocos2d-x/下的某个。不过,这样的话,如果使用的是预编译库,就需要重新生成liblua.a等)。将lfs.hlfs.c添加到工程,打开lua_module_register.h,作如下更改:

添加:#include "lfs.h"

在函数int lua_module_register(lua_State* L)中添加:

    lua_getglobal(L, "package");

    lua_getfield(L, -1, "preload");

    lua_pushcfunction(L, luaopen_lfs);

    lua_setfield(L, -2, "lfs");

lua_pop(L, 2);

3. [LUA ERROR] [string"core/module/PktAnalyser.luac"]:175: attempt to call global 'add_map_define' (a nil value):这个问题看起来和第一个类似,但它们并不是一回事。因为add_map_define并不是lua中定义的函数,而是由c++导出到lua中的函数。打开libcocos2dlua.so反编译,在字符串中搜索“add_map_define”,可以搜索到,但由于idabug或者其他什么原因,看不到任何对它的引用。在函数中搜索“add_map_define”,也可以搜索到:

int __fastcalladd_map_define(CommMgr *a1)

{

  CommMgr *v1; // r4@1

  CommMgr *v2; // r0@1

 

  v1 = a1;

  v2 = CommMgr::getInstance(a1);

  CommMgr::AddMapDefine((int)v2,(int)v1);

  return 0;

}

函数的参数类型错了,应当是lua_State*

如何在C++中还原出add_map_define函数呢?这很痛苦,要仔细分析代码。

getInstance本身没啥好说的,一个简单的单件:

CommMgr *__fastcallCommMgr::getInstance(CommMgr *this)

{

 CommMgr *v1; // r4@1

 

  v1 =(CommMgr *)dword_9B4CB0;

  if (!dword_9B4CB0 )

  {

    v1= (CommMgr *)j_operator new(0x90u);

   CommMgr::CommMgr(v1);

   dword_9B4CB0 = (int)v1;

  }

 return v1;

}

CommMgr 对象的大小是0x90u。这个单件函数在首次构造实例的时候,会调用CommMgr的构造函数,这个麻烦:

CommMgr *__fastcall CommMgr::CommMgr(CommMgr*this)

{

 CommMgr *v1; // r4@1

 

  v1 = this;

 *(_DWORD *)this = &off_977C08;

 CUtlBuffer::CUtlBuffer((CommMgr *)((char *)this + 4), 10240, 51200, 0);

 CUtlBuffer::CUtlBuffer((CommMgr *)((char *)v1 + 28), 10240, 51200, 0);

 j_j___aeabi_memset((char *)v1 + 56, 20, 0);

 *((_DWORD *)v1 + 16) = (char *)v1 + 56;

 *((_DWORD *)v1 + 17) = (char *)v1 + 56;

 j_j___aeabi_memset((char *)v1 + 80, 20, 0);

 *((_DWORD *)v1 + 22) = (char *)v1 + 80;

 *((_DWORD *)v1 + 23) = (char *)v1 + 80;

 j_j___aeabi_memset((char *)v1 + 104, 20, 0);

 *((_DWORD *)v1 + 28) = (char *)v1 + 104;

 *((_DWORD *)v1 + 29) = (char *)v1 + 104;

 *((_BYTE *)v1 + 140) = 0;

 return v1;

}

B了,CommMgr又用到了新的类型:CUtlBuffer

CUtlBuffer*__fastcall CUtlBuffer::CUtlBuffer(CUtlBuffer *this, int a2, int a3, bool a4)

{

  bool v4; // r4@1

  CUtlBuffer *v5; // r5@1

 

  v4 = a4;

  v5 = this;

  *(_DWORD *)this = 0;

  *((_DWORD *)this + 1) = a3;

  *((_DWORD *)this + 2) = a2;

  if ( a3 )

    *(_DWORD *)this = j_j_malloc(a3);

  *((_BYTE *)v5 + 20) = 0;

  *((_DWORD *)v5 + 3) = 0;

  *((_DWORD *)v5 + 4) = 0;

  *((_BYTE *)v5 + 21) = v4;

  return v5;

}

值得庆幸,CUtlBuffer没有继承自啥,也没有用到其他类型。翻译过来大概是这么一个东西:

class CUtlBuffer

{

public:

            CUtlBuffer(intsize_, int capacity_, boola4) : buf(nullptr), capacity(capacity_), size(size_),o3(0), o4(0), o20(0), o21(a4)

            {

                       if(capacity_) this->buf = newBYTE[capacity_];

            }

 

private:

            BYTE*buf;

            DWORDcapacity;

            DWORDsize;

            DWORDo3;

            DWORDo4;

            BYTEo20;

            boolo21;

};

需要弄明白其他一些字段的含义(即使是已命名字段,也只是猜测,需要确认)。看看CUtlBuffer的其他函数。在函数中搜索“CUtlBuffer::”,发现它还有另外一个构造:

int __fastcallCUtlBuffer::CUtlBuffer(int result, int a2, int a3, char a4)

{

  *(_DWORD *)result = a2;

  *(_DWORD *)(result + 4) = a3;

  *(_DWORD *)(result + 8) = -1;

  *(_BYTE *)(result + 20) = 0;

  *(_DWORD *)(result + 12) = 0;

  *(_DWORD *)(result + 16) = 0;

  *(_BYTE *)(result + 21) = a4;

  return result;

}

老问题,参数类型不对,正确的参数是:void const*,int,bool

            CUtlBuffer(voidconst*buf_, int capacity_, boola4) : buf(buf_), capacity(capacity_), o3(0), o4(0), o20(0), o21(a4)

            {

                       this->size= -1;

}

它对找出和确定成员的意义没有啥帮助。那就再看别的。其中一个EnsureCapacity看起来会有用:

int __fastcallCUtlBuffer::EnsureCapacity(CUtlBuffer *this, int a2)

{

  return CUtlMemory<unsignedchar>::EnsureCapacity(this, a2);

}

void *__fastcallCUtlMemory<unsigned char>::EnsureCapacity(int a1, signed int a2)

{

  int v2; // r4@1

  void *result; // r0@1

 

  v2 = a1;

  result = *(void**)(a1 + 4);

  if ( (signed int)result < a2 )

  {

    result = (void *)-1;

    if ( *(_DWORD*)(v2 + 8) != -1 )

    {

      *(_DWORD *)(v2 + 4) = a2;

      if ( *(_DWORD *)v2 )

        result = j_j_realloc(*(void **)v2, a2);

      else

        result = j_j_malloc(a2);

      *(_DWORD *)v2 = result;

    }

  }

  return result;

}

a1CUtlBuffer类型,红字部分的*(void **)(a1 + 4)正是CUtlBuffercapacity成员,这说明我们对该成员的理解没有错。蓝字部分的*(_DWORD *)(v2 + 8)CUtlBuffersize成员,根据经验(STL中的capacitysize),这个成员也没错。

我们在看看CUtlBuffer::Get

int __fastcallCUtlBuffer::Get(CUtlBuffer *this, void *a2, int a3)

{

  ……

  v3 = a3;

  v4 = this;

  j_j___aeabi_memcpy(a2, *(_DWORD *)this +*((_DWORD *)this + 3), a3);

  result = *((_DWORD *)v4 + 3) + v3;

  *((_DWORD *)v4 + 3) = result;

  return result;

}

翻译并精简后的代码:

            DWORDGet(void *outBuf, intcount)

            {

                       memcpy(outBuf,this->buf+ this->o3, count);

                       this->o3+= count;

                       returnthis->o3;

}

可以看出,o3其实读取buf时所用的索引、偏移,改成nextReadingPosition。继续下看,找个比较简单又有其他字段出现的,比如CheckGet

signed int__fastcall CUtlBuffer::CheckGet(CUtlBuffer *this, int a2)

{

  ……

  v2 = this;

  v3 = *((_DWORD *)this + 3) + a2;

  if ( *((_DWORD *)v2 + 1) >= v3 )

  {

    *((_BYTE *)v2 + 20) = 0;

    result = 1;

  }

  else

  {

    if ( *((_DWORD *)v2 + 4) < v3 )

      cocos2d::log((cocos2d *)"%s, %d,CUtlBuffer get overflow \n", "CheckGet", 276);

    *((_BYTE *)v2 + 20) |= 2u;

    result = 0;

  }

  return result;

}

            boolCheckGet(int count)

            {

                       DWORDposition = this->nextReadingPosition + count;

                       if(this->capacity>= position)

                       {

                                   this->o20= 0;

                                   returntrue;

                       }

                       else

                       {

                                   if(this->o4< position)

                                               cocos2d::log((cocos2d*)"%s, %d, CUtlBuffer get overflow \n","CheckGet", 276);

                                   this->o20|= 2u;

                                   returnfalse;

                       }

}

出现和o20o4。从代码上看,为什么比较的是capacity而不是size?确定Check的是Get而不是Set吗?还是说对capacitysize这两个字段的理解是错的?先留个疑问,继续下看:

int __fastcallCUtlBuffer::GetString(CUtlBuffer *this, char *a2, int a3)

{

  ……

  v3 = a2;

  v4 = this;

  if ( *((_BYTE *)this + 20) )

  {

LABEL_15:

    result = 0;

    *v3 = 0;

    return result;

  }

  v5 = 0x7FFFFFFF;

  if ( a3 )

    v5 = a3;

  if ( *((_BYTE *)this + 21) & 1 )

  {

    CUtlBuffer::EatWhiteSpace(this);

    v6 = *((_DWORD *)v4 + 3);

    v13 = *((_DWORD *)v4 + 1);

    if ( v6 < v13 )

    {

      v12 = v5 - 1;

      for( i = 0; ; ++i )

      {

        v8 = *(_BYTE *)(*(_DWORD *)v4 + v6);

        v9 = 0;

        if ( v8 != 255 )

          v9 = (*(_BYTE *)(v8 + ctype_ + 1)& 8u) >> 3;

        if ( v9 || !*(_BYTE *)(*(_DWORD *)v4 +v6) )

          break;

        if ( i < v12 )

        {

          *v3++ = v8;

          v6 = *((_DWORD *)v4 + 3);

        }

        *((_DWORD *)v4 + 3) = ++v6;

        if ( v6 >= v13 )

          break;

      }

    }

    goto LABEL_15;

  }

  v14 = (const char *)(*(_DWORD *)this +*((_DWORD *)this + 3));

  v11 = j_j_strlen(v14) + 1;

  if ( v11 <= v5 )

  {

    j_j___aeabi_memcpy(v3, v14, v11);

    result = *((_DWORD *)v4 + 3) + v11;

    *((_DWORD *)v4 + 3) = result;

  }

  else

  {

    j_j___aeabi_memcpy(v3, v14, v5);

    *((_DWORD *)v4 + 3) += v5;

    *(&v3[v5] + ~0) = 0u;

    result = v11 - v5 + *((_DWORD *)v4 + 3);

    *((_DWORD *)v4 + 3) = result;

  }

  return result;

}

这段代码没怎么看懂,还出现了一个外部变量ctype_,难了。还是先看个简单点的:

int __fastcallCUtlBuffer::EatWhiteSpace(int result)

{

  ……

  if ( *(_BYTE *)(result + 21) & 1 )

  {

    if ( !*(_BYTE *)(result + 20) )

    {

      v1 = *(_DWORD *)(result + 12);

      v2 = *(_DWORD *)(result + 4);

      if ( v1 < v2 )

      {

        v3 = *(_DWORD *)result;

        do

        {

          v4 = *(_BYTE *)(v3 + v1);

          if ( v4 == 255 )

            break;

          if ( !(*(_BYTE *)(v4 + ctype_ + 1)& 8) )

            break;

          *(_DWORD *)(result + 12) = ++v1;

        }

        while ( v1 < v2 );

      }

    }

  }

  return result;

}

还是用到了外部变量ctype_。看名字和C标准库中的ctype.h很有关系,经过一番查找后发现确实如此:

unsignedshort_ctype[257] = {

       0,                      /*-1 EOF   */

       _CONTROL,               /*00 (NUL) */

       _CONTROL,               /*01 (SOH) */

       _CONTROL,               /*02 (STX) */

        _CONTROL,               /* 03(ETX) */

       _CONTROL,               /*04 (EOT) */

       _CONTROL,               /*05 (ENQ) */

       _CONTROL,               /*06 (ACK) */

       _CONTROL,               /*07 (BEL) */

       _CONTROL,               /* 08 (BS)  */

       _SPACE+_CONTROL,        /*09 (HT)  */

       _SPACE+_CONTROL,        /*0A (LF)  */

       _SPACE+_CONTROL,        /*0B (VT)  */

       _SPACE+_CONTROL,        /*0C (FF)  */

       _SPACE+_CONTROL,        /*0D (CR)  */

        _CONTROL,               /* 0E(SI)  */

        ……

};

我只能说自己真的很无知,根本就不知道C标准库中还有这么一个东西。它的作用是指示所有ASCII字符的类型:控制字符、大写字符、小写字符、数字字符……唯一需要注意的是,下标0对应EOF,下标1才对应ASCII0。和它相关的还有另外一个导出变量:

_CRTIMP externunsignedshort*_pctype;

unsignedshort*_pctype = _ctype+1;

还有一系列用于判断字符类型的函数,这儿就不列举了。

翻译后的EatWhiteSpace代码:

            voidEatWhiteSpace()

            {

                       if(this->o21& 1)

                       {

                                   if(!this->o20)

                                   {

                                               DWORDposition = this->nextReadingPosition;

                                               if(position < this->capacity)

                                               {

                                                          do

                                                          {

                                                                      BYTEvalue = this->buf[position];

                                                                      if(value == 255) break;

                                                                      if(!isspace(value)) break;

                                                                      this->nextReadingPosition= ++position;

                                                          }while(position < this->capacity);

                                               }

                                   }

                       }

}

那么多的if嵌套,不知道这是ida造成的还是原始代码就这样,如果是后者,我只能呵呵了。为了更加方便理解,我给重构一下:

            voidEatWhiteSpace()

            {

                       if(!(this->o21 & 1)) return;

                       if(this->o20)return;

 

                       DWORDposition = this->nextReadingPosition;

                       if(position >= this->capacity) return;

 

                       do

                       {

                                   BYTEvalue = this->buf[position];

                                   if(value == 255) break;

                                   if(!isspace(value)) break;

                                   this->nextReadingPosition= ++position;

                       }while(position < this->capacity);

}

do……while没有whilefor便于理解,继续重构:

            voidEatWhiteSpace()

            {

                       if(!(this->o21 & 1)) return;

                       if(this->o20)return;

 

                       while(this->nextReadingPosition< this->capacity)

                       {

                                   BYTEvalue = this->buf[this->nextReadingPosition];

                                   if(value == 255) break;

                                   if(!isspace(value)) break;

                                   ++this->nextReadingPosition;

                       }

}

是不是好一点了?^_^ 如果知道o21&1的意义,还可以进一步重构,将它抽取为内联函数。

EatWhiteSpace中用到了o21o20,结合CheckGet,还是推敲不出什么来。捣鼓GetString?再等等吧,再试试SeekGet

int __fastcallCUtlBuffer::SeekGet(int result, int a2, int a3)

{

  int v3; // r1@3

 

  if ( a2 == 2 )

  {

    v3 = *(_DWORD *)(result + 4) - a3;

    goto LABEL_5;

  }

  if ( a2 == 1 )

  {

    v3 = *(_DWORD *)(result + 12) + a3;

LABEL_5:

    *(_DWORD *)(result + 12) = v3;

    return result;

  }

  if ( !a2 )

    *(_DWORD *)(result + 12) = a3;

  return result;

}

a2的类型是enum CUtlBuffer::SeekType_t。我也不知道它具体有哪些。但在SeekGet中,它至少有三个枚举项,初步翻译后的代码如下:

            enumSeekType

            {

                       Type0= 0,

                       Type1= 1,

                       Type2= 2,

            };

            voidSeekGet(SeekType seekType, int value)

            {

                       switch(seekType)

                       {

                       caseType0: this->nextReadingPosition = value; break;

                       caseType1: this->nextReadingPosition += value; break;

                       caseType2: this->nextReadingPosition = this->capacity- value; break;

                       }

}

三个枚举项的意义一目了然了,重构吧。

            enumSeekType

            {

                       SET= 0,

                       AFTER_CURRENT= 1,

                       BEFORE_END= 2,

            };

            voidSeekGet(SeekType seekType, int value)

            {

                       switch(seekType)

                       {

                       caseSET: this->nextReadingPosition = value; break;

                       caseAFTER_CURRENT: this->nextReadingPosition += value; break;

                       caseBEFORE_END: this->nextReadingPosition = this->capacity- value; break;

                       }

}

除了令人捉急的命名水平以外,没啥好说了。——好吧,还是有要说的——这个函数对确定剩余的成员变量的意义毫无作用,汗。

下面找和剩余的成员变量相关的函数:

signed int__fastcall CUtlBuffer::CheckPut(CUtlBuffer *this, int a2)

{

  int v2; // r5@1

  CUtlBuffer *i; // r4@1

  int v4; // r6@4

 

  v2 = a2;

  for ( i = this; *((_DWORD *)i + 1) <*((_DWORD *)i + 4) + v2; CUtlMemory<unsigned char>::Grow(i, 1) )

  {

    v4 = 0;

    if ( *((_DWORD *)i + 2) == -1 )

    {

      *((_BYTE *)i + 20) |= 1u;

      cocos2d::log((cocos2d*)"CUtlBuffer::CheckPut no free memory.\n", (const char *)0xFFE6F43B);

      return v4;

    }

  }

  *((_BYTE *)i + 20) = 0;

  return 1;

}

            boolCheckPut(int count)

            {

                       for(; this->capacity < this->o4+ count; CUtlMemory<unsigned char>::Grow(this,1))

                       {

                                   if(this->size== -1)

                                   {

                                               this->o20|= 1u;

                                               cocos2d::log("CUtlBuffer::CheckPut no free memory.\n");

                                               returnfalse;

                                   }

                       }

                       this->o20= 0;

                       returntrue;

}

CUtlMemory<unsignedchar>::Grow是如何实现的?请参考当前过程——我们正在还原CommMgr中用到的CUtlBuffer

CheckPut这个函数很有帮助。至少o4的意义大概可以想象了,和nextReadingPosition对应,为nextWritingPosition。结合CheckGeto20的意义也有眉目了。但为了更准确,还是先看看和CheckPut相关的Put

int __fastcallCUtlBuffer::Put(CUtlBuffer *this, const void *a2, int a3)

{

  ……

  v3 = a3;

  v4 = a2;

  v5 = this;

  result = CUtlBuffer::CheckPut(this, a3);

  if ( result == 1 )

  {

    j_j___aeabi_memcpy(*(_DWORD *)v5 +*((_DWORD *)v5 + 4), v4, v3);

    result = *((_DWORD *)v5 + 4) + v3;

    *((_DWORD *)v5 + 4) = result;

  }

  return result;

}

            DWORDPut(const void*inBuf, int length)

            {

                       if(!this->CheckPut(length)) return0;

 

                       memcpy(this->buf+ this->nextWritingPosition, inBuf,length);

                       this->nextWritingPosition+= length;

                       returnthis->nextWritingPosition;

}

失算了,nextWritingPosition确实可以确定,但o20,还是来猜猜吧。在CheckGet中,如果可以正常读取,o20就设置为0;否则,就|=2u。在EatWhiteSpace中,如果o20不为0,就return。在CheckPut中,如果可以正常写入,o20就设置为0;否则,就|=1u。这么综合来看,o20用于指示读写错误,0x01表示写错误,0x02表示读错误,0x03表示读写都错误。但令人不明白的是,可以正常读取和可以正常写入时为啥设置o200,而不是&=~0x01或者0x02?还有EatWhiteSpace中,为毛o20不为0return,就不用区分一下到底是写错误还是读错误?果然,还是我的理解有问题吧?

现在,还有一个o21这个成员没有确定其意义。在EatWhiteSpace中,如果!(this->o21& 1)return;在GetString(虽然我没有整理)中,仅当this->o21& 1时才进行。然后在PutStringPutUTF等函数中也用到o21,我就大概可以确定了,它是一种标识,用于确定是否可以处理字符串。

到此,CUtlBuffer的成员变量基本确定了,其全部成员函数花点时间也可转换出来,该回到CommMgr说说它的构造了?错了,我表示,我已经累了,这么转换要捣鼓到啥时候?

我发现CUtlBufferValveSource SDK中的有点类似。找出合适的版本替代?有这个想法,但想到游戏中还有其他的自定义代码,就放弃了。

这也就放弃了“还原全部开发环境”,回到原始的主题,“显示csb”。

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

00003 不思议迷宫.0010.1.1:csb解析显示

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭