ioquake笔记

ioquake代码分析一

  • 目录结构
  • 主流程框架
    • main函数流程
    • Com_Init 初始化过程
    • OpenGL初始化流程
        • InitOpenGL
    • 其他信息
    • NET_Init
      • NET_Config 流程

wiki :http://wiki.ioquake3.org

目录结构

  • misc:各个工程和配置文件
    • msvc/msvc10
    • nsis
    • osxfe/setup
    • ico图标和照片文件
  • code:代码文件
    • AL:OpenAL的头文件
    • asm:汇编代码
    • botlib
    • cgame
    • client
    • game
    • 相关lib:jpeg-8c、libcurl、zlib、libspeex音频编解码库
    • null:内容和sdl目录下基本对应
    • q3_ui
    • qcommon
    • renderer
    • sdl:对sdl的部分包装,glimp、gamma、icon、input、snd
    • SDL12: SDL的头文件
    • server
    • sys:主程序的入口出
    • tools
      • asm:q3asm tool,quake3的asm工具
      • lcc:Local C Compiler 一款开源的ANSIC编译器
    • ui
  • ui:txt文件存放得是要加载的菜单名
  • Makefile
  • cross-make-*
  • pak0.pk3
  • README
  • TODO
    主要的代码在code下的sdl、qcommon、server、client、sys、renderer、game、cgame、botlib中

主流程框架

windwos中的主入口是在WinMain函数中,Winmain函数还是调用的main函数。linux的main函数在:code/sys/sys_main.c,后面的代码分析只看linux平台的。

main函数流程

  • SDL最小版本判断
  • Sys_PlatformInit,平台初始化,根据平台两个函数实现不太一样
    Windows: code/sys/sys_win32.c
    Unix: code/sys/sys_unix.c
	const char* term = getenv( "TERM" );  //获取环境变量, getenv是系统函数signal( SIGHUP, Sys_SigHandler );  //创建信号,signal是系统函数,其他几个信号,也是关联到了Sys_SigHandler上,SIGQUIT、SIGTRAP、SIGIOT、SIGBUSstdinIsATTY = isatty( STDIN_FILENO ) &&!( term && ( !strcmp( term, "raw" ) || !strcmp( term, "dumb" ) ) ); 

isatty:检查设备类型 , 判断文件描述词是否是为终端机。stdinIsATTY 是true
STDIN_FILENO:三个流(标准输入、标准输出和标准出错)中的一个。UNIX系统shell使用文件描述符0与进程的标 准输入相关联,文件描述符1与标准输出相关联,文件描述符2与标准出错相关联。
Sys_SigHandler:信号处理,推测出程序,CL_Shutdown和SV_Shutdown和Sys_Exit

  • Sys_Milliseconds: 获取当前时间,用gettimeofday,然后做一次时间转换
  • Sys_ParseArgs: main中输入的参数解释,只解释了–version和-v
  • 获取应用程序路经存放在binaryPath,获取安装路径放在installPath,unix下是一样的。
  • 命令行参数截取存放在commandLine中
  • Com_Init
  • NET_Init :qcommon目录下,网络初始化
  • CON_Init
  • 中断信号关联:SIGILL、SIGFPE、SIGSEGV、SIGTERM、SIGINT。
    详细意义可以参考信号列表,都是中断信号:非法指令、浮点例外、段非法错误、终止、来自键盘的中断信号
  • 后面开启while 1循环 IN_Frame和Com_Frame函数

Com_Init 初始化过程

  • 清空event队列eventQueue
  • 初始化随机数种子
qboolean Sys_RandomBytes( byte *string, int len )
{FILE *fp;fp = fopen( "/dev/urandom", "r" );if( !fp )return qfalse;if( !fread( string, sizeof( byte ), len, fp ) ){fclose( fp );return qfalse;}fclose( fp );return qtrue;
}
static void Com_InitRand(void)
{unsigned int seed;if(Sys_RandomBytes((byte *) &seed, sizeof(seed)))srand(seed);elsesrand(time(NULL));
}
  • 初始化 com_pushedEvents :清空队列,头尾设置为0
    类型:
