diff -r 38b7583302c3 3x666.c
--- a/3x666.c	Tue Mar 19 02:55:25 2013 +0200
+++ b/3x666.c	Tue Mar 19 03:00:45 2013 +0200
@@ -7,6 +7,19 @@
 #include "config.h"
 #include "3xfont.h"
 
+#define RECORD 1
+#define RECORD_FPS 50
+#define RECORD_AUDIO_FILE "audio.wav"
+#define RECORD_VIDEO_FILE "%05d.png"
+
+
+#ifdef RECORD
+#include <errno.h>
+#include "dmlib.h"
+#include "dmwav.h"
+#include "libgfx.h"
+
+#else
 
 #if !defined(FALSE) && !defined(TRUE) && !defined(BOOL)
 typedef enum { FALSE = 0, TRUE = 1 } BOOL;
@@ -20,6 +33,8 @@
 #    endif
 #endif
 
+#endif
+
 
 struct
 {
@@ -51,6 +66,7 @@
 void setpal(void);
 
 
+#ifndef RECORD
 
 static void dmPrintVA(int level, const char *fmt, va_list ap)
 {
@@ -99,6 +115,7 @@
     dmErrorVA(fmt, ap);
     va_end(ap);
 }
+#endif
 
     
 static int engineGetTick()
@@ -994,10 +1011,12 @@
     engine.optAfmt.callback = engineAudioCallback;
     
     // Initialize SDL audio
+#ifndef RECORD
     if (SDL_OpenAudio(&engine.optAfmt, NULL) < 0)
     {
         dmError("Couldn't open SDL audio: %s\n", SDL_GetError());
     }
+#endif
 
     // Initialize SDL video
     if (!engineInitializeVideo())
@@ -1019,13 +1038,53 @@
 
     // Start audio, enter main loop
     dmPrint(0, "We are go.\n");
+#ifdef RECORD
+    DMImage image;
+    DMImageSpec imageSpec =
+{
+    .scale = 1,
+    .nplanes = 4,
+    .interleave = FALSE,
+    .paletted = FALSE,
+    .format = DM_IFMT_RGB,
+};
+    int audioSize = 0, audioBufSize = sizeof(Sint16) * (engine.optAfmt.freq / RECORD_FPS) * engine.optAfmt.channels;
+    Uint8 *audioBuf = malloc(audioBufSize);
+    FILE *audioFile = NULL;
+    char videoFilename[64];
+    engine.startTime = 0;
+
+    image.width = engine.screen->w;
+    image.height = engine.screen->h;
+    image.pitch = engine.screen->pitch;
+    image.ncolors = 256;
+    image.constpal = TRUE;
+    image.pal = (DMColor *) engine.screen->format->palette->colors;
+    image.data = engine.screen->pixels;
+    
+    
+    // Open output file(s)
+    if ((audioFile = fopen(RECORD_AUDIO_FILE, "wb")) == NULL)
+    {
+        dmError("Error opening output file '%s'. (%s)\n", RECORD_AUDIO_FILE, strerror(errno));
+        goto error_exit;
+    }
+
+    // Write initial header
+    dmWriteWAVHeader(audioFile, 16, engine.optAfmt.freq, engine.optAfmt.channels, 1024);
+
+#else
     SDL_LockAudio();
     SDL_PauseAudio(0);
     SDL_UnlockAudio();
     engine.startTime = SDL_GetTicks();
+#endif
 
     while (!engine.exitFlag)
     {
+#ifdef RECORD
+        engine.frameTime += 1000 / RECORD_FPS;
+#else
         // Handle SDL events
         while (SDL_PollEvent(&engine.event))
         switch (engine.event.type)
@@ -1066,8 +1125,9 @@
                 break;
         }
 
+        engine.frameTime = SDL_GetTicks();
+#endif
         // Draw frame
-        engine.frameTime = SDL_GetTicks();
         int qt = engineGetTick(&engine);
 
         if (SDL_MUSTLOCK(engine.screen) != 0 && SDL_LockSurface(engine.screen) != 0)
@@ -1184,13 +1244,25 @@
             n /= 10;
         }
 
-        // Flip screen, increase frame count, wait
+#ifdef RECORD
+        // Dump frame to file
+        snprintf(videoFilename, sizeof(videoFilename), RECORD_VIDEO_FILE, engine.frameCount);
+        dmWritePNGImage(videoFilename, &image, &imageSpec);
+        
+        // Render audio to another
+        engineAudioCallback(NULL, audioBuf, audioBufSize);
+        audioSize += fwrite(audioBuf, sizeof(Uint8), audioBufSize, audioFile);
+#endif
+
         if (SDL_MUSTLOCK(engine.screen) != 0)
             SDL_UnlockSurface(engine.screen);
 
+        // Flip screen, increase frame count, wait
         engine.frameCount++;
         SDL_Flip(engine.screen);
+#ifndef RECORD
         SDL_Delay(20);
+#endif
     }
 
 error_exit:
@@ -1206,9 +1278,26 @@
     if (engine.screen)
         SDL_FreeSurface(engine.screen);
 
+#ifdef RECORD
+    if (audioFile != NULL)
+    {
+        // Write the correct WAV header
+        if (fseek(audioFile, 0L, SEEK_SET) != 0)
+        {
+            dmError("Error rewinding to header position!\n");
+            return 9;
+        }
+        
+        dmWriteWAVHeader(audioFile, 16, engine.optAfmt.freq, engine.optAfmt.channels, audioSize / sizeof(Sint16));
+        
+        // Done!
+        fclose(audioFile);
+    }
+#else
     SDL_LockAudio();
     SDL_PauseAudio(1);
     SDL_UnlockAudio();
+#endif
 
     audio_close();
 
diff -r 38b7583302c3 Makefile.gen
--- a/Makefile.gen	Tue Mar 19 02:55:25 2013 +0200
+++ b/Makefile.gen	Tue Mar 19 03:00:45 2013 +0200
@@ -24,11 +24,10 @@
 ### Main demo
 ###
 $(OBJPATH)3x666.o: 3x666.c config.h 3xfont.h
-	$(CC) $(CFLAGS) -c -o $@ $< $(SDL_CFLAGS) -Idmlib/
+	$(CC) $(CFLAGS) -c -o $@ $< $(SDL_CFLAGS) -Idmlib/ -DDM_USE_LIBPNG
 
-$(BINPATH)3x666$(EXEEXT): $(OBJPATH)3x666.o
-	$(CC) -o $@ $+ $(LDFLAGS) $(SDL_LDFLAGS)
-
+$(BINPATH)3x666$(EXEEXT): $(OBJPATH)3x666.o dmlib/unix/dmwav.o dmlib/unix/dmfile.o dmlib/unix/dmlib.o dmlib/unix/libgfx.o dmlib/unix/dmbstr.o
+	$(CC) -o $@ $+ $(LDFLAGS) $(SDL_LDFLAGS) -lpng
 
 ###
 ### Special targets
