游戏脚本开发日志1

 

一直难以净下心来好好完成一件事,彷徨了许久,最终觉得一个程序开发者的修养在于根基的牢固。

 

对游戏脚本有些兴趣,而且可以加深自己在语言方面的能力,所以开始研究学习脚本语言的实现,学习用书是游戏《脚本高级编程》,争取将书中所讲亲自实现一遍。

 

之前所有至 9.12.2008

    

    写汇编器用到的数据结构    

        字符串表、符号表、函数表、标签表、指令查找表、主应用程序API调用表。

    

    写字符处理功能函数

        包括标识符检测等

 

    更改了注释习惯

 

/*

    文件
       
        DataStructs.h

    内容
       
        汇编器用到的数据结构定义与对应的功能函数

    日期

        12.9.2008

    作者
       
        张锦

*/

#ifndef _DATASTRUCTS_H_
#define _DATASTRUCTS_H_


// ---- 宏 -----------------------------------------------------------------------------------

    // ---- 源代码与标识符 -------------------------------------------------------------------

        #define MAX_IDENT_SIZE          100     // 标识符最大长度
        #define MAX_SOURCE_LINE_SIZE    4096    // 源代码最大函数

    // ---- 指令查找表 -----------------------------------------------------------------------

        #define MAX_INSTR_MNEMONIC_SIZE 16      // 指令助记符字符串的最大长度
        #define MAX_INSTR_LOOKUP_COUNT  256     // 指令查找表存储的指令的最大个数
       
        // ---- 操作数类型位域掩码 -----------------------------------------------------------

            #define OP_FLAG_TYPE_INT        1       // 整形字面值
            #define OP_FLAG_TYPE_FLOAT      2       // 浮点型字面值
            #define OP_FLAG_TYPE_STRING     4       // 字符串型字面值
            #define OP_FLAG_TYPE_MEM_REF    8       // 内存引用
            #define OP_FLAG_TYPE_LINE_LABEL 16      // 行标签
            #define OP_FLAG_TYPE_FUNC_NAME  32      // 函数名(用于call指令)
            #define OP_FLAG_TYPE_REG        128     // 一个寄存器,即_RetVal
            #define OP_FLAG_TYPE_HOST_API_CALL 64   // 主应用程序API调用(用于CallHost指令中)

// ---- 数据结构 -----------------------------------------------------------------------------

    // ---- 汇编指令流 -----------------------------------------------------------------------

        struct Op
        {
            int     iType;      // 类型
            union
            {
                int     iIntLiteral;    // 整形字面量
                float   fFloatLiteral;  // 浮点型字面量
                int     iStringTableIndex;  // 字符串表索引
                int     iStackIndex;    // 堆栈索引
                int     iInstrIndex;    // 指令索引
                int     iFuncIndex;     // 函数索引
                int     iHostAPICallIndex;  // 主应用程序API调用索引
                int     iReg;           // 寄存器码
            };
            int     iOffsetIndex;       // 偏移量索引
        };

        struct Instr
        {
            int     iOpcode;    // 操作码
            int     iOpCount;   // 操作数
            Op      *pOpList;   // 指向操作数列表的指针
        };

    // ---- 脚本头 ---------------------------------------------------------------------------

        struct ScriptHeader
        {
            int     iStackSize;         // 要求的堆栈大小
            int     iGlobalDataSize;    // 脚本中全局数据的大小
            int     iIsMainFuncPresent; // _Main () 是否存在
            int     iMainFuncIndex;     // _Main () 函数的索引
        };

    // ---- 简单链表 -------------------------------------------------------------------------

        struct LinkedListNode 
        {
            void    *pData;             // 指向节点数据的指针
            LinkedListNode  *pNext;     // 指向链表中下一个节点的指针
        };

        struct LinkedList      
        {
            LinkedListNode  *pHead;     // 指向链表头节点的指针
            LinkedListNode  *pTail;     // 指向链表末节点的指针
            int     iNodeCount;         // 连表中节点的数量
        };

    // ---- 函数表 ---------------------------------------------------------------------------

        struct  FuncNode
        {
            int     iIndex;                     // 索引
            char    pstrName[MAX_IDENT_SIZE];   // 名称
            int     iEntryPoint;                // 入口点
            int     iParamCount;                // 参数个数
            int     iLocalDataSize;             // 局部数据大小
        };
       
    // ---- 符号表 ---------------------------------------------------------------------------

        struct SymbolNode
        {
            int     iIndex;                     // 索引
            char    pstrIdent[MAX_IDENT_SIZE];  // 标识符
            int     iSize;                      // 大小
            int     iStackIndex;                // 负号指向的堆栈索引
            int     iFuncIndex;                 // 负号所在的函数
        };

    // ---- 标签表 ---------------------------------------------------------------------------

        struct LabelNode
        {
            int     iIndex;         // 标签表节点
            int     iTargetIndex;   // 目标指令索引
            int     iFuncIndex;     // 标签所属函数
            char    pstrIdent[MAX_IDENT_SIZE];  // 标识符
        };

    // ---- 指令查找表 -----------------------------------------------------------------------

        typedef int OpTypes;
       
        struct InstrLookup
        {
            char    pstrMnemonic[MAX_INSTR_MNEMONIC_SIZE];  // 助记符
            int     iOpcode;    // 操作码
            int     iOpCount;   // 操作数个数
            OpTypes *OpList;    // 操作数类型列表指针
        };

   

