The rise and fall of Gearboy on Cydia

After several months of hard work my Game Boy Color emulator Gearboy can be considered as finished.

It has sound, full emulation of the most usual memory bank controllers, save files, disassembler, frame mixing and can be played on many platforms including Windows, Mac OS, Linux, iOS and Raspberry Pi.

The compatibility is pretty high. It can run almost all Game Boy and Game Boy Color games. Most of them run flawlessly.

If you are interested you can grab the full source code and binaries from here: https://github.com/drhelius/Gearboy

Some days ago I had the happy idea of selling the iOS port on Cydia. It was a good idea indeed.

This attracted a lot of people on Twitter and the news of a new Game Boy emulator running on iPhone 5 got viral. Quite a lot of people were asking me about the emulator, its features and when it was going to be released.

Gearboy eventually went live on Cydia and was selling pretty fast when suddenly, only a few hours later, I got an email from Saurik telling me he was having some issues with PayPal not allowing payments for the emulator. So he decieded to refund all customers and pull the emulator out of Cydia.

This was sad 🙁

Anyway, I learnt a lot by writing Gearboy and it was quite funny. In the end, my real interest is just to learn how consoles do work.

 

Gearboy: a Gameboy emulator hosted at github

It’s been a long time since I last tried to write a Gameboy emulator… 6 years methinks 🙂

That time I was struggling with my emulator written in C# and finally abandoned it.

And for the sake of completeness I just wanted to say that I’m now finishing it!

Some weeks ago I decided to give it another try, this time in C++ in order to run it on Windows, Linux, Mac and iOS…

Well, this is the result, it needs more work and lacks sound, but is compatible whith most roms.

You can see all the progress and source code in my github repository: https://github.com/drhelius/Gearboy

Ozone available on April 9th world-wide

After one year of hard coding and long periods without sleep I finished Ozone with my mates at Geardome! :mrgreen:

http://ozone.geardome.com

Some curiosities about the game:

– 1 year of development (not full time). Although we based the game in a previous game of us (Hydrium) we started completely from scratch, both art, audio and code.

– Full 3D game engine coded in C++ and fully optimized for portable devices (iPhone, iPad, PSP, Nintendo DS…), easily portable, with cool features, effects, particles, culling, but lacks some things like materials and animation (maybe for the next game).

– 60 FPS on iPad, iPhone 3GS, and iPod touch 2nd gen and above. 30 FPS on old models.

– Fully integrated with Bullet Physics Engine for physics simulation. Bullet runs quite fast indeed! We are definitely using it in future projects.

– 3D sound based in OpenAL.

– Modular design, based in episodes. Ozone currently ships with 5 episodes but it will be easy for us to add more episodes.

– Online MySQL database for storing world wide scores.

– iPad edition is on the way.

iPhone and C++ OpenGL programming

I am currently working in my last big game for the iPhone with so much to do and so few time 😛

And during this last months I received many comments about writing a detailed post about C++ programming with OpenGL and the iPhone SDK.

Well… here it is!

I created a new OpenGL ES Application Project within Xcode.

I then added a test C++ class to the project. The trick here is to change the extension of the implementation file from “.cpp” to “.mm”, this way we can freely mix C++ code with ObjectiveC code.

I also renamed the “EAGLView.m” file to “EAGLView.mm” for the same reason. Well, in my project every implementation file ends with “.mm” to avoid headaches!

This is how the test class looks like:

class TestClass : public Singleton<testClass>
{

    friend class Singleton<testClass>;

private:

    EAGLContext* m_pContext;
    GLuint m_uiViewRenderbuffer;
    GLuint m_uiViewFramebuffer;
    GLuint m_uiDepthRenderbuffer;

public:

    TestClass(void);

    void Init(EAGLContext* pContext, GLuint renderBuffer, GLuint frameBuffer, GLuint depthBuffer);
    void Cleanup(void);

    void Update(void);

private:

    void BeginRender(void);
    void EndRender(void);

    void DrawSomething(void);

};

As you can see, the class is a singleton for simplicity and convenience.

Then I changed the “createFramebuffer”, “destroyFramebuffer” and “drawView” methods of “EAGLView.mm” in order to call the wrapper methods of our test class.

- (BOOL)createFramebuffer {

    glGenFramebuffersOES(1, &viewFramebuffer);
    glGenRenderbuffersOES(1, &viewRenderbuffer);

    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
    glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);

    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
    glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);

    if (USE_DEPTH_BUFFER) {
        glGenRenderbuffersOES(1, &depthRenderbuffer);
        glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
        glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);
        glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
    }

    if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
        NSLog(@"failed to make complete framebuffer object %x",     glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
        return NO;
    }

    TestClass::Instance().Init(context, viewRenderbuffer, viewFramebuffer, depthRenderbuffer);

    return YES;
}
- (void)destroyFramebuffer {

    TestClass::Instance().Cleanup();

    glDeleteFramebuffersOES(1, &viewFramebuffer);
    viewFramebuffer = 0;
    glDeleteRenderbuffersOES(1, &viewRenderbuffer);
    viewRenderbuffer = 0;

    if(depthRenderbuffer) {
        glDeleteRenderbuffersOES(1, &depthRenderbuffer);
        depthRenderbuffer = 0;
    }
}
- (void)drawView {

    TestClass::Instance().Update();
}

You can wrap the input methods of “EAGLView.mm” in the same simple way.

And I’m afraid that’s all folks :mrgreen:

You can grab the full source code from here.

Hope this helps!