Tutorial *84*
I've never been a big fan of QuakeWorld. While it's client-side prediction was the starting point for what has become a major factor in the succesful play of modern games such as Quake Arena and Unreal Tournament, it was the first of it's kind and I was never able to get used to it. There was, nowever, one feature of the QuakeWorld client that I did wish would've been implemented in NetQuake... The way that the console would "hold it's place" when you scrolled back was a gem. Nothing more frustrating than trying to look back in the consle history to read over something that had occurred only to have the text scroll back down to the bottom everytime something new got added to the console.

Surprising to me, it was quite easy to add this feature to the released source. Thanks to Radix and Maddes whose other works on console code pointed me in the right direction to come up with the code for this feature. Let's dig right in.

Right to the meat, in CONSOLE.C locate the function Con_Print. Find the line:



	con_backscroll = 0;

and comment it right out


	// con_backscroll = 0;	Enhanced scrollback [Fett]

Believe it or not, that's our meat and potatoes. The little bugger that forces us all the way back down to the bottom of the console history everytime a new event is added. If con_backscroll has a value it is used by the drawing routines to determine how far back in the console history to start drawing. As it was, everytime something new got printed to the console we would get forced back down to the bottom.

Now we need to clean up some details. also in CONSOLE.C locate the Con_Linefeed function. Before the first line:



	con_x = 0;

add the following:


	// Enhanced scrollback [Fett] 



	if (con_backscroll)

		con_backscroll++;



	// Enhanced scrollback [Fett] 

Everytime a line is added to the console it changes the relative location of all previous lines in the history. Without the above code the console would still scroll when lines were added. While we wouldn't get forced back down to the bottom, what we are looking for might still scroll off the screen again if there's a lot of action going on. This is easy to understand if you see it. If you really want a clear picture comment this line out later after we've finished.

Now, onto some cosmetics. We'll recreate the up arrows that QuakeWorld uses to show that you are scrolled back in the console. Still in CONSOLE.C, head down to the Con_DrawConsole function. Starting from the top:
after:



	int	j;

add:


	int	sb; // Enhanced scrollback [Fett]

then, after:


	y = lines - 16 - (rows<<3);	// may start slightly negative

add:


	// Enhanced scrollback [Fett] 



	if (con_backscroll)

		sb=2;

	else

		sb=0;



	// Enhanced scrollback [Fett] 

sb is going to be used by the upcoming drawing loop. If the console is scrolled back we need to leave some space for the scrollback indicator so we don't want to draw the last two lines of text that would normally be there by default.

Let's comment out the definition of the drawing loop:



	// for (i= con_current - rows + 1 ; i<=con_current ; i++, y+=8)	//IDCODE

and let it take advantage of the sb variable as follows:


	for (i= con_current - rows + 1 ; i<=con_current - sb ; i++, y+=8) // Enhanced scrollback [Fett]

Lastly let's put the drawing routine for the scrollback indicator. Immediately after the close of this last loop add the following:


	// Enhanced scrollback [Fett] 



	if (sb)	// are we scrolled back?

	{

		y+=8; // skip a line



		// draw arrows to show the buffer is backscrolled

		for (x=0 ; x<con_linewidth ; x+=4)

			Draw_Character ((x+1)<<3, y, '^');

	}



	// Enhanced scrollback [Fett] 

That takes care of the drawing routines. One feature that would be convenient is to enable the HOME and END keys. HOME taking us to the top of the console history and END taking us immediately down to the bottom (saves having to PAGEDOWN over and over to get back down to the 'current events'). The code to do this already exists in the KEYS.C function Key_Console however the HOME and END keys aren't enabled in the console. To activate them goto the KEYS.C function Key_Init. The list of keys that are valid within the console end with the line:


	consolekeys['~'] = false;

Add the following immediately after:


	// Enhanced scrollback [Fett] 



	consolekeys[K_HOME] = true;

	consolekeys[K_END] = true;



	// Enhanced scrollback [Fett] 

Now we have the HOME and END key functionality. One thing to note. There's a finite amount of memory allocated to the console history before events are "lost forever". Hitting the HOME key early after starting up Quake will result in what appears to be a blank console. It is, but it isn't. The HOME keys projects us to the beginning of the memory allocated to the console history. Since it's early on, there haven't been enough events to fill up this space yet. Hitting PAGEDOWN enough times will eventually yield text once we start hitting used lines. I'd ultimately like to have the HOME key bring us to the first 'readable' line in the history, but haven't endeavored to lick that yet. Based on the amount of feedback I got regarding the math on my last tutorial, I wouldn't be surprised to see a fix for this issue fairly quickly in my mailbox.

Here's a quicky bonus tutorial. While we're on the subject of memory allocation for the console, back in CONSOLE.C check out the line:



	#define	CON_TEXTSIZE	16384

This is the amount of memory dedicated to the console for history storage (in Kilobytes if I'm note mistaken). Increasing it will allow for a bigger buffer, decreasing a smaller buffer (thanks to Maddes for pointing this out). As an occasional map developer I like to dump edict lists to the console and like a BIG buffer like:


	#define	CON_TEXTSIZE	1024*128

although the average user would probably not ever need more that 64K or so.

As with most other tutorials you see around these days, this code is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. While the GPL doesn't require that you give me credit if you use my code, it would be a nice thing to do.



 
Sign up
Login:
Passwd:
[Remember Me]