Handmade Hero»Forums»Code
Miles Williams
3 posts
A bit of clarification for someone new
Edited by Miles Williams on
Hi everyone.

I'm new around these parts, and also to C/C++ (having used much higher level languages in the past).

At first I went on a bit of a binge watching the first few weeks' episodes from the YouTube archive just to get a feel for what things were going to be like before diving in and coding along.

I've just recently gone back to the beginning and begun coding and have gotten through the first 4 days and although for the most part I can understand the code well enough, there are a few things that are just not sitting well for me.

For instance:

We have our Message processing loop which pull messages from a message queue and puts them into a MSG structure through the PeekMessage() function and then we pass them along to the TranslateMessage() and DispatchMessage() functions. But what I don't quite understand is exactly how the switch clause in Win32MainWindowCallback() manages to get a hold of these messages? I can see that it takes a Message as one of its parameters but we don't call the function anywhere to pass the message along.

Is it something that is beyond our control, that only Windows can handle? Is it solely handled by DispatchMessage()? And how does DispatchMessage() even know where to send them (messages) to, after all Win32MainWindowCallback() was defined by us?

Does DispatchMessage() look into our WNDCLASS structure and find that lpfnWndProc has been set to point to our Win32MainWindowCallback() function? And does the DispatchMessage() function call into it passing the message? It isn't really clear how things are moving around with all these Windows things in the way, I'm not used to programming to an API I guess and usually everything is very explicit and clear with no opaque structures and functions prohibiting my view.

Something else that is perplexing me a little is the way the RenderWeirdGradient() and Win32UpdateWindow() work.

I think I understand what is going on in the RenderWeirdGradient() function, but I guess what I want to know is the following:

*Row is pointing to the same memory as our global void *BitmapMemory, which is the memory that was given to us by VirtualAlloc() inside Win32ResizeDIBSection(), is that right? Only we have cast in into byte sized chunks? Then we do our for loops which write the values into memory in 4 byte chunks placing the iterated values into the spots for blue and green etc etc.

Now here comes my question. Are we filling up a huge region of memory with ALL the values required to write a WHOLE window full of pixels' individual RGB values and then writing them all to the screen with Win32UpdateWindow() and StretchDIBits() and then once everything is written to the screen we ReleaseDC() and increment offsets and go back through the nested loops and all that jazz all over again, over and over? And in this process do our offsets keep growing to the max size of an int before wrapping but because they are being added to the X and Y values inside RenderWeirdGradient() and assigned to uint8_t variables (Blue and Green) they wrap after reaching 255? What happens when the offsets reach the maximum int value and wrap around? Wont that cause some problem? Or will it just align and when the ints wrap the uint_t's will wrap at the same time with both becoming zero and starting all over again? If for instance we were incrementing the YOffset by a number that the maximum int value was not divisible by would we have an issue of not wrapping around to zero in sync with our Green value?

Sorry. I might not be very clear. I had more questions, but in the process of typing this up and looking through the code I have managed to answer them myself and they were quite obvious once I really drilled down into it and stepped through the code using the Watch and Memory Windows. This is so much more fun than Python or any other high level language. I am sorry if I may be answering my own questions in places here.

Anyhow. I would very much appreciate some clarification, and if my assumptions are right, some validation of my guesses, and if not then corrections and explanations to the things I have mentioned.

If you have read through all this, thank you, I know I very much tend to waffle on and always find it hard to get directly to my point/s when typing things up.

Cheers.
Miles.
Casey Muratori
801 posts / 1 project
Casey Muratori is a programmer at Molly Rocket on the game 1935 and is the host of the educational programming series Handmade Hero.
A bit of clarification for someone new
miles_williams
what I don't quite understand is exactly how the switch clause in Win32MainWindowCallback() manages to get a hold of these messages? ...
Does DispatchMessage() look into our WNDCLASS structure and find that lpfnWndProc has been set to point to our Win32MainWindowCallback() function? And does the DispatchMessage() function call into it passing the message?

This is exactly how it works, yes.

Because Windows is Windows, and doesn't like to bother with things like being consistent, technically there are two distinct ways this dispatch occurs. The first is exactly how you surmised - when we call DispatchMessage(), Windows will (eventually) use the HWND in the message structure to look up the class of the window, and then look up in the class what the message handler function is, and then finally jump to it with the contents of the MSG passed as parameters. It sounds like you already were guessing that.

