David Gow
10 posts
Handmade Penguin is a tutorial for porting Handmade Hero to Linux using the SDL library.

I thought this thread might be a good place for people to post any questions they have about it (or SDL/Linux development in general), as well as report bugs, comments, etc.

To start off, I'll announce Chapter 11: Making Graphics Portable. I had to write half of this one twice thanks to a wayward power outage, so there might be a few half-finished sentances or similar lying around. :/

— David
Stefan Koch
22 posts
I think it's a great thing you are dooing.

Thumbs up!
David Gow
10 posts
Chapter 12: Platform-independent Sound Output is now out.

If no-one objects, I'll no longer be doing both the ring buffer and SDL_QueueAudio() versions of the source code in future, unless there's a particularly interesting reason to look at it. Speak up now if this upsets you!

— David
David Vereb
1 posts
Edited by David Vereb on

I was starting a list of comments and typos. The only real-code typo I saw so far was this. There were a few missing letters in the text here and there - I'll send you a full list when I'm caught up to the main stream. :D
David Gow
10 posts
Fixed, thanks!

I'm looking forward to your comments: these were all written pretty quickly, so I'm sure there are lots of mistakes.

— David
Dan
21 posts / 2 projects
None
Edited by Dan on
Not sure if I should make new thread with this, but I am having issue with playing sound. It seems that no sound is playing out of my speakers.

This is my callback. This callback is being called by SDL, so I am not forgetting an SDL_PauseAudio(0) or anything like that.

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 static void SDLAudioCallBack(void* userData, uint8_t* stream, int len) { int16_t* currSample = (int16_t*)stream; uint32_t tone = 256; uint32_t period = 48000 / tone; uint32_t halfPeriod = period / 2; for (size_t i = 0; i < (len / sizeof(*currSample)); i+=2) { int16_t halfSample = ((i / halfPeriod) % 2) ? 1 : -1; currSample[i] = halfSample * 3000; //left channel currSample[i+1] = halfSample * 3000; //right channel } } 

This is my audio spec

  1 2 3 4 5 6 7 8 9 10  SDL_AudioSpec desiredAudio = {}; desiredAudio.channels = 2; desiredAudio.samples = 4096; desiredAudio.freq = SOUND_FREQ; desiredAudio.format = AUDIO_S16LSB; desiredAudio.callback = SDLAudioCallBack; if (SDL_OpenAudio(&desiredAudio, NULL) < 0) { printSDLErrorAndExit(); } 

Any help would be greatly appreciated! Thanks!

Also, in addition, it seems that _rdtsc() or __rdtsc() does not seem to be in x86intrin.h on Mac or Linux Mint for whatever reason (perhaps I am compiling with the wrong flags? I am compiling in C using clang, not g++. Maybe it's not in clang's std library?). As a workaround, I found that this implimentation seems to work:

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 static inline uint64_t __rdtsc(void) { uint32_t eax = 0, edx; __asm__ __volatile__("cpuid;" "rdtsc;" : "+a" (eax), "=d" (edx) : : "%rcx", "%rbx", "memory"); __asm__ __volatile__("xorl %%eax, %%eax;" "cpuid;" : : : "%rax", "%rbx", "%rcx", "%rdx", "memory"); return (((uint64_t)edx << 32) | eax); } 

Just as a suggestion: If it turns out that these functions really are missing on these platforms and this implementation is good enough, would you want to update the tutorial with this implementation?

Thanks!
David Gow
10 posts
I'm afraid I'm totally stumped: your sound code works perfectly here. The two follow-up questions I'd ask are:
1. If you're using PulseAudio, does your game show up in the volume control?
2. Does setting the environment variable SDL_AUDIODRIVER=alsa help? If you're using a non-default alsa device, you may also need AUDIODEV=<device>.

As to the intrinsics, it seems that clang only added support for _rdtsc in version 3.5, so you'll need to upgrade if you want to use the intrinsics. Otherwise, the inline assembly implementation will work fine. I've quickly noted this in the chapter, but I might discuss it further if I get time.

Best of luck,
— David
David Gow
10 posts
Chapter 13: Platform-indpendent User Input is out.

I've also upgraded the server it's hosted on, so if anything dies, do let me know.

— David
Dan
21 posts / 2 projects
None
Found the issue. Thanks David! It seems that the correct audio device wasn't selected. I was confused because I was watching the Handmade hero archive before with no problems. Maybe for some reason, in Linux Mint, the correct audio device was assigned to firefox but not the rest of my programs or something.
David Gow
10 posts
Chapter 14: A Trip Down Memory Lane is now up.

The top-secret behind-the-scenes info:
• The site now has a proper SSL certificate. Let me know if I broke the Apache config and you can no longer connect.
• I spent far too long coming up with the title for this one, so I apologise for it being a bit later than usual.

— David
David Gow
10 posts
Chapter 15: Platform-indpendent Debug File I/O is up.

I've included a little bit on using the mmap() for mapping files into memory as a bonus!

— David
David Gow
10 posts
Sorry for the delay; Chapter 16 "Bits and Pieces" of Handmade Penguin is now up.

This is the longest chapter yet, and goes into the top secret techniques, passed down from Linux developer to Linux developer, for getting your binaries to work across lots of different distributions.

Please let me know if anything doesn't work, or doesn't make sense, or eats your pets and/or beloved family members. This sort of compatibility is made of hacks built on top of other, more horrible, hacks, so the result is always going to be a bit ugly.

Thanks, and apologies for the wait,
— David
David Gow
10 posts
Fear not, Chapter 17 is here.

With some luck, the delays that plagued the last couple of chapters are over. I have lots of notes on my notepad, so it's just typing up and debugging to go.

— David
David Gow
10 posts
It's Chapter 18 time for Handmade Penguin.

We look at getting refresh rates, sleeping with SDL_Delay() and synchronising to the vertical blank.

For the interested, here's a little bit of the raw data from one of my SDL_Delay() timing experiments. You can read more about how timers on linux work here.

Enjoy,
— David

SDL_Delay(1) takes 1.095611 ms
SDL_Delay(1) takes 1.079751 ms
SDL_Delay(1) takes 1.083415 ms
SDL_Delay(1) takes 1.085282 ms
SDL_Delay(1) takes 1.088205 ms
SDL_Delay(1) takes 1.086309 ms
SDL_Delay(1) takes 1.069637 ms
SDL_Delay(1) takes 1.068966 ms
SDL_Delay(1) takes 1.068637 ms
SDL_Delay(1) takes 1.081438 ms
SDL_Delay(1) takes 1.078134 ms
SDL_Delay(1) takes 1.085287 ms
SDL_Delay(1) takes 1.085804 ms
SDL_Delay(1) takes 1.085721 ms
SDL_Delay(1) takes 1.024315 ms
SDL_Delay(1) takes 1.081754 ms
SDL_Delay(1) takes 1.082592 ms
SDL_Delay(1) takes 1.085334 ms
SDL_Delay(1) takes 1.086600 ms
SDL_Delay(1) takes 1.085623 ms
SDL_Delay(1) takes 1.085648 ms
SDL_Delay(1) takes 1.085545 ms
SDL_Delay(1) takes 1.085480 ms
SDL_Delay(1) takes 1.082745 ms
SDL_Delay(1) takes 1.085969 ms
Neo Ar
165 posts / 1 project
riscy.tv host