typedef enum {// SE_NONE must be zeroSE_NONE = 0,		// evTime is still validSE_KEY,			// evValue is a key code, evValue2 is the down flagSE_CHAR,		// evValue is an ascii charSE_MOUSE,		// evValue and evValue2 are reletive signed x / y movesSE_JOYSTICK_AXIS,	// evValue is an axis number and evValue2 is the current state (-127 to 127)SE_CONSOLE		// evPtr is a char*
} sysEventType_t;typedef struct {int				evTime;sysEventType_t	evType;int				evValue, evValue2;int				evPtrLength;	// bytes of data pointed to by evPtr, for journalingvoid			*evPtr;			// this must be manually freed if not NULL
} sysEvent_t;
  • 创建和初始化内存池ZoneMemory:
	s_smallZoneTotal = 512 * 1024;smallzone = calloc( s_smallZoneTotal, 1 );Z_ClearZone( smallzone, s_smallZoneTotal );// 初始化memory zone,这个zone中存放的是debug信息void Z_ClearZone( memzone_t *zone, int size ) {memblock_t	*block;zone->blocklist.next = zone->blocklist.prev = block =(memblock_t *)( (byte *)zone + sizeof(memzone_t) );zone->blocklist.tag = 1;	// in use blockzone->blocklist.id = 0;zone->blocklist.size = 0;zone->rover = block;zone->size = size;zone->used = 0;block->prev = block->next = &zone->blocklist;block->tag = 0;			// free blockblock->id = ZONEID;block->size = size - sizeof(memzone_t);

结构组成:zone中包含一堆block,block用blocklist管理,其他的rover、zise、used是blocklist的属性。
初始化将blocklist初始化成一个空的双向循环链表,里面只放一个block,作为和blocklist的彼此头尾,block也包含自己的属性

  • 初始化环境变量参数
    调用Cvar_Get函数 获取sv_cheats,所有的环境变量用hash table进行管理的搜索
    用Cmd_AddCommand将对应的命令挂载到制定的函数上,每一个命令结构体是一个循环的链表
    所有的cmd存在static变量cmd_functions中,是个单向链表,每次新来的存到头部,cmd_functions永远指向的是第一个。
  • Com_ParseCommandLine:只是将前面的commandLine存放到数组com_consoleLines中
  • 初始化 cmd_text : cmd_text.data = cmd_text_buf;
  • Com_DetectSSE:判断CPU是否支持SSE,调用的是SDL_XXX 函数,这些函数最终调用的是CPU_XXX函数,这些函数中调用的是汇编语言
	if( SDL_HasRDTSC( ) )    features |= CF_RDTSC;if( SDL_HasMMX( ) )      features |= CF_MMX;if( SDL_HasMMXExt( ) )   features |= CF_MMX_EXT;if( SDL_Has3DNow( ) )    features |= CF_3DNOW;if( SDL_Has3DNowExt( ) ) features |= CF_3DNOW_EXT;if( SDL_HasSSE( ) )      features |= CF_SSE;if( SDL_HasSSE2( ) )     features |= CF_SSE2;if( SDL_HasAltiVec( ) )  features |= CF_ALTIVEC;

支持了SSE之后实现这三个函数
Q_ftol = qftolx87;
Q_VMftol = qvmftolx87;
Q_SnapVector = qsnapvectorx87;
后面的函数都是用汇编指令实现的

  • 把命令你行的参数全部写进 cmd list 中,cmd list是一对的,前面是命令,后面是命令的参数
    初始化的后面操作也是在设置和写cmd list,这些list存放的是游戏的相关设置,
  • 根据命令行的com_zoneMegs,创建内存池 mainzone,创建方法和上面的一样
  • Com_ExecuteCfg函数中执行所有的配置cmd函数,后面Cvar_Get一系列的参数
  • 渲染开始在函数注册CL_StartHunkUsers中CL_InitRenderer,初始化UI界面CL_InitUI
    在这个函数里创建窗口

动画播放在函数CL_InitUI中执行
re.BeginRegistration = RE_BeginRegistration;

OpenGL初始化流程

RE_BeginRegistration
R_Init(); //初始化生成相关的数据,fog,noise,注册render相关参数;初始化场景的顺序;
R_Register函数中所有的参数进行初始化,包括全屏参数r_fullscreen = ri.Cvar_Get( “r_fullscreen”, “1”, CVAR_ARCHIVE );
// InitOpenGL,其中GLimp_Init来实现OpenGL相关的初始化

*glconfigOut = glConfig;R_SyncRenderThread();tr.viewCluster = -1;		// force markleafs to regenerate
R_ClearFlares();
RE_ClearScene();tr.registered = qtrue;
InitOpenGL
  • GLimp_Init:

GLimp_StartDriverAndSetMode创建窗口,这里调用GLimp_SetMode,设置相关属性,SDL_CreateRGBSurfaceFrom创建窗口,获取opengl context GLimp_GetCurrentContext
gdb调试过程中全屏窗口的显示是再函数SDL_SetVideoMode时
IN_ActivateMouse到这里等待鼠标卡住

