Category Archives: Mars: Land of No Mercy

Back to work, Mars r622

Yesterday my exams session finally ended, I’m really satisfied about the results achieved, but during the studying period I was eager to get back to coding…

Today I fixed bug #0000008, a fastidious one which caused program termination if the user tried to take a screenshot after having deleted the hidden directory inside his home where settings and images are saved by default. 🙂

Mars 0.1.1 2nd

The first thing I thought was that I was missing a fopen() return code check, but, fortunately for my reputation, it wasn’t the case. 😉

// Opening output file
if((fp = fopen(filename, "wb")) == NULL)
{
  throw Exception("Screen", "fopen error");
  return -1;
}

The problem, as the shell output was suggesting, was related to the exception system: the fopen() exception was never caught.

Just changing this:

case SDLK_F4:
  screen->TakeScreenshot();
  break;

into this:

case SDLK_F4:
  try
  {
    screen->TakeScreenshot();
  }
  catch(Exception e)
  {
    e.PrintError();
  }
  break;

fixed everything.

Have a look at r622 log and at mars.cpp changes and remember to catch all the exception you may throw. 😉

Mars r594 and the vflip hack

For my first entry on this blog let me tell you a tale, it’s about OpenGL framebuffer and vertical flipping…

Mars 0.1.1 1st

Once upon a time a little fool called Encelo used to perform, in a little testing program, a vertical flip of the entire OpenGL framebuffer this way:

if(_flags & SDL_OPENGL)
{

  GLvoid * pixels;

  pixels = (GLvoid *) malloc(_width * _height * 4);
  glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_PIXEL_MODE_BIT);
  glReadBuffer(GL_FRONT);
  glReadPixels(0, 0, _width, _height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
  glDrawBuffer(GL_BACK);
  glRasterPos2f(-1.0f, 1.0f);
  glPixelZoom(1.0f, -1.0f);
  glDrawPixels(_width, _height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
  glReadBuffer(GL_BACK);
  glReadPixels(0, 0, _width, _height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
  glPopAttrib();
  output_surf = SDL_CreateRGBSurfaceFrom(pixels, _width, _height, 32, _surface->pitch, rmask, gmask, bmask, amask);
}

It wasn’t really bad, it performed some interesting tricks with buffers, and, as a matter of fact, Encelo was really proud of this implementation. 🙂
But… it didn’t work on Mars. Yes, no matter how much Encelo tested, changed, and tested again, it simply didn’t work on anything else than the original testing program.
A decision had to be taken soon, to persevere or not to persevere? That was the question.

Encelo chose not to persevere and to try a completely different approach… memcpy() flipping! 😀
Yeah, something as simple, elegant, fast and smart as this:

if(_flags & SDL_OPENGL)
{
  int row, stride;
  GLubyte * swapline;
  GLubyte * pixels;

  stride = _width * 4; // length of a line in bytes
  pixels = (GLubyte *) malloc(stride * _height);
  swapline = (GLubyte *) malloc(stride);

  glReadPixels(0, 0, _width, _height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

  // vertical flip
  for(row = 0; row < _height/2; row++)
  {
    memcpy(swapline, pixels + row * stride, stride);
    memcpy(pixels + row * stride, pixels + (_height - row - 1) * stride, stride);
    memcpy(pixels + (_height - row -1) * stride, swapline, stride);
  }

  output_surf = SDL_CreateRGBSurfaceFrom(pixels, _width, _height, 32, _surface->pitch, rmask, gmask, bmask, amask);
}

This story is true, and happened exactly a month ago, on the 30 of November 2006.
As a proof have a look at r594 log and at Screen.cpp changes. 😉