Fabien Sanglard's non-blog

  




Quake Engine code review (1/4)



March 9th, 2009

1  2  3  4 

Foreworlds



I happily dove into Quake World source code. Here is what I understood, hopefully it will help someone to swim.


See the Network section
See the Prediction section
See the Rendition section



Quake Client


A good starting point to study Quake is the qwcl (client) project. The entry point WinMain can be found in sys_win.c. A quick summary of the code is as follows:


			
	WinMain
	{
		while (1)
		{
				newtime = Sys_DoubleTime ();
				time = newtime - oldtime;
				Host_Frame (time)
				{
					setjmp
					Sys_SendKeyEvents
					IN_Commands
					Cbuf_Execute
					
					/* Network */
					CL_ReadPackets
					CL_SendCmd
					
					/* Prediction//Collision */
					CL_SetUpPlayerPrediction(false)
					CL_PredictMove
					CL_SetUpPlayerPrediction(true)
					CL_EmitEntities
					
					/* Rendition */
					SCR_UpdateScreen
				}
				oldtime = newtime;
		}
	}
	


From here, we can identify the three key elements of Quake World:


The network layer (also called Net Channel) outputs world information into the frames variable ( An array of frame_t). They are picked up by the prediction layer, where collisions are also taken care of and data are outputted under the form of Visibility Edicts (cl_visedicts) and the POV definition. VisEdicts are used by the rendition layer, in addition to the POV (cl.sim*) variables to render the scene.


setjmp :

Setup a code waypoint, if anything bad happens, program jumps back here.


Sys_SendKeyEvents :

Retrieve Windows OS messages, minimizing etc... Update engine variable accordingly (world is not rendered if window is minimized for example).


IN_Commands :

Get joystick inputs.


Cbuf_Execute :

In every game loop, commands in the buffer are executed. Commands are generated mostly via the console, but can also come from the server or even direct keystroke.

The game starts with a exec quake.rc in the command buffer.

CL_ReadPackets and CL_SendCmd :

Take care of the Network piece of the engine. CL_SendCmd grabs the mouse/keyboard inputs, generates a command, which is then sent. As Quake World used UDP, the reliability is mainly replicated via a set of sequence/sequenceACK in the netChannel packet headers. Additionally, the last sent command is systematically re-sent. Regarding the flow control, there is no limitation on client side, updates are sent as fast as possible. On server side, a message is sent to a client only if a packet has been received and if the sending rate is below a "choke" limit. This limit is set from client side and sent to the server.

An entire section is dedicated to this part.

CL_SetUpPlayerPrediction , CL_PredictMove and CL_EmitEntities :

Take care of the Prediction piece of the engine as well as collisions. The goal is mainly to fight network communication latency.

An entire section is dedicated to this part.

SCR_UpdateScreen :

Take care of the Rendition piece of the engine. In this part, the BSP/PVS is extensively used. This is also where a fork occurs in the code based on include/define. Quake engine can render the world either with pure software or hardware accelerated.

An entire section is dedicated to this part.

Opening the zip and compiling




Opening the zip:

Upon opening q1sources.zip, there is two folders/Visual Studio projects: QW and WinQuake.


I studied Quake World, openGL rendered ; Upon opening the solution, 4 sub-projects can be seen:



Compiling:

After installation of Windows and DirectX SDKs, compilation with Visual Studio 2008 raised one error :

			
			
		.\net_wins.c(178) : error C2072: '_errno' : initialization of a function
		
			


Nowadays, _errno is a Microsoft macro used for something else. You can fix these errors by changing the name of the variable from _errno to qerrno for example.


net_wins.c

			
	if (ret == -1)

	{

		int qerrno = WSAGetLastError();



		if (qerrno == WSAEWOULDBLOCK)

			return false;

		if (qerrno == WSAEMSGSIZE) {

			Con_Printf ("Warning:  Oversize packet from %s\n",

				NET_AdrToString (net_from));

			return false;

		}





		Sys_Error ("NET_GetPacket: %s", strerror(qerrno));

	}
		

The linker will complain about LIBC.lib in qwcl project, just add it to the list of "Ignored Library", the 4 projects should build.

Tools



For the IDE, Visual Studio Express (free), was awesome.
A few books I highly recommend to read if you want to dig further into BSP/PVS based engine, Id Software and Quake:



My bookshelf during the Quake Source Code week:


Add a comment



Name Homepage
E-mail
(Will not appear online)
Comment



Comments (9)


#1 - Roger Robusté - 11/10/2010 - 14:04
Very interesant artice, good job !
#2 - Mehadi Hasan - 01/15/2011 - 20:20
Hi there, u have done a good job. but i am having some trouble to find out the quake server source which is compilable in windows. can u send me some links where i can download this version? all i have found is quakeforge which is not compilable on windows unless u do a lot of hassles. also can u give me a suggestion how the quake server can distributed among different servers in a dynamic way so that the load balancing can be dynamic. that means u can dynamically create servers at designated hosts when the load is high and vice versa.

thanks in advance.
#3 - eric - 02/15/2011 - 08:11
Plan on reading those books, or do you not want to damage the bindings?
#4 - keiner2 - 03/09/2011 - 10:33
Hey there.. reading your article is a good starting point at least for my own studies. However I'm having trouble getting the Visual Studio 6 Projects to work in Visual Studio 2010 Express. Anyone experiencing the same problems?
#5 - Fabien Sanglard - 03/09/2011 - 11:07
keiner,

The code is suffering from "software erosion" :( ! You will need Visual Studio 2008 to open it. Your other option is to rebuild the project starting from a new one in VS2010 and import all the source files.
#6 - keiner2 - 03/09/2011 - 18:23
Hey Fabien,
nice hint there, the project-conversion worked for me from VS6 to VS2008. Good job dude thanks (also for your quick reply) !!
#7 - mazing - 04/16/2011 - 16:56
Array index cycling with the AND operator is still great for signed numbers.
#8 - Vladimir Grichina - 08/14/2011 - 10:58
Hi Fabien,

Why do you use JPEG for diagrams? It looks awful.
http://lbrandy.com/blog/2008/10/my-first-and-last-webcomic/
#9 - Madhu - 03/29/2013 - 17:27
Hello Fabien, great code review. I learned a lot from it.

Re: " You will need Visual Studio 2008 to open it."
I downloaded Visual Studio 2008 and and when I try to open "qw.dsw" with Microsoft Visual Studio 2008 Express Edition. It says "Cannot load the project due to a corrupt project file.". And I did some googling to fix this and I came across this: http://blogs.msdn.com/b/vcblog/archive/2010/03/02/visual-studio-2010-c-project-upgrade-guide.aspx

It looks like I am missing some minimum requirements. Not sure what it is, can you please help me fixing this?

 

@2009