其他信息

  • wiki[http://wiki.ioquake3.org/Main_Page]页面中包含了详细的编译和开发介绍
  • log输出中用宏定义写固定的信息:
fprintf( stdout, Q3_VERSION " dedicated server (%s)\n", date );
#define Q3_VERSION PRODUCT_NAME " " PRODUCT_VERSION
#define PRODUCT_VERSION "1.36"
#define PRODUCT_NAME			"ioq3"
  • exit进行了包装:Sys_Exit

NET_Init

网络是否启用的控制参数:net_enabled->integer

	NET_Config( qtrue );Cmd_AddCommand ("net_restart", NET_Restart_f);

NET_Config 流程

  • 判断网络参数是否修改
  • enableNetworking 和 networkingEnabled分别表示网络是否开始、网络是否已经开启。如果两个状态相同,并且网络参数没有修改,就可以保持现状退出改配置函数。
  • 否则根据enableNetworking 和 networkingEnabled的值配置stop和start的状态,状态组合情况如下:
enableNetworking/networkingEnabledT/TF/FT/FF/T
stopTFTF
startTFFT
  • if stop:调用closesocket关闭网络
  • if start && net_enabled->integer:调用NET_OpenIP和NET_SetMulticast6函数。
    • NET_OpenIP:
      NET_GetLocalAddress:获取ip地址,调用getifaddrs函数获取ip地址的链表;然后遍历,ip中有标志IFF_UP,表示网络装置正常启用;NET_AddLocalAddress区分IPv4和IPv6然后填充LocalIP数组;freeifaddrs释放链表;Sys_ShowIP调用getnameinfo将地址转换成字符串显示。
      根据net_enabled->integer & NET_ENABLEV6或NET_ENABLEV分别进行获取socket端口,进行遍历,调用socket、ioctlsocket、setsocketopt、bind函数
    • NET_SetMulticast6:
      只是做一个地址拷贝

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/31853.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

print(“{}{}“.format())

print("{}{}".format()) 是 Python 中用于格式化字符串并将其输出到控制台的一种方法。format 方法允许你在字符串中插入变量或表达式的值,并以指定的格式显示它们。 基本语法 print("format_string".format(value1, value2, ...))format_str…

JAVA学习笔记DAY7——Spring_Ioc

文章目录 Bean配置注解方式配置注解配置文件调用组件 注解方法作用域 DI注入注解引用类型自动装配文件结构自动装配实现 基本数据类型DI装配 Bean配置 注解方式配置 类上添加Ioc注解配置文件中告诉SpringIoc容器要检查哪些包 注解仅是一个标记 注解 不同注解仅是为了方便开…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 反射计数(200分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 📎在线评测链接 https://app5938.acapp.acwing.com.cn/contest/2/problem/OD…

单例模式---线程安全实现

文章目录 1.单例模式的特点😊2.单例模式两种实现🤣🤗😊2.1 饿汉式2.2 懒汉式 3.传统单例模式的线程安全问题4.解决方法4.1静态局部变量4.2加锁4.3双重检查锁(DCL)4.4pthread_once 1.单例模式的特点&#x1…

刷代码随想录有感(111):动态规划——零钱兑换II

干,被上了一课。注意题干,到底是求能装最大价值的方案还是装满这个容量共有多少种方法。他们的公式都不同,最大价值的方案是: dp[j] max(dp[j], dp[j - weight[i]] value[i]); 而装满有多少种方法是: dp[j] dp[j…

FISSURE:一款功能强大的RF和逆向工程框架

关于FISSURE FISSURE是一款功能强大的RF和逆向工程框架,该工具适用于不同技能水平的安全研究人员,并提供了信号检测、信号分类、协议发现、渗透测试、IQ操作、漏洞分析、自动化和AI/机器学习等功能。该框架旨在促进软件模块、无线电、协议、信号数据、脚…

Spring相关注解详细版

1、RestController RequestMapping("/api")这两个的作用分别是什么?如何相互区分? RestController 注解用于标识一个类是RESTful风格的Controller,它会将方法的返回值直接转换为HTTP响应体,通常用于返回JSON或XML格式的…

[力扣二叉树]本地调试环境指导手册

以236. 二叉树的最近公共祖先为例子 本地编译软件为Viusal Studio 2022 写代码 项目里文件位置 CreateTree.h #pragma once #ifndef CLIONPROJECT_LEETCODECREATETREE_H #define CLIONPROJECT_LEETCODECREATETREE_H #include<vector> #include<queue> using na…

qt 简单实验 画一个等边三角形

1.概要 2.代码 2.1 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPainter>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJECTpublic:Widget(QWidget *parent nullptr)…

Linux (centos7.9)上部署 NFS(Network File System)服务

NFS&#xff08;Network File System&#xff09;是一种网络文件系统协议&#xff0c;允许不同计算机之间通过网络共享文件和目录。NFS 最初由 Sun Microsystems 在 1984 年开发&#xff0c;现已成为许多 Unix 和类 Unix 系统&#xff08;包括 Linux&#xff09;上的标准文件系…

Chromium 调试指南2024 Mac篇 - 编译 Chromium(二)

1.引言 在完成了环境准备和源码获取之后&#xff0c;下一步就是编译Chromium源码。编译是将源码转换为可执行程序的关键步骤&#xff0c;对于验证代码更改和调试至关重要。由于Chromium项目的庞大规模和复杂性&#xff0c;编译过程可能会遇到各种问题和挑战&#xff0c;因此了…

RSA —非对称加密算法

常见的数字加密方式分为两类&#xff1a;对称加密 和 非对称加密。 对称加密&#xff0c;又称为私钥加密&#xff0c;指的是加密和解密使用同一个密钥的方式。其特点是加密和解密过程简单、快速&#xff0c;并且只需要一个密钥。常见的对称加密算法包括DES、AES等。然而&#x…

LabVIEW常用的加密硬件

LabVIEW在工程和科学领域中广泛应用&#xff0c;其中数据保护和程序安全尤为重要。为了确保数据的安全性和完整性&#xff0c;常用的加密硬件设备包括TPM&#xff08;可信平台模块&#xff09;、HSM&#xff08;硬件安全模块&#xff09;和专用加密芯片。本文将推荐几款常用的加…

【嵌入式开发】UART

目录 一、概述 1.1 常见的通信类别/特点 1.2 常见几种通信 二、UART通信协议 2.1 UART通信介绍 2.2 UART通信协议 物理连接示意图&#xff1a; 三、STM32的UART接口 3.1 STM32的UART特点 3.2 STM32的UART框图分析 3.3 UART初始化步骤 3.4 STM32中UART使用 一、概述…

物联网技术-第4章物联网通信技术-4.1无线网络

目录 1. 无线通信概念 &#xff08;1&#xff09;有线与无线 &#xff08;2&#xff09;电磁波的频谱 &#xff08;3&#xff09;频段的划分 &#xff08;4&#xff09;调制与解调 &#xff08;5&#xff09;调制技术 &#xff08;6&#xff09;信道的复用 &#xff08;…

【ARMv8/v9 GIC 系列 4.3 -- GIC 中断控制系统寄存器 ICC_SRE_ELn 使用介绍】

文章目录 GIC 中断控制系统寄存器 ICC_SRE_ELn寄存器位域介绍Interrupt BypassBypass IRQBypass FIQBypass 配置GIC 中断控制系统寄存器 ICC_SRE_ELn ICC_SRE_EL3是中断控制器系统寄存器(Interrupt Controller System Register),用于控制在异常级别3(EL3)下,对GIC CPU接口…

恒昌公益第五所“云杉校园”于湖南怀化正式揭牌

在中国近代史上湖南无疑是不可忽视的存在&#xff0c;在“敢为天下先”的湖湘文化熏陶下更是涌现了无数改变国家命运的人物。而作为推动民族复兴与社会进步的关键支柱&#xff0c;重视教育的传统起到的作用功不可没。在迈向中国式现代化的当下&#xff0c;积极推动优质教育资源…

无版权图片素材搜索网站,解决无版权图片查找问题

在数字内容创作领域&#xff0c;图片素材的选择至关重要。一张高质量、合适的图片不仅能够吸引读者的眼球&#xff0c;还能有效传达信息。然而&#xff0c;找到既免费又无版权限制的图片素材并非易事。小编将为大家介绍几个解决这一问题的无版权图片素材搜索网站&#xff0c;这…

简易版的进程池

1.使用匿名管道实现 进程池 #pragma oncetypedef void(*task_t)();void task1() {cout << "游戏 刷新日志" << endl; }void task2() {cout << "游戏 刷新野区" << endl; } void task3() {cout << "游戏 检测软件是否更…

PyMuPDF 操作手册 - 05 PDF的OCR识别等

文章目录 六、PyMuPDF的OCR识别6.1 使用 Tesseract进行OCR6.2 使用MuPDF进行OCR6.3 使用 Python 包easyocr进行OCR识别6.4 使用 Python ocrmypdf包进行OCR识别6.5 将图像批量OCR并转换为PDF七、PDF附加、嵌入、批注等7.1 附加文件7.2 嵌入文件7.3 从文档中获取所有批注六、PyMu…