1

I am trying to make a c++ emulator for the original space invaders arcade machine. Everything works just fine but it is slow. After timing several functions in my project i found that the biggest drain is my draw screen functions. It takes +100ms but i need 16ms/frame, e.g. 60Hz. This is my function:

unsigned char *fb = &state->memory[0x2400];
Bitmap ^ bmp = gcnew Bitmap(512, 448);

for (int j = 1; j < 224; j++)
{
    for (int i = 0; i < 256; i+=8)
    {
        unsigned char pix = fb[(j * 256 / 8) + i / 8];
        for (int p = 0; p < 8; p++)
        {
            if (0 != (pix & (1 << p)))
            {
                bmp->SetPixel(i + p, j, Color::White);
            }
            else
            {
                bmp->SetPixel(i + p, j, Color::Black);
            }
        }
    }
}
bmp->RotateFlip(RotateFlipType::Rotate270FlipNone);
this->pictureBox1->Image = bmp;

fb is my framebuffer, a byte array with 8 pixels per byte, 1 for white, 0 for black.

Browsing the internet i found that the "slow part" is the SetPixel method, but i couldn't find a better method to do this.

  • 1
    One simple thing you can try is to `g.Clear(Color::Black);` where `g` is the `Graphics` object from the image. Then you can eliminate the `SetPixel(..., Color::Black);`, which might be enough to get the performance you need. – Loathing Aug 23 '15 at 17:56
  • Its worth a try, thx; – Maarten Van Genechten Aug 23 '15 at 18:03
  • 2
    Here's a link that will probably help: http://stackoverflow.com/questions/1563038/fast-work-with-bitmaps-in-c-sharp – Loathing Aug 23 '15 at 18:14
  • Great gonna use that in a next project. I'm trying your first solution and its working pretty good, only the clear function makes the screen flicker, working on that now – Maarten Van Genechten Aug 23 '15 at 18:24

1 Answers1

2

Thanks to Loathings comment i solved the problem. Instead of redrawing every pixel, i first clear the image to black and then only the white pixels are drawn. Had to use a buffer to prevent flickering

        unsigned char *fb = &state->memory[0x2400];
        Bitmap ^ bmp = gcnew Bitmap(512, 448);
        Image ^buffer = this->pictureBox1->Image;
        Graphics ^g = Graphics::FromImage(buffer);
        for (int j = 1; j < 224; j++)
        {
            for (int i = 0; i < 256; i += 8)
            {
                unsigned char pix = fb[(j * 256 / 8) + i / 8];
                for (int p = 0; p < 8; p++)
                {
                    if (0 != (pix & (1 << p)))
                    {
                        bmp->SetPixel(i + p, j, Color::White);
                    }

                }
            }
        }
        bmp->RotateFlip(RotateFlipType::Rotate270FlipNone);

        g->Clear(Color::Black);
        buffer = bmp;
        this->pictureBox1->Image = buffer;

and at initialisation i added next code to prevent nullexception being thrown,

        Bitmap ^def = gcnew Bitmap(20, 20);
        this->pictureBox1->Image = def;

Update: Although this method works for my project, considering the screen will be mostly composed of only black pixels. GetPixel and SetPixel are slow, and shouldn't be used with performance sensitive programs. LockBits will be the way to go. I didn't implement this because i got the performance i needed by just clearing the graphics interface