Quake source generation sequence analysis (draft)

Source: Internet
Author: User
Tags failover

Http://blog.csdn.net/breakpointer/archive/2004/09/30/121378.aspx

Quake is an id software company that launched a worldwide fan of FPS. so far, it has been developed to the third generation, and as a sound growth engine, it has also been widely used in other companies' marketing scenarios. for example, we know that CS is improved on the quake2 engine. although the current generation is not exactly the same, but the entire framework is still quake2, as long as it is a little connected to the quake engine, it is easy to see. (It is such an example. As a result, it has been used until today. I personally think it is the best example of large-scale Structural Design in graphic domains. currently, many developers have switched to object-oriented programming methods, but the effect of quake is profound. including CS2 source images exposed some time ago, its architecture still retains many quake indexes .)
Many people told me that id software has opened quake 3 all source code a long time ago. in this case, I want to tell you that, in fact, not all source generations are created with the ID, but the primary region is the primary region, you can think about which company is dumb enough to pour out its core technical skills, but they have to pay for it! The generation of artificial intelligence only includes the UI, AI, and so on. for Image Rendering, the webpage was not provided. what you see is only the clear part of the function. therefore, to thoroughly study quake3, you must obtain the source code of this part. Where can I find it? What is surprising is that some cool people have sorted out the quake3 core generation through reverse engineering, and developed a quake3 engine (dusk3d ). my analysis below is based on his generation, although it may be somewhat different from the real quake3 engine, but I believe that does not affect our understanding of quake3.
For example, for most Win32 applications, the Win32 part of quake is also imported from the winmain function. zookeeper has been divided into four major modules: cgame, game, UI, and q3_ui. (this role is made into a DLL program, and the engine adds them) the interaction between DLL and engine in quake has been completed through the vmmain and dllentry functions.
Vmmain serves as the interface for the engine program to ask about Kernel kernel DLL. The engine uses vm_call function data to use vmmain derived from kernel DLL, then, the index provided by vmmain and the root engine for the query function finds the corresponding function.
Dllentry is the interface for reading the system function numbers of zookeeper DLL receiving engine. zookeeper DLL uses it to provide the system function data to him using the engine receiver.
Sv_gamesystemcils is the system function interface provided by the engine to the game module. cl_cgamesystemcils is provided to the cgame module, while cl_uisystemcils is provided to the UI module. the real method of the preceding functions is very similar to that of vmmain, they all jump to the specified function through the index written by the root of a switch sentence.
The following is the result of the dllentry function. We can see that it only has one dynamic number and one function refers to a dynamic number, this function refers to the interface number provided by the engine to the role model, for example, sv_gamesystemcils:
Static int (cdecl * syscall) (INT Arg,...) = (INT (cdecl *) (INT,...)-1;
Void dllentry (INT (cdecl * syscallptr) (INT Arg ,...)){
Syscall = syscallptr;
}
The typical trap header function is actually replaced by an engine, as shown below:
Void trap_printf (const char * FMT ){
Syscall (g_print, FMT );
}
After learning about the usage rules, we will be able to communicate with quake sources more efficiently.
In the previous article, I wrote to quake's various parameter modules that were blocked in different DLL files. The interaction between them took advantage of the function as an interface. this is a bit like Com. The difference is that com needs to parse the DLL, because com sometimes needs to be provided to multiple applications for use, the application locates the DLL through the guid in the program catalog table, and then logs it into the program's progress space. but quake's dll is different. It doesn't have to let all application programs know its existence. It is attributed to the engine, and it is useless when the engine is enabled. the other difference between COM and quake DLL is that the main program statement of COM is C ++, which is oriented to xiangyan, all interfaces produced by it are generated in a similar way. Therefore, the statement of using it must also be oriented to the object. however, quake is just a C-producer and does not have a similar concept. Therefore, quake provides an interface in the form of fax data.
The DLL mode is widely used in zookeeper design. It is not unreasonable to choose the construction method of zookeeper.
Message Handling:
I divide quake messages into two types. One is a message that is frequently used for logging, such as keyboard, mouse, and joystick.
The other is the message that is triggered when the number of packets is stored online or locally.
In the engine, the com_eventloop () function counts the type of the root messaging event that is caught and sends it to the corresponding processing function,
Com_getevent () can retrieve all unprocessed messages from the volumes column of com_eventqueue and eventqueue,
Typedef Enum syseventtype_s {
Se_none, // evtime is still valid
Se_key, // evvalue is a key code, evvalue2 is the down flag
Se_char, // evvalue is an ASCII char
Se_mouse, // evvalue and evvalue2 are reletive signed x/y moves
Se_joystick_axis, // evvalue is an axis Number and evvalue2 is the current State (-127 to 127)
Se_console, // evptr is a char *
Se_packet // evptr is a netadr_t followed by data bytes to evptrlength
} Syseventtype_t;
 
Typedef struct {
Int evtime;
Syseventtype_t evtype;
Int evvalue, evvalue2;
Int evptrlength; // bytes of data pointed to by evptr, for journaling
Void * evptr; // This must be manually freed if not null
} Sysevent_t;
Static sysevent_t com_eventqueue [com_max_events];
Static sysevent_t eventqueue [sys_max_events];
From the preceding description, we can see that com_eventqueue and eventqueue are actually the Data Group of a sysevent_t structure.
Here you may ask, why did the data volume in com_eventqueue come from? When the com_getevent () function finds that there is no data in com_eventqueue, for example, when the program crashes, it uses com_getrealevent () to collect unprocessed messages. then, events are merged from eventqueue.

Com_getrealevent () à sys _ getevent () à sys _ pumpevents ()
Sys_pumpevents () uses the message loop body (
While (peekmessage (& MSG, null, 0u, 0u, pm_noremove )){
If (! Getmessage (& MSG, null, 0, 0 )){
Sys_quit ();
}
Translatemessage (& MSG );
Dispatchmessage (& MSG );
})
The message is first sent to wndproc () for processing, and then wndproc () is used to store the input information of external devices, such as buttons and mouse tag movement, to the global queue eventqueue by calling the sys_queevent () function. In addition, sys_pumpevents () will still use sys_getpacket () to store the website data sent from the socket into eventqueue through the sys_queevent () function.
The com_eventqueue events column uploads events in eventqueue to com_eventqueue through the com_pushevent () function. quake stores messages in this batch queue column. quake website summary:
(1) The webpage is divided into two parts: receiving and sending.
(2) The sending part is divided into two parts: local data package quota and local data package quota.
(3) The local packet ingress is identified by net_sendloopbackpacket () ingress.
(4) The local packet forwarding rule is composed of sys_sendpacket () packets.
(5) A data package can be divided into a single package and multiple packages.
(6) net_sendpacket () can be sent to a local or local data package that does not exceed the size of a single package.
(7) netchan_transmit ()
The size of the root data package is optional. If the size of a data package is larger than that of a package,
Then use the netchan_transmitnextfragment () function,
Cut the data block (max_msglen) to several equal-size (max_packetlen-100) packets, and then dispatch net_sendpacket () packets.
Otherwise, if the size of a data package is smaller than the size of a package, use net_sendpacket () to directly deliver the package.
Netchan_scramblepacket () encrypts the preceding data packets before being sent by net_sendpacket (), and then uses cl_netchan_encode () to encode them.
This is multi-package zookeeper.
From the above description, we can see that, in fact, the most optimized multi-package failover is to be changed to a single-package failover.
(8) data packet reception is also divided into local data packet reception and local data packet reception.
(9) receive local data packets: net_getloopbackpacket ()
(10) receive local data packets: sys_getpacket ()
(11) when the system receives a local data package, it will initiate a se_packet event. When the event arrives at com_eventloop (), it will trigger cl_packetevent () handle the data packages sent from the client,
Dynamic sv_packetevent () handles the number of packages sent by the server.
Cl_packetevent () cl_netchan_process () netchan_process ()
Sv_packetevent () sv_netchan_process () netchan_process ()
For the data volumes of multiple packets, it is handled by cl_netchan_process () or sv_netchan_process (). It will wait until all packets are received and then be used again.
Netchan_unscramblepacket () is decrypted, and cl_netchan_decode () is used for decoding. Finally, the complete data package can be uploaded using the suffix.
(12) when the system receives a local data package, it directly changes
Cl_packetevent () or sv_packetevent ()
You do not need to wait for packets because these packets do not enter the network.
While (net_getloopbackpacket (ns_client, & ADR, & MSG ))
While (net_getloopbackpacket (ns_server, & ADR, & MSG ))
The preceding cycle can be used to extract all the cut packets at one time.
(13)
Use net_sendpacket ()
Net_outofbandprint () net_sendpacket ()
Bytes: The data packet transmitted using net_outofbandprint (). The first four bytes must be ffffffff, that is,-1.
It will be handled by sv_connectionlesspacket () and cl_connectionlesspacket.

Some tips on the website are as follows:
When sending the sys_sendpacket () function of the webpage package, sendto is used. The function of sendto is as follows:
TheSendtoFunction is normally used on a connectionless socket to send a datax to a specific peer socket identified byToParameter. Even if the connectionless socket has been previusly connected to a specific address,ToParameter overrides the destination address for that maid only. On a connection-oriented socket,ToAndTolenParameters are ignored, makingSendtoEquivalentSend.
Therefore, it is clear that using sendto does not require reliable failover, that is, you do not need to use connect to directly send data packets.

Step 3:

1. cl_connect_f ()

If the server connected by the guest terminal is not a local machine, perform the svc_getchallenge step.

Cls. State is set to ca_connecting.

Sentence:

Cls. State = net_islocaladdress (& ClC. server_address )? Ca_challenging: ca_connecting;

2. If the customer terminal changes Cls. State = ca_connecting, then when the system crashes

Cl_checkforresend () will be triggered

Net_outofbandprint (ns_client, & ClC. server_address, "getchallenge ");

Send the "getchallenge" message to the server

3. When the server receives the "getchallenge" message, the server uses svc_getchallenge () à

Net_outofbandprint (ns_server, address, "challengeresponse % I", challenge );

Send the "challengeresponse" message to the client

4. The client receives the "challengeresponse" message:

Cls. State = ca_challenging;

5. If the customer terminal changes Cls. State = ca_challenging, then when the system crashes

Cl_checkforresend () will be triggered
Net_outofbandprint (ns_client, & ClC. server_address, "Connect/" % S/"", Info );

Send a "Connect" message to the server

6. the server accepts the "Connect" message and initiates svc_directconnect (). If the customer identity is confirmed, use net_outofbandprint (ns_server, address, "connectresponse ");

Send a "connectresponse" message to the client

Otherwise, net_outofbandprint (ns_server, address, "Disconnect ");

Send "Disconnect" messages to the client

7. The client receives the "connectresponse" message and calls netchan_setup. Then, the client uses the cl_writepacket () function to send a blank message to the server.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.