Archive for the ‘Mars: Land of No Mercy’ Category

Back to work, Mars r622

Wednesday, February 28th, 2007

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

Saturday, December 30th, 2006

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! :D
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. ;)