diff --git a/source/main.cpp b/source/main.cpp
index 42d8caaa8ff2b1b6b3c64328d50d8f7f3134fbda..14cf50b4aa5e62b7a45e05c07ee8a3427af46337 100755
--- a/source/main.cpp
+++ b/source/main.cpp
@@ -18,27 +18,117 @@
 #include "MicroBit.h"
 
 
+/**
+ * @brief Main class responsible for the game loop and logic
+ */
 class Game {
 public:
+    /**
+     * @brief Constructor
+     * @details takes reference to the micro-bit instance for the sake of not
+     * using global variables.
+     */
     Game(MicroBit& micro_bit);
 
+    /**
+     * @brief Starts a new run of the game
+     * @note method blocks until game over.
+     */
     void run();
 
+    /* begin event handler methods */
+
+    /**
+     * Handles Button A Press event
+     */
+    void press_button_a(MicroBitEvent e);
+
+    /**
+     * Handles Button B Press event
+     */
+    void press_button_b(MicroBitEvent e);
+
+    /* end event handler methods */
+
 private:
+    /**
+     * @brief Draws whatever's in the screen buffer to display
+     */
+    void draw();
+
+    // reference to our MicroBit instance
     MicroBit& micro_bit;
+    // internal screen-buffer, which we draw to first before pasting to display
+    MicroBitImage screen_buffer;
 };
 
 Game::Game(MicroBit& micro_bit)
     : micro_bit(micro_bit)
-    {}
+    , screen_buffer(5, 5) // our screen buffer mirrors the display dimensions
+{}
 
 void Game::run() {
-    this->micro_bit.display.scroll("NEW GAME");
+    this->micro_bit.display.scroll("NEW GAME!");
+    // init screen display mode, to be sure it is in a known-state
+    // TODO: consider changing to greyscale to allow "mutli-coloured" blocks
+    this->micro_bit.display.setDisplayMode(DISPLAY_MODE_BLACK_AND_WHITE);
+    // register event-handlers
+    this->micro_bit.messageBus.listen(
+        MICROBIT_ID_BUTTON_A,
+        MICROBIT_BUTTON_EVT_CLICK,
+        this,
+        &Game::press_button_a
+    );
+    this->micro_bit.messageBus.listen(
+        MICROBIT_ID_BUTTON_B,
+        MICROBIT_BUTTON_EVT_CLICK,
+        this,
+        &Game::press_button_b
+    );
+    while (true) { // TODO: change to use game-over condition
+        this->draw(); // render screen buffer
+        // sleep to conserve CPU cycles and allow other fibers a chance to run
+        this->micro_bit.sleep(50); // a 50ms sleep gives us a 20Hz tick-rate
+    }
+    // TODO: add the rest of the game logic
+    this->micro_bit.display.scroll("GAME OVER!");
+    // TODO: display final score
+    // TODO: de-register event-handlers
+    this->micro_bit.messageBus.ignore(
+        MICROBIT_ID_BUTTON_A,
+        MICROBIT_BUTTON_EVT_CLICK,
+        this,
+        &Game::press_button_a
+    );
+    this->micro_bit.messageBus.ignore(
+        MICROBIT_ID_BUTTON_B,
+        MICROBIT_BUTTON_EVT_CLICK,
+        this,
+        &Game::press_button_b
+    );
 }
 
+void Game::draw() {
+    // XXX: debug drawing, fill the screen buffer with black
+    this->screen_buffer.clear();
+    // render our screen buffer
+    this->micro_bit.display.image.paste(this->screen_buffer);
+}
+
+void Game::press_button_a(MicroBitEvent e) {
+    // XXX: debug
+    this->screen_buffer.setPixelValue(0, 2, 255);
+}
+
+void Game::press_button_b(MicroBitEvent e) {
+    // XXX: debug
+    this->screen_buffer.setPixelValue(4, 2, 255);
+}
+
+
 MicroBit micro_bit;
 
-int main(void) {
+int main() {
     // Initialise the micro:bit runtime.
     micro_bit.init();