diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index e05e1b023..fad3439c8 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -84,6 +84,10 @@ const u8* GetFramebufferPointer(const u32 address) {
 template <typename T>
 inline void Read(T &var, const u32 addr) {
     switch (addr) {
+    case Registers::FramebufferTopSize:
+        var = g_regs.top_framebuffer.size;
+        break;
+
     case Registers::FramebufferTopLeft1:
         var = g_regs.framebuffer_top_left_1;
         break;
@@ -92,6 +96,18 @@ inline void Read(T &var, const u32 addr) {
         var = g_regs.framebuffer_top_left_2;
         break;
 
+    case Registers::FramebufferTopFormat:
+        var = g_regs.top_framebuffer.format;
+        break;
+
+    case Registers::FramebufferTopSwapBuffers:
+        var = g_regs.top_framebuffer.active_fb;
+        break;
+
+    case Registers::FramebufferTopStride:
+        var = g_regs.top_framebuffer.stride;
+        break;
+
     case Registers::FramebufferTopRight1:
         var = g_regs.framebuffer_top_right_1;
         break;
@@ -100,6 +116,10 @@ inline void Read(T &var, const u32 addr) {
         var = g_regs.framebuffer_top_right_2;
         break;
 
+    case Registers::FramebufferSubSize:
+        var = g_regs.sub_framebuffer.size;
+        break;
+
     case Registers::FramebufferSubLeft1:
         var = g_regs.framebuffer_sub_left_1;
         break;
@@ -108,6 +128,26 @@ inline void Read(T &var, const u32 addr) {
         var = g_regs.framebuffer_sub_right_1;
         break;
 
+    case Registers::FramebufferSubFormat:
+        var = g_regs.sub_framebuffer.format;
+        break;
+
+    case Registers::FramebufferSubSwapBuffers:
+        var = g_regs.sub_framebuffer.active_fb;
+        break;
+
+    case Registers::FramebufferSubStride:
+        var = g_regs.sub_framebuffer.stride;
+        break;
+
+    case Registers::FramebufferSubLeft2:
+        var = g_regs.framebuffer_sub_left_2;
+        break;
+
+    case Registers::FramebufferSubRight2:
+        var = g_regs.framebuffer_sub_right_2;
+        break;
+
     case Registers::DisplayInputBufferAddr:
         var = g_regs.display_transfer.input_address;
         break;
@@ -154,6 +194,17 @@ inline void Read(T &var, const u32 addr) {
 template <typename T>
 inline void Write(u32 addr, const T data) {
     switch (static_cast<Registers::Id>(addr)) {
+    // TODO: Framebuffer registers!!
+    case Registers::FramebufferTopSwapBuffers:
+        g_regs.top_framebuffer.active_fb = data;
+        // TODO: Not sure if this should only be done upon a change!
+        break;
+
+    case Registers::FramebufferSubSwapBuffers:
+        g_regs.sub_framebuffer.active_fb = data;
+        // TODO: Not sure if this should only be done upon a change!
+        break;
+
     case Registers::DisplayInputBufferAddr:
         g_regs.display_transfer.input_address = data;
         break;
@@ -195,7 +246,7 @@ inline void Write(u32 addr, const T data) {
                       g_regs.display_transfer.output_height * g_regs.display_transfer.output_width * 4,
                       g_regs.display_transfer.GetPhysicalInputAddress(), (int)g_regs.display_transfer.input_width, (int)g_regs.display_transfer.input_height,
                       g_regs.display_transfer.GetPhysicalOutputAddress(), (int)g_regs.display_transfer.output_width, (int)g_regs.display_transfer.output_height,
-                      (int)g_regs.display_transfer.output_format);
+                      (int)g_regs.display_transfer.output_format.Value());
         }
         break;
 
diff --git a/src/core/hw/gpu.h b/src/core/hw/gpu.h
index 29eb7ed81..50c360814 100644
--- a/src/core/hw/gpu.h
+++ b/src/core/hw/gpu.h
@@ -14,14 +14,23 @@ static const u32 kFrameTicks    = kFrameCycles / 3; ///< Approximate number of i
 
 struct Registers {
     enum Id : u32 {
-        FramebufferTopLeft1     = 0x1EF00468,   // Main LCD, first framebuffer for 3D left
-        FramebufferTopLeft2     = 0x1EF0046C,   // Main LCD, second framebuffer for 3D left
-        FramebufferTopRight1    = 0x1EF00494,   // Main LCD, first framebuffer for 3D right
-        FramebufferTopRight2    = 0x1EF00498,   // Main LCD, second framebuffer for 3D right
-        FramebufferSubLeft1     = 0x1EF00568,   // Sub LCD, first framebuffer
-        FramebufferSubLeft2     = 0x1EF0056C,   // Sub LCD, second framebuffer
-        FramebufferSubRight1    = 0x1EF00594,   // Sub LCD, unused first framebuffer
-        FramebufferSubRight2    = 0x1EF00598,   // Sub LCD, unused second framebuffer
+        FramebufferTopSize        = 0x1EF0045C,
+        FramebufferTopLeft1       = 0x1EF00468,   // Main LCD, first framebuffer for 3D left
+        FramebufferTopLeft2       = 0x1EF0046C,   // Main LCD, second framebuffer for 3D left
+        FramebufferTopFormat      = 0x1EF00470,
+        FramebufferTopSwapBuffers = 0x1EF00478,
+        FramebufferTopStride      = 0x1EF00490,   // framebuffer row stride?
+        FramebufferTopRight1      = 0x1EF00494,   // Main LCD, first framebuffer for 3D right
+        FramebufferTopRight2      = 0x1EF00498,   // Main LCD, second framebuffer for 3D right
+
+        FramebufferSubSize        = 0x1EF0055C,
+        FramebufferSubLeft1       = 0x1EF00568,   // Sub LCD, first framebuffer
+        FramebufferSubLeft2       = 0x1EF0056C,   // Sub LCD, second framebuffer
+        FramebufferSubFormat      = 0x1EF00570,
+        FramebufferSubSwapBuffers = 0x1EF00578,
+        FramebufferSubStride      = 0x1EF00590,   // framebuffer row stride?
+        FramebufferSubRight1      = 0x1EF00594,   // Sub LCD, unused first framebuffer
+        FramebufferSubRight2      = 0x1EF00598,   // Sub LCD, unused second framebuffer
 
         DisplayInputBufferAddr  = 0x1EF00C00,
         DisplayOutputBufferAddr = 0x1EF00C04,
@@ -36,6 +45,15 @@ struct Registers {
         ProcessCommandList      = 0x1EF018F0,
     };
 
+    enum class FramebufferFormat : u32 {
+        RGBA8  = 0,
+        RGB8   = 1,
+        RGB565 = 2,
+        RGB5A1 = 3,
+        RGBA4  = 4,
+    };
+
+    // TODO: Move these into the framebuffer struct
     u32 framebuffer_top_left_1;
     u32 framebuffer_top_left_2;
     u32 framebuffer_top_right_1;
@@ -45,6 +63,31 @@ struct Registers {
     u32 framebuffer_sub_right_1;
     u32 framebuffer_sub_right_2;
 
+    struct FrameBufferConfig {
+        union {
+            u32 size;
+
+            BitField< 0, 16, u32> width;
+            BitField<16, 16, u32> height;
+        };
+
+        union {
+            u32 format;
+
+            BitField< 0, 3, FramebufferFormat> color_format;
+        };
+
+        union {
+            u32 active_fb;
+
+            BitField<0, 1, u32> second_fb_active;
+        };
+
+        u32 stride;
+    };
+    FrameBufferConfig top_framebuffer;
+    FrameBufferConfig sub_framebuffer;
+
     struct {
         u32 input_address;
         u32 output_address;
@@ -75,8 +118,8 @@ struct Registers {
             u32 flags;
 
             BitField< 0, 1, u32> flip_data;
-            BitField< 8, 3, u32> input_format;
-            BitField<12, 3, u32> output_format;
+            BitField< 8, 3, FramebufferFormat> input_format;
+            BitField<12, 3, FramebufferFormat> output_format;
             BitField<16, 1, u32> output_tiled;
         };