// ---- 全局变量 -----------------------------------------------------------------------------

    // ---- 源代码缓存与计数 -----------------------------------------------------------------

        char    **g_ppstrSourceCode     = 0;
        int     g_iSourceCodeSize       = 0;

    // ---- 指令缓存与计数 -------------------------------------------------------------------

        Instr   *g_pInstrStream         = 0;
        int     g_iInstrStreamSize      = 0;

    // ---- 字符串表 -------------------------------------------------------------------------

        LinkedList  g_StringTable;

    // ---- 函数表 ---------------------------------------------------------------------------

        LinkedList  g_FuncTable;

    // ---- 标签表 ---------------------------------------------------------------------------

        LinkedList  g_LabelTable;

    // ---- 符号表 ---------------------------------------------------------------------------

        LinkedList  g_SymbolTable;

    // ---- 指令查找表 -----------------------------------------------------------------------

        InstrLookup g_InstrTable[MAX_INSTR_LOOKUP_COUNT];

    // ---- 主程序API调用表

        LinkedList  g_HostAPICallTable;

// ---- 函数原型 -----------------------------------------------------------------------------

    // ---- 简单链表 -------------------------------------------------------------------------

        int     AddFunc( char *pstrName, int iEntryPoint );
        void    InitLinkedList( LinkedList *pList );
        void    FreeLinkedList( LinkedList *pList );

    // ---- 字符串表 -------------------------------------------------------------------------

        int     AddString( LinkedList *pList, char *pstrString );

    // ---- 函数表 ---------------------------------------------------------------------------

        int     AddFunc( char * pstrName, int iEntryPoint );
        void    SetFuncInfo( char * pstrName, int iParamCount, int iLocalDataSize );
        FuncNode* GetFuncByName( char *pstrName );

    // ---- 符号表 ---------------------------------------------------------------------------

        int     AddSymbol( char *pstrIdent, int iSize, int iStackIndex, int iFuncIndex );
        int     GetSizeByIdent( char *pstrIdent, int iFuncIndex );
        int     GetStackIndexByIdent( char *pstrIdent, int iFuncIndex );
        SymbolNode* GetSymbolByIdent( char *pstrIdent, int iFuncIndex );

    // ---- 标签表 ---------------------------------------------------------------------------
      
        int     AddLabel( char *pstrIdent, int iTargetIndex, int iFuncIndex );
        LabelNode* GetLabelByIdent( char *pstrIdent, int iFuncIndex );   

    // ---- 指令查找表 -----------------------------------------------------------------------
       
        int     AddInstrLookup( char *pstrMnemonic, int iOpCode, int iOpCount );
        void    SetOpType( int iInstrIndex, int iOpIndex, OpTypes iOpType );


