Month Three : Week Four
This week I encountered a big issue with the Mac of development that really brought development to a standstill. The issue is that in order to kick off the event loop for an application on Mac, you must call [NSApp run]. This function will begin to take in and process message coming into the window. However, the big kicked is that on Mac this is a blocking function, whereas on Windows and Mac the window can be created and its events handled on a separate thread without blocking. This meant that my OpenWindow function on Mac never returns because it calls [NSApp run] at the end to open the window and start the loop. Initially I figured I could just launch the window on a secondary thread, but the I got hit with the realization that any Cocoa function MUST be called on the main thread of the application no matter what. This is a big problem because the entire test suite resides on a secondary thread to begin with.
The answer for this one was first to figure out what [NSApp run] really does. By looking directly at its source code I was able to discover it was simply getting the next message from the NSApp and sending to off and then updating the window. So, I created my own [NSApp run] equivalent that does the exact same this but breaks when the event queue is empty so the thread can continue running. However, this didn't fix the issue completely because getting the next event is a Cocoa function which must be ran on the main thread. Through a lot of research on this issue I finally found to separate ways to send a whole block of code to the main thread from any other thread. By using this method of code dispatching and my custom run function I was able to sufficiently mimic the functionality of the Windows and Linux side GWindow.
The purpose of Gateware is to create lightweight, multi-platform libraries that handle functionality common to video games. At the moment this includes keyboard and mouse input libraries and file logging libraries. The intent is for current and future students to be able to utilize these libraries to aid them in the creation of their final projects. The current deployments for the libraries are the Windows, Mac, and Linux platforms.
Wednesday, June 28, 2017
Mac Development
Month Three : Week Three
These next two weeks are dedicated to developing the Mac implementation for GWindow. I was two days behind at the beginning of this week because of the issues I encountered with Linux and the bug we all fixed as a group. The main issue I ran into for Mac this week was the fact that the message Loop for Mac is handled very differently from Windows and Linux and I was very unfamiliar with the Objective-C language I would need to use to complete the Mac side of GWindow.
First I looked at the Mac side of the libraries that the other Gateware members had already made. Through this and some Cocoa documentation I figured out that the WndProc functions I created for the Windows and Linux side of the message loops for GWindow are handled by a custom object called a Responder or a Delegate in Mac. Essentially a delegate is like a listener that you attach to an object you'd like to receive events from (like a window). The delegate is then filled with overridden event catching functions like windowDidResize windowDidMove. Inside these functions is where I fill out my custom GWindow events and pass them along to my GWindow's listeners.
However, just writing the delegate wasn't enough. Now I had to figure out how to connect them to my window which is being handled in a different file and even a different language. It turns out .mm and .cpp can be included directly into each other, and my GWindowDelegate was declared in the .mm with the class declaration and then assigned to my window with [window setDelegate:GWDelegate]. In the end, it took a a lot of official Cocoa documentation reading and testing things out in a separate testApp to get things to work correctly.
These next two weeks are dedicated to developing the Mac implementation for GWindow. I was two days behind at the beginning of this week because of the issues I encountered with Linux and the bug we all fixed as a group. The main issue I ran into for Mac this week was the fact that the message Loop for Mac is handled very differently from Windows and Linux and I was very unfamiliar with the Objective-C language I would need to use to complete the Mac side of GWindow.
First I looked at the Mac side of the libraries that the other Gateware members had already made. Through this and some Cocoa documentation I figured out that the WndProc functions I created for the Windows and Linux side of the message loops for GWindow are handled by a custom object called a Responder or a Delegate in Mac. Essentially a delegate is like a listener that you attach to an object you'd like to receive events from (like a window). The delegate is then filled with overridden event catching functions like windowDidResize windowDidMove. Inside these functions is where I fill out my custom GWindow events and pass them along to my GWindow's listeners.
However, just writing the delegate wasn't enough. Now I had to figure out how to connect them to my window which is being handled in a different file and even a different language. It turns out .mm and .cpp can be included directly into each other, and my GWindowDelegate was declared in the .mm with the class declaration and then assigned to my window with [window setDelegate:GWDelegate]. In the end, it took a a lot of official Cocoa documentation reading and testing things out in a separate testApp to get things to work correctly.
Linux Development : 2
Month Three : Week Two
This week the main issue I ran into was dealing with the X11 window event system. The event loop is running on its own thread so it is hard to tell when a window call is going to be processed and have the changes made be visible to the user. This meant that an X11 function may be called successfully, but the Test-Suite would keep moving on to the next test before the function was completed, making the test-suite get off track and start failing.
Like most operating systems, when an X11 event is sent it enters a queue that processes messages one by one until the queue is empty. For the purposes of my library, I need the results of the functions I call to be in effect before the program continues on. Because this was not occurring I was experiencing very frustrating bugs that were not immediately obvious. For instance, when minimizing or moving a window or messing with its borders, the window would not react for several seconds but the function would return true because the action was successful, it just wasn't visible yet.
By looking through some example code of other window handlers it became apparent that most X11 calls could be followed by XFlush() which will flush and process every message in the queue. By adding an XFlush() and sleep(1) after every X11 call that edits a window I was able to make sure that the functions were completing and actually changing the window before my program is allowed to move on, which resulted in successful tests.
This week the main issue I ran into was dealing with the X11 window event system. The event loop is running on its own thread so it is hard to tell when a window call is going to be processed and have the changes made be visible to the user. This meant that an X11 function may be called successfully, but the Test-Suite would keep moving on to the next test before the function was completed, making the test-suite get off track and start failing.
Like most operating systems, when an X11 event is sent it enters a queue that processes messages one by one until the queue is empty. For the purposes of my library, I need the results of the functions I call to be in effect before the program continues on. Because this was not occurring I was experiencing very frustrating bugs that were not immediately obvious. For instance, when minimizing or moving a window or messing with its borders, the window would not react for several seconds but the function would return true because the action was successful, it just wasn't visible yet.
By looking through some example code of other window handlers it became apparent that most X11 calls could be followed by XFlush() which will flush and process every message in the queue. By adding an XFlush() and sleep(1) after every X11 call that edits a window I was able to make sure that the functions were completing and actually changing the window before my program is allowed to move on, which resulted in successful tests.
Linux Development
Month Three : Week One
This month is all about Linux and Mac development. The first week I decided to start with Linux because I am most familiar with it and was fairly confident I could deliver on time. The major issue I encountered was just the fact that X11 is rarely used by itself by an end-user, and because of this there is not a lot of useful documentation or example projects that display correct usage of many common window functions that I need to implement. Most posts tell me to not use raw X11 and to just use a toolkit, which does not help me at all because I am essentially trying to be the toolkit.
The manner in which this issue manifested itself most often was when messing with the fullscreen functionality of the X11 window. X11 has no easy to use fullscreen toggle or even a good way to check if the window is currently fullscreen. The most frustrating and time consuming way this would inhibit me is when I would manage to get the window fullscreen, nothing short of a user pressing the maximize button could get it out of fullscreen mode. Resizing, unmapping, taking the border off, nothing worked. Which essential meant if the window ever became fullscreen it would be impossible to restore it to its normal size through code. It took lots of trial and error to eventually discover that it is much easier to create a custom ClientMessage and fill that message with the information to set the window to fullscreen or out of fullscreen instead of trying to manually resize it. There is a massive list of properties that denote every attribute of an X11 window, and it is possible to peek and edit these properties by grabbing their ID's using Atoms and then putting them into a set or delete message and sending that off to the window with XSendEvent. Eventually I discovered that fullscreen mode on an X11 window is denoted by two properties being set on the window, _NET_WM_STATE_MAXIMIZED_HORZ and _NET_WM_STATE_MAXIMIZED_VERT.
By grabbing these two properties and sending a property delete message to the window, I was able to get the window to exit fullscreen mode set itself to its proper internal size. Once I was able to get the window out of fullscreen it was trivial to do move and resize it.
This month is all about Linux and Mac development. The first week I decided to start with Linux because I am most familiar with it and was fairly confident I could deliver on time. The major issue I encountered was just the fact that X11 is rarely used by itself by an end-user, and because of this there is not a lot of useful documentation or example projects that display correct usage of many common window functions that I need to implement. Most posts tell me to not use raw X11 and to just use a toolkit, which does not help me at all because I am essentially trying to be the toolkit.
The manner in which this issue manifested itself most often was when messing with the fullscreen functionality of the X11 window. X11 has no easy to use fullscreen toggle or even a good way to check if the window is currently fullscreen. The most frustrating and time consuming way this would inhibit me is when I would manage to get the window fullscreen, nothing short of a user pressing the maximize button could get it out of fullscreen mode. Resizing, unmapping, taking the border off, nothing worked. Which essential meant if the window ever became fullscreen it would be impossible to restore it to its normal size through code. It took lots of trial and error to eventually discover that it is much easier to create a custom ClientMessage and fill that message with the information to set the window to fullscreen or out of fullscreen instead of trying to manually resize it. There is a massive list of properties that denote every attribute of an X11 window, and it is possible to peek and edit these properties by grabbing their ID's using Atoms and then putting them into a set or delete message and sending that off to the window with XSendEvent. Eventually I discovered that fullscreen mode on an X11 window is denoted by two properties being set on the window, _NET_WM_STATE_MAXIMIZED_HORZ and _NET_WM_STATE_MAXIMIZED_VERT.
By grabbing these two properties and sending a property delete message to the window, I was able to get the window to exit fullscreen mode set itself to its proper internal size. Once I was able to get the window out of fullscreen it was trivial to do move and resize it.
Month #1 of Gateware research for mobile; Android Research
The great little green android man... little did I know that to work with this guy I had to assemble it first. Thanks to google and its Android Studio, at least it came with a manual.
Android is definitely not as user friendly as its competitor, especially since it's on its own world, and in this world, the language spoken is Java. Apparently google noticed this poor patched up robot dude and reworked him enough that now they have one of the best developer resources library I have ever seen.
After I got hold of these resources it was very easy to get a grasp of deployment in their environment, giving me a warm feel that if any questions arise (or android parts fall off) I'll have their resources waiting for me.
Android is definitely not as user friendly as its competitor, especially since it's on its own world, and in this world, the language spoken is Java. Apparently google noticed this poor patched up robot dude and reworked him enough that now they have one of the best developer resources library I have ever seen.
After I got hold of these resources it was very easy to get a grasp of deployment in their environment, giving me a warm feel that if any questions arise (or android parts fall off) I'll have their resources waiting for me.
Month #1 of Gateware research for mobile; iOS Research
I joined the gateware team with the task of porting as many existing libraries as possible into iOS and Android, starting with iOS.
I've never gone too far into apple's development environment until now, and to be honest, I was very surprised to find a very organized and resourceful environment. It definitely had that apple feel of giving you as much as they can to help you, but this time, without abstracting the deeper layers of complexity that come with software, at least, not as much as they would like to.
I also had to dive pretty deep into the world of Objective-C, and was amazed. Once you get used to it, it's easy to see the reasoning behind their choices of syntax and functionality. I was also surprised at how simple it is to combine it with C++, although thinking in low-levels, it shouldn't be that complicated given that they both are, in their raw form, C.
All in all, I have found new respect for apple after going through this experience, and am sure I will appreciate them even more in the near future.
Learning the Inner Workings of Audio Part 1: RESEARCH
For the past 48 hours, my life have been succumbed to study. I have been tasked with making a multi-platform Audio Engine for games, or simply a Audio Library whose focus will be for playing, loading, and editing sounds/music for games. To do this I will be using existing first party libraries to do the heavy lifting while the library I create will be able to reference those existing libraries when needed.
But enough about that, onto what I learned.
Generally, gaming audio files run on their own threads at run-time and usually sounds needed for a level are pre-loaded into memory prior to actually playing the file and unloaded when it is no longer needed. Have you ever noticed your game freezes but the background audio is still playing fine, this is the reason why. One of the most commonly used file formats used in games is the .wav file due to its heavily documented and easy to read/write file format. This knowledge is needed since some api's such as XAudio2 doesn't actually handle loading the data itself but rather once the data is loaded, it accesses the necessary hardware to play that sound. This is not universally accepted as CoCos2d, another api designed specifically with games in mind, handles all the loading and playing of files itself.
Another common thing I found among different api's was the use of Instancing and Asynchronous Callbacks. For sounds that may stay for the length of the game such as background music, an instance of sound kind of audio device is create which manages the audio specifically for the background music. A separate instance of an audio or several instances of an object might be used just to handle specific sound effects. This way the BGM and sound effects can vary in volume and other things as the player wishes. Callbacks are used mostly with streaming the audio so that huge music files aren't loaded into memory all at once and they are asynchronous as to not block the rest of the gameplay while its waiting for some feedback to play a sound
Well that's all for today, next time I'll be delving more into XAudio2 and how one loads and plays a sound with it. Until then, you can read up more on XAudio2 on MSDN.
In the meantime, You've activated my trap card! Goodbye!
Friday, June 23, 2017
Linux, Cmake and I
So, through the efforts of Google and Stackoverflow, we have found a majority of answers to my CMake wall. The days are growing closer to the end of the Linux Project. I have already created the main project of Linux with CMake using Unix Makefiles. That was the easy part, the hard part was getting definitions to stick in the Codeblocks project for use such as -lpthread. Passing in the right one with the right call was actually tricky because it was a case of rinse and repeat on which one it belonged to such as linker or compiler flags. Then, I also had to add compiler flags to represent the libraries in c++11. I hit a wall on Thursday on how to make two separate projects targeting different architectures such as amd64 and i386. After I left work, I have an epiphany because I only think about work after I leave work. My thought on how to do this is to first create two folders in the Linux folder. After going into a folder, CMake would then check the folder it's in and build the project according to the folder. We will see how this works on Monday. Other than that, Linux will be done and I will be starting on Mac. Let's hope for the best.
Friday, June 16, 2017
Linux may just kill me.
Last week, I finished the Windows Toolchain for CMake and put it into the project. This week, however, a series of unfortunate events have kept me from finishing the Linux Toolchain. Monday, I wrapped up output directories for the Windows Toolchain. Tuesday, I had to restart a new Linux Virtual Machine because my old one got corrupted and I lost the project on it. On that same day, a team using our project came up to me and said that the input manager library of ours was not working correctly. After I brought this up to the rest of the team, the bug was reported and appointed to be fixed on wednesday which is what I did all day for Wednesday. Thursday was really my only work day as I established the Linux Project and started working on the Linux side of the toolchain. Friday, I had meetings all day long which took up a majority of my time. All in all, the work I have done for the Linux side of the toolchain just comprises of CMakeLists in each folder, Compiler directories, and output paths for the source files. At the moment, it is giving me an error on locating a file in the source folder which is there.
Friday, June 9, 2017
CMake, Windows and a whole bunch of Text files.
This week, I've been working on porting all the scripts and files from the test project into the actual project. The walls we've run into are, believe or not, just linking errors and property settings. These things are easy to change but hard to notice prior to the error. Now, the biggest wall/hurdle that had to be overcome was the inability for a single project created with CMake to target multiple platform types on visual studios such as x86 and x64 platform. The solution we used to make this work is simply the generation of two different projects at build time. One would be an amd64 project and the other will be an i386 project. As of right now, from all the research and forums I've read, there is no way that a CMake project could have both them either now or in the near future. With this knowledge, I will continue to use this method for the other two platforms which are Linux and Mac but the problem remains as if this method would work on either platform. This upcoming week, we shall take up the Mac platform so expect my blog next weekend to be an overlook on that progress. As of right now, CMake is currently producing a working project for Windows where both x86 and x64 Visual Studio projects are being created with their outputs of libraries are directed.
Friday, June 2, 2017
Integration and Testing CMake
The starting of moving CMake files and toolchains into the actual project proves to be as difficult as I knew it would. I think I might have to create two different CMake projects in the same directory. One directory would be for the creation of the libraries and the second project would be for the creation of the unit tests project. The unit test project will prove to be the most difficult to set up since it has a dependency on the first project being built so I might have CMake require the library directory to be full. On the other hand, setting up the first project is also proving to be a problem as the cache that is created is not able to find the compilers for visual studio which is really annoying. I've been digging through youtube videos and google to find my Holy Grail for a toolchain that has an output to dlls. Just like the Monty Python version of King Arthur, I found nothing but a french fortress which is an error on compile time. I think it might be just the compiler settings not be correct or the inability for the path to reach the compiler in visual studio. My goal for the following week is to fix the bug and hopefully finish the Windows build as I still have two other target platforms to code.
Subscribe to:
Posts (Atom)