Bad practices are up to subjectivity and opinion. Please explain how my code was using "bad" practices. It works for my project, That is my standard, therefore I use it. You don't know the true scope of my programming skill, therefore you can't know all what I do. So I am already aware of the many ways of achieving the same goal, those are up to my executive decision to execute. It is also my choice what I post to the forums or not. I could write a book right now, but that is not an involatile investment right now.
Don't know any recent games written in C. As well most game API are written exclusively in C++ (havok, directx, bullet, etc) and then have wrappers for C, python, Java, etc.
How is this relevant? Most games are not written purely in those technologies. Scripting languages for example for games, and programming languages for writing tools and such. I'm writing something different than a game, therefore I choose what is necessary for such. It is subjective to the programmer. Thats like saying "a bootloader was written in "pure" assembly, but many nowadays are written in c, therefore the assembly bootloader is "worthless"." It all winds up as 1's and 0's anyway. It depends on your needs. John Carmack made the first versions of Quake in mostly C.
Pre-emptive multithreading, yes. It's not worth the hassle.
Co-op multithreading, though, is an option worth considering.
To do this without any threading is also possible. The typical approach is to have a 'catch up' mechanism. IE, you run the CPU up until it does something interesting (like write to a PPU register)... then you switch to the PPU and have it "catch up" to whatever timestamp the CPU is currently at. Then, once the CPU/PPU are in sync, you actually perform the write, and continue running the CPU.