HUD coding question...

Discuss programming topics for the various GPL'd game engine sources.
Post Reply
ScatterBox
Posts: 50
Joined: Sun Oct 13, 2013 7:53 pm

HUD coding question...

Post by ScatterBox »

I'm just gonna say this right now. I'm sorry. I've looked all through this forum though and read every other topic on HUD coding in the engine and still didn't find my answer. Basically I am following Spikes advice, and doing something simple, yet visual. Well, I wanted to draw the health on the screen as a string. So I wrote my code, but when I get into the game nothing is there?! Code:

Code: Select all

/*
==================
Sbar_DrawDatHealth
==================
*/
void Sbar_DrawHealth (void)
{
    char	str[80];

if  (cl.stats[STAT_HEALTH] >= 0)
{
        sprintf (str,"Health: %i/%i", cl.stats[STAT_HEALTH]);
        Sbar_DrawString (8, 12, str);
}
You'll see that I took the quick and easy way out. I'm not sure if the health updates, or if it's static yet. I guess I'll see once it works in game. :P
Last edited by ScatterBox on Wed Oct 23, 2013 10:18 pm, edited 2 times in total.
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: HUD coding question...

Post by Spike »

it repeats itself needlessly (bad coding style)).
indentation is fucked (insulting to anyone who you ask for help).
it has a (repeated) bug (bad.. err... bugs).
you use sprintf (bad habit).
ScatterBox
Posts: 50
Joined: Sun Oct 13, 2013 7:53 pm

Re: HUD coding question...

Post by ScatterBox »

Spike wrote:it repeats itself needlessly (bad coding style)).
indentation is fucked (insulting to anyone who you ask for help).
it has a (repeated) bug (bad.. err... bugs).
you use sprintf (bad habit).
Ok, I fixed the repeat. I realize now that, that was very bad of me. :/ I also fixed the indentation the best I could. I'm not sure what you mean about the repeated bugs.. I will try and draw it without using sprintf, it just seemed to be the easiest way for me. But easy isn't always better. Thanls!
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: HUD coding question...

Post by Spike »

regarding sprintf, you'd get into a much better habit from using snprintf (or equivelent) instead.
the bug would be apparent if you tried running it.
indenting is important, though I realise that pasting it into a browser can mess it up for you.
ScatterBox
Posts: 50
Joined: Sun Oct 13, 2013 7:53 pm

Re: HUD coding question...

Post by ScatterBox »

Spike wrote:regarding sprintf, you'd get into a much better habit from using snprintf (or equivelent) instead.
the bug would be apparent if you tried running it.
indenting is important, though I realise that pasting it into a browser can mess it up for you.
Sorry if I am annoying you with all of these replys. :/ Ok, so I used snprintf and it compiled fine, but when I checked the declaration, it is not defined. I ran the game with just sprintf and it compiled and ran with no errors. No apparent bugs. Health went down as it should. So I am stuck. Not sure what to do anymore. Thanks for the help though.
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: HUD coding question...

Post by Spike »

%i/%i is two arguments. but you only provide one. the first number printed have the value, but the second will be pseudo-random (whatever value was in memory at the time).

sprintf does not bound the string, thus (C console program):
char buf1[64];
char buf2[64];
puts("Please enter your name!\n");
fgets(buf1, sizeof(buf1), stdin);
sprintf(buf2, "Hello there %s, I hope you are well\n", buf1);
puts(buf2);
will write past the end of buf2. At the end of buf2 you will presumably find the return address of your function. If the values are carefully crafted, you can insert some exploit code into those 63 bytes that are writable in buf1 and overwrite the return address to point to that data. you just have to avoid nulls. :P

Now admittedly if you'd used snprintf instead, it wouldn't have been formatted properly (no trailing part of the string, including the newline), but at least it wouldn't be exploitable (normally).