The second way it can happen is that certain parts of Windows will simply call your lpfnWndProc directly without ever posting the message. This happens when a piece of Windows decides it wants to synchronously ask you to do something, and wants the result immediately, and doesn't want to put it in a queue to be processed in line with everything else. The process is still just like DispatchMessage() in that it looks up the lpfnWndProc in the WNDCLASS, but it just never goes through the MSG queue.

miles_williams
Are we filling up a huge region of memory with ALL the values required to write a WHOLE window full of pixels' individual RGB values and then writing them all to the screen with Win32UpdateWindow() and StretchDIBits() and then once everything is written to the screen we ReleaseDC() and increment offsets and go back through the nested loops and all that jazz all over again, over and over?

Yep, we sure are.

miles_williams
And in this process do our offsets keep growing to the max size of an int before wrapping but because they are being added to the X and Y values inside RenderWeirdGradient() and assigned to uint8_t variables (Blue and Green) they wrap after reaching 255? What happens when the offsets reach the maximum int value and wrap around? Wont that cause some problem? Or will it just align and when the ints wrap the uint_t's will wrap at the same time with both becoming zero and starting all over again? If for instance we were incrementing the YOffset by a number that the maximum int value was not divisible by would we have an issue of not wrapping around to zero in sync with our Green value?

Going to have to admit that at this point I have long forgotten what we were doing in RenderWeirdGradient() :) But generally speaking yes, if you were to look at the bottom 8 bits of a 32-bit value (the low-order uint8_t of a uint32_t), they're not affected by the _upper_ part of the value during addition, if that makes sense. So adding to an 8-bit value and adding to a 32-bit value is generally the same effect if all you're doing is adding!

- Casey
Miles Williams
3 posts
A bit of clarification for someone new
Thank you for your reply Casey. Much appreciated.

Also, in anticipation of when I get to where things turn to mathematics, I have started on Strangs intro text on Linear Alegbra and it is AWESOME! I may have found a new love. I've also had a peek into Thomas' Calculus but I think I should first deal with Strang and get a thorough understanding of linearity before bending and twisting my way through calculus, but I am VERY excited from the quick peek I did have inside Thomas. And I can honestly say that I don't think I'd have touched these if it weren't for you Casey. So THANK YOU!!! You have indirectly made an extremely positive impact on my life which I can only see leading to greater and greater understanding and appreciation..

Thank you.
Miles.
Casey Muratori
801 posts / 1 project
Casey Muratori is a programmer at Molly Rocket on the game 1935 and is the host of the educational programming series Handmade Hero.
A bit of clarification for someone new
Awesome! Strang was a big eye-opener for me, and it's the main thing responsible for starting me down the linear algebra path. I hope it treats you well.

Best wishes,
- Casey
Jesse
64 posts
Programmer at NASA GSFC
A bit of clarification for someone new
Check out this "intuitive" introduction to L.A.

https://www.youtube.com/watch?v=k...LZHQObOWTQDPD3MizzM2xVFitgF8hE_ab
Jeremiah Goerdt
209 posts / 2 projects
Programmer, Linux apologist, and not-so-wiseman.
A bit of clarification for someone new
I had never heard of Strang before so I thought I'd check out the text you mentioned. In my search I came across his lectures at MIT which seem to be available for free online.

http://ocw.mit.edu/courses/mathem...18-06-linear-algebra-spring-2010/
Casey Muratori
801 posts / 1 project
Casey Muratori is a programmer at Molly Rocket on the game 1935 and is the host of the educational programming series Handmade Hero.
A bit of clarification for someone new
As an obligatory caveat to this thread, I'd also point out that most people seemed to think that Strang _wasn't_ a very good introductory linear algebra text, and usually recommend that other one with the yellow cover (I can't remember the name). I have no idea! But it might be worth checking out some other intro texts to see.

- Casey
Jay Waggle
10 posts
insobot++
A bit of clarification for someone new
Edited by Jay Waggle on
That other book with the yellow cover might possibly be "Linear Algebra Done Right" by Sheldon Axler: https://www.amazon.com/dp/3319110799/

I believe I've seen it recommended by Jon Blow a few times before. (Edit: I have indeed.)