// ---- 函数定义 -----------------------------------------------------------------------------

    /*****************************************************************************************
    *
    *   AddNode()
    *
    *   向指定的简单链表链表添加节点
    */

    int AddNode( LinkedList *pList, void *pData )
    {
        // 创建一个新节点
       
        LinkedListNode  *pNewNode   = new LinkedListNode;

        // 把节点数据设定成指定的指针
       
        pNewNode->pData = pData;
       
        // 把下一个指针设为空
       
        pNewNode->pNext = 0;

        // 如果当前链表为空,则把头指针和末指针都设成新节点
       
        if( pList->iNodeCount == 0 )
        {
            pList->pHead = pList->pTail = pNewNode;
        }

        // 否则把它追加到链表的最后
       
        else
        {
            pList->pTail->pNext = pNewNode;
            pList->pTail    = pNewNode;
        }

        // 增大链表中节点的数量
       
        ++pList->iNodeCount;

        // 返回新的链表的大小减一,也就是新节点的索引
       
        return  pList->iNodeCount - 1;
    }

    /*****************************************************************************************
    *
    *   InitLinkedList()
    *
    *   初始化指定链表
    */

    void    InitLinkedList( LinkedList *pList )
    {
        pList->pHead    = 0;
        pList->pTail    = 0;
        pList->iNodeCount   = 0;
    }

    /*****************************************************************************************
    *
    *   FreeLinkedList()
    *
    *   释放指定链表
    */

    void FreeLinkedList( LinkedList *pList )
    {
        if( !pList )    return;

        if( pList->iNodeCount != 0 )
        {
            // 保存当前节点和下一个节点的指针
           
            LinkedListNode  *pCurrNode;
            LinkedListNode  *pNextNode;

            // 设定当前节点为链表头
           
            pCurrNode   = pList->pHead;

            // 遍历链表
           
            while(true)
            {
                // 释放当前节点前保存下一个节点的指针
               
                pNextNode   = pCurrNode->pNext;

                // 释放当前节点中的数据
               
                if( pCurrNode->pData != 0 )
                {
                    delete  pCurrNode->pData;
                }

                // 清除当前节点
               
                delete  pCurrNode;

                // 如果存在下一个节点则后移,否则退出循环
               
                if( pNextNode != 0 )
                {
                    pCurrNode   = pNextNode;
                }
                else
                {
                    break;
                }
            }  
        } 
    }

    /*****************************************************************************************
    *
    *   AddString()
    *
    *   向指定的表添加字符串
    */
    
    int AddString( LinkedList *pList, char *pstrString )
    {
        // 创建节点指针用于遍历

        LinkedListNode  *pNode  = pList->pHead;

        // 对表中的每一个节点循环操作

        for( int iCurrNode = 0 ; iCurrNode<pList->iNodeCount ; ++ iCurrNode )
        {
            if( strcmp( pstrString, (char*)pNode->pData ) == 0 )
            {
                return      iCurrNode;
            }
            else
            {
                pNode   = pNode->pNext;      
            }
        }

        // 字符串还没有添加,则添加新的字符串

        char    *pstrStringNode = new char[strlen(pstrString)+1];
        strcpy( pstrStringNode, pstrString );

        return  AddNode( pList, pstrStringNode );
    }

    /*****************************************************************************************
    *
    *   AddFunc()
    *
    *   向函数表添加函数
    */

    int     AddFunc( char *pstrName, int iEntryPoint )
    {
        // 如果指定函数名已经存在,则返回一个无效索引
       
        if( GetFuncByName( pstrName ) != 0 )
            return  -1;

        // 创建一个函数节点
       
        FuncNode    *pNewFunc   = new FuncNode;
        pNewFunc->iEntryPoint   = iEntryPoint;
        strcpy( pNewFunc->pstrName, pstrName );
       
        // 把函数节点添加到表中并取回索引
       
        pNewFunc->iIndex    = AddNode( &g_FuncTable, pNewFunc );

        // 返回新函数的索引
       
        return  pNewFunc->iIndex;
    }

    /*****************************************************************************************
    *
    *   SetFuncInfo()
    *
    *   设置函数表节点参数数量、局部数据大小
    */

    void SetFuncInfo( char *pstrName, int iParamCount, int iLocalDataSize )
    {
        // 在函数表中查找指定函数
       
        FuncNode    *pFunc  = GetFuncByName( pstrName );
       
        // 设定其余信息
       
        pFunc->iParamCount  = iParamCount;
        pFunc->iLocalDataSize   = iLocalDataSize;
    }

    /*****************************************************************************************
    *
    *   GetFuncByName()
    *
    *   根据函数名取得函数节点
    */

    FuncNode* GetFuncByName( char *pstrName )
    {
        // 如果表是空的,则返回一个空指针
       
        if( g_FuncTable.iNodeCount == 0 )
            return  0;

        // 创建一个指针用于链表的遍历
       
        LinkedListNode  *pCurrNode  = g_FuncTable.pHead;

        // 遍历链表直至找到匹配的结构
       
        for( int iCurrNode = 0 ; iCurrNode < g_FuncTable.iNodeCount ; ++ iCurrNode )
        {
            // 将当前节点数据转换为函数表指针
       
            FuncNode    *pCurrFunc  = (FuncNode*)pCurrNode->pData;

            // 检测是否匹配

            if( strcmp( pCurrFunc->pstrName, pstrName ) == 0 )
            {
                return  pCurrFunc;
            }
            else
            {
                pCurrNode   = pCurrNode->pNext;
            }
        }

        // 没有找到匹配的结构,返回0

        return  0;
    }

    /*****************************************************************************************
    *
    *   AddSymbol()
    *
    *   向符号表添加符号
    */

    int AddSymbol( char *pstrIdent, int iSize, int iStackIndex, int iFuncIndex )
    {
        // 如果标签已经存在,返回无效索引

        if( GetSymbolByIdent( pstrIdent, iFuncIndex ) )
            return  -1;

        // 创建新的符号节点

        SymbolNode  *pNewSymbol = new SymbolNode;

        // 为新节点赋值

        strcpy( pNewSymbol->pstrIdent, pstrIdent );
        pNewSymbol->iSize       = iSize;
        pNewSymbol->iStackIndex = iStackIndex;
        pNewSymbol->iFuncIndex  = iFuncIndex;

        // 想符号表中添加符号,并取得索引

        pNewSymbol->iIndex  = AddNode( &g_SymbolTable, pNewSymbol );

        // 返回新符号的索引

        return  pNewSymbol->iIndex;
    }

    /*****************************************************************************************
    *
    *   GetSymbolByIdent()
    *
    *   根据标识符取得符号节点指针
    */

    SymbolNode* GetSymbolByIdent( char *pstrIdent, int iFuncIndex )
    {
        // 声明链表节点指针用于符号表的遍历

        LinkedListNode  *pCurrNode  = g_SymbolTable.pHead;

        // 遍历符号表
        for( int iCurrNode=0 ; iCurrNode<g_SymbolTable.iNodeCount ; ++ iCurrNode )
        {
            // 将当前节点数据转换成符号表节点数据

            SymbolNode  *pCurrSymbol    = (SymbolNode*)pCurrNode->pData;

            // 检测当前符号节点是否和指定符号匹配

            if( strcmp( pCurrSymbol->pstrIdent, pstrIdent ) == 0 )
            {
                // 当前节点标识符匹配时检测作用域是否相同或重叠(全局/局部)

                if( pCurrSymbol->iFuncIndex == iFuncIndex || pCurrSymbol->iStackIndex >= 0 )
                {
                    return  pCurrSymbol;
                }
            }
            else
            {
                pCurrNode   = pCurrNode->pNext;
            }
        }

        // 没找到指定节点,返回0

        return  0;
    }

    /*****************************************************************************************
    *
    *   GetStackIndexByIdent()
    *
    *   根据标识符取得其堆栈索引
    */

    int GetStackIndexByIdent( char *pstrIdent, int iFuncIndex )
    {
        // 取得符号

        SymbolNode  *pSymbol    = GetSymbolByIdent( pstrIdent, iFuncIndex );

        // 返回堆栈索引

        return  pSymbol->iStackIndex;
    }

    /*****************************************************************************************
    *
    *   GetSizeByIdent()
    *
    *   根据标识符取得符号大小
    */

    int GetSizeByIdent( char *pstrIdent, int iFuncIndex )
    {
        // 取得符号

        SymbolNode  *pSymbol    = GetSymbolByIdent( pstrIdent, iFuncIndex );

        // 返回符号大小

        return  pSymbol->iSize;
    }

    /*****************************************************************************************
    *
    *   AddLabel()
    *
    *   向标签表添加标签
    */

    int AddLabel( char *pstrIdent, int iTargetIndex, int iFuncIndex )
    {
        // 如果标签已经存在,则返回无效索引-1

        if( GetLabelByIdent( pstrIdent, iFuncIndex ) )
            return  -1;

        // 创建新标签节点

        LabelNode   *pNewLabel  = new LabelNode;

        // 为新节点赋值

        strcpy( pNewLabel->pstrIdent, pstrIdent );
        pNewLabel->iTargetIndex = iTargetIndex;
        pNewLabel->iFuncIndex   = iFuncIndex;

        // 将新节点插入到标签表并取得索引

        pNewLabel->iIndex   = AddNode( &g_LabelTable, pNewLabel );

        // 返回索引

        return  pNewLabel->iIndex;
    }

    /*****************************************************************************************
    *
    *   GetLabelByIdent()
    *
    *   根据标标签标识符取得标签节点
    */

    LabelNode* GetLabelByIdent( char *pstrIdent, int iFuncIndex )
    {
        // 如果标签表为空,返回0

        if( g_LabelTable.iNodeCount == 0 )
            return  0;
       
        // 创建一个链表节点用于遍历

        LinkedListNode  *pCurrNode  = g_LabelTable.pHead;

        // 遍历标签表,寻找匹配的标签

        for( int i=0 ; i<g_LabelTable.iNodeCount ; ++i )
        {
            LabelNode   *pCurrLabel = (LabelNode*)pCurrNode->pData;

            // 如果名称和范围匹配,则返回当前指针
            if( strcmp( pCurrLabel->pstrIdent, pstrIdent) == 0 &&
                pCurrLabel->iFuncIndex == iFuncIndex )
            {
                return  pCurrLabel;
            }
            else
            {
                pCurrNode   = pCurrNode->pNext;
            }
        }

        // 没有找到匹配的结构,返回0

        return  0;
    }

    /*****************************************************************************************
    *
    *   AddInstrLookup()
    *
    *   向指令查找表添加指令
    */

    int AddInstrLookup( char *pstrMnemonic, int iOpCode, int iOpCount )
    {
        // 用静态变量保存查找表中下一条指令的索引

        static int  s_iInstrIndex   = 0;

        // 检测指令索引是否超出查找表的范围

        if( s_iInstrIndex >= MAX_INSTR_LOOKUP_COUNT )
            return  -1;

        // 设置指令助记符、操作码和操作数计数字段

        strcpy( g_InstrTable[s_iInstrIndex].pstrMnemonic, pstrMnemonic );
        _strupr( g_InstrTable[s_iInstrIndex].pstrMnemonic );
        g_InstrTable[s_iInstrIndex].iOpcode     = iOpCode;
        g_InstrTable[s_iInstrIndex].iOpCount    = iOpCount;

        // 为操作数类型数组分配空间

        g_InstrTable[s_iInstrIndex].OpList  = new OpTypes[iOpCount];

        // 返回当前指令在指令查找表中的索引,后移索引

        int     iRetInstrIndex  = s_iInstrIndex;
        ++ s_iInstrIndex;

        return  iRetInstrIndex;
    }
   
    /*****************************************************************************************
    *
    *   SetOpType()
    *
    *   设定操作数类型列表
    */

    void SetOpType( int iInstrIndex, int iOpIndex, OpTypes iOpType )
    {
        g_InstrTable[iInstrIndex].OpList[iOpIndex]  = iOpType;
    }

#endif _DATASTRUCTS_H_

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值