if you're unable to compile code that uses snprintf, you must be using windows. Sorry, but microsoft are morons.
On windows, you'll need to use _snprintf instead. Be warned that unlike linux's snprintf function, it does not guarentee null termination. Which means you need to reduce the number of bytes by 1, and unconditionally write the last byte of the buffer as 0. Which is a bit of a pain. It sucks to use windows. You can fairly easily write a wrapper function for it, but its annoying to have to do that. If you're lazy you can #ifdef _WIN32 #define snprintf sprintf_s #endif but your program will safely abort if its too long (which can be a major issue in server code, yay for denial of service attacks). So really, there's no choice but to validate all string lengths carefully... Programming can be a real pain some times.
In your original case, truncation is fine and dandy. Yay for snprintf.
ScatterBox
Posts: 50
Joined: Sun Oct 13, 2013 7:53 pm

Re: HUD coding question...

Post by ScatterBox »

Spike wrote:%i/%i is two arguments. but you only provide one. the first number printed have the value, but the second will be pseudo-random (whatever value was in memory at the time).

sprintf does not bound the string, thus (C console program):
char buf1[64];
char buf2[64];
puts("Please enter your name!\n");
fgets(buf1, sizeof(buf1), stdin);
sprintf(buf2, "Hello there %s, I hope you are well\n", buf1);
puts(buf2);
will write past the end of buf2. At the end of buf2 you will presumably find the return address of your function. If the values are carefully crafted, you can insert some exploit code into those 63 bytes that are writable in buf1 and overwrite the return address to point to that data. you just have to avoid nulls. :P

Now admittedly if you'd used snprintf instead, it wouldn't have been formatted properly (no trailing part of the string, including the newline), but at least it wouldn't be exploitable (normally).

if you're unable to compile code that uses snprintf, you must be using windows. Sorry, but microsoft are morons.
On windows, you'll need to use _snprintf instead. Be warned that unlike linux's snprintf function, it does not guarentee null termination. Which means you need to reduce the number of bytes by 1, and unconditionally write the last byte of the buffer as 0. Which is a bit of a pain. It sucks to use windows. You can fairly easily write a wrapper function for it, but its annoying to have to do that. If you're lazy you can #ifdef _WIN32 #define snprintf sprintf_s #endif but your program will safely abort if its too long (which can be a major issue in server code, yay for denial of service attacks). So really, there's no choice but to validate all string lengths carefully... Programming can be a real pain some times.
In your original case, truncation is fine and dandy. Yay for snprintf.
Thanks!! I got it to work finally. I basically just re-wrote the entire function. Then I moved it above "Sbar_Draw" and called the function there. Here's the code.

Code: Select all

/*
==================
Sbar_DrawDatHealth
==================
*/
void Sbar_DrawHealth (void)
{
          char	str[34];
          int	x, y;

          sprintf (str, "Health: %i", cl.stats[STAT_HEALTH]);
          x = 230;
          y = 160;
          Draw_String (x, y, str);
};
The only problem is that I can't set the size of the string, and when I scale up the resolution, the positioning changes. I know these are really noobish problems, but I can't figure them out. :/ Thanks for all your help so far guys!!

EDIT: You'll see I used sprintf still. :/ The reason is because _snprintf didn't work either. :/
frag.machine
Posts: 2126
Joined: Sat Nov 25, 2006 1:49 pm

Re: HUD coding question...

Post by frag.machine »

If you're programming for Windows with Visual Studio (likely), try sprintf_s(). It's similar to sprintf, but takes a extra parameter for the buffer size.
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
ScatterBox
Posts: 50
Joined: Sun Oct 13, 2013 7:53 pm

Re: HUD coding question...

Post by ScatterBox »

frag.machine wrote:If you're programming for Windows with Visual Studio (likely), try sprintf_s(). It's similar to sprintf, but takes a extra parameter for the buffer size.
I'm using Code::Blocks since I like the UI a lot better. But I decided to draw the HUD using images instead and it looks a lot better. Thanks for all the reply's guys! :D
Post Reply