diff --git a/README.md b/README.md
index 3d55f45a3648454fdb995aab486e1cf959fbe27c..784a120a2b52f288703db581240b0fc63d66117b 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@ A Game Boy emulator that is written in Rust 🦀.
 * Game Boy Printer emulation
 * Support for multiple MBCs: MBC1, MBC2, MBC3, and MBC5
 * Variable CPU clock speed
-* Accurate PPU - passes [dmg-acid2](https://github.com/mattcurrie/dmg-acid2) tests
+* Accurate PPU - passes [dmg-acid2](https://github.com/mattcurrie/dmg-acid2) and [cgb-acid2](https://github.com/mattcurrie/cgb-acid2) tests
 
 For the Web front-end...
 
diff --git a/frontends/sdl/res/test/cgb_acid2.png b/frontends/sdl/res/test/cgb_acid2.png
new file mode 100644
index 0000000000000000000000000000000000000000..6d23ed4468bb4e3fc45019b1ac6fb7aea4642067
Binary files /dev/null and b/frontends/sdl/res/test/cgb_acid2.png differ
diff --git a/frontends/sdl/src/test.rs b/frontends/sdl/src/test.rs
index 154a5a34c8b8a7d4588d2ee48451d1f2d0d86765..7fa014f81ad9c1f2ce1eb6f7407d0bd5848157a4 100644
--- a/frontends/sdl/src/test.rs
+++ b/frontends/sdl/src/test.rs
@@ -26,6 +26,7 @@ pub fn compare_images(source_pixels: &[u8], target_path: &str) -> bool {
 #[cfg(test)]
 mod tests {
     use boytacean::{
+        gb::GameBoyMode,
         ppu::FRAME_BUFFER_SIZE,
         test::{run_image_test, TestOptions},
     };
@@ -54,6 +55,20 @@ mod tests {
         assert_eq!(image_result, true);
     }
 
+    #[test]
+    fn test_cgb_acid2() {
+        let result: [u8; FRAME_BUFFER_SIZE] = run_image_test(
+            "../../res/roms/test/cgb_acid2.gbc",
+            Some(50000000),
+            TestOptions {
+                mode: Some(GameBoyMode::Cgb),
+                ..Default::default()
+            },
+        );
+        let image_result = compare_images(&result, "res/test/cgb_acid2.png");
+        assert_eq!(image_result, true);
+    }
+
     #[test]
     fn test_firstwhite() {
         let result: [u8; FRAME_BUFFER_SIZE] = run_image_test(
diff --git a/src/ppu.rs b/src/ppu.rs
index 9e20dffeb1bfcdf3821973eb25e004381ca8201c..24fbe4f586997718d8b8fbbb9d2d1cf41ba37ae2 100644
--- a/src/ppu.rs
+++ b/src/ppu.rs
@@ -285,6 +285,11 @@ pub struct Ppu {
     /// processed set of pixels ready to be displayed on screen.
     pub frame_buffer: Box<[u8; FRAME_BUFFER_SIZE]>,
 
+    /// The buffer that will control the background to OAM
+    /// priority, allowing the background to be drawn over
+    /// the sprites/objects if necessary.
+    priority_buffer: Box<[bool; COLOR_BUFFER_SIZE]>,
+
     /// Video dedicated memory (VRAM) where both the tiles and
     /// the sprites/objects are going to be stored.
     vram: [u8; VRAM_SIZE],
@@ -499,6 +504,7 @@ impl Ppu {
         Self {
             color_buffer: Box::new([0u8; COLOR_BUFFER_SIZE]),
             frame_buffer: Box::new([0u8; FRAME_BUFFER_SIZE]),
+            priority_buffer: Box::new([false; COLOR_BUFFER_SIZE]),
             vram: [0u8; VRAM_SIZE],
             hram: [0u8; HRAM_SIZE],
             oam: [0u8; OAM_SIZE],
@@ -555,6 +561,7 @@ impl Ppu {
     pub fn reset(&mut self) {
         self.color_buffer = Box::new([0u8; COLOR_BUFFER_SIZE]);
         self.frame_buffer = Box::new([0u8; FRAME_BUFFER_SIZE]);
+        self.priority_buffer = Box::new([false; COLOR_BUFFER_SIZE]);
         self.vram = [0u8; VRAM_SIZE_CGB];
         self.hram = [0u8; HRAM_SIZE];
         self.vram_bank = 0x0;
@@ -1196,6 +1203,10 @@ impl Ppu {
         let mut xflip = tile_attr.xflip;
         let mut yflip = tile_attr.yflip;
 
+        // obtains the value the BG-to-OAM priority to be used in the computation
+        // of the final pixel value (CGB only)
+        let mut priority = tile_attr.priority;
+
         // increments the tile index value by the required offset for the VRAM
         // bank in which the tile is stored, this is only required for CGB mode
         tile_index += tile_attr.vram_bank as usize * TILE_COUNT_DMG;
@@ -1240,6 +1251,12 @@ impl Ppu {
             self.frame_buffer[frame_offset + 1] = color[1];
             self.frame_buffer[frame_offset + 2] = color[2];
 
+            // updates the priority buffer with the current pixel
+            // the priority is only set in case the priority of
+            // the background (over OAM) is set in the attributes
+            // and the pixel is not transparent
+            self.priority_buffer[color_offset] = priority && pixel > 0;
+
             // increments the current tile X position in drawing
             x += 1;
 
@@ -1269,6 +1286,7 @@ impl Ppu {
                     palette = &self.palettes_color_bg[tile_attr.palette as usize];
                     xflip = tile_attr.xflip;
                     yflip = tile_attr.yflip;
+                    priority = tile_attr.priority;
                     tile_index += tile_attr.vram_bank as usize * TILE_COUNT_DMG;
                 }
 
@@ -1540,7 +1558,13 @@ impl Ppu {
                     // window should be drawn over or if the underlying pixel
                     // is transparent (zero value) meaning there's no background
                     // or window for the provided pixel
-                    let is_visible = obj_over || self.color_buffer[color_offset as usize] == 0;
+                    let mut is_visible = obj_over || self.color_buffer[color_offset as usize] == 0;
+
+                    // additionally (in CCG mode) the object is only considered to
+                    // be visible if the priority buffer is not set for the current
+                    // pixel, this means that the background is capturing priority
+                    // by having the BG-to-OAM priority bit set in the bg map attributes
+                    is_visible &= always_over || !self.priority_buffer[color_offset as usize];
 
                     // determines if the current pixel has priority over a possible
                     // one that has been drawn by a previous object, this happens
diff --git a/src/test.rs b/src/test.rs
index c9e0369833c85c1896cf792d17774dfc5dcfa78b..ac1cd49725defdab96b01ecaec1e4aad15eaa0b5 100644
--- a/src/test.rs
+++ b/src/test.rs
@@ -1,16 +1,21 @@
-use crate::{devices::buffer::BufferDevice, gb::GameBoy, ppu::FRAME_BUFFER_SIZE};
+use crate::{
+    devices::buffer::BufferDevice,
+    gb::{GameBoy, GameBoyMode},
+    ppu::FRAME_BUFFER_SIZE,
+};
 
 #[derive(Default)]
 pub struct TestOptions {
-    ppu_enabled: Option<bool>,
-    apu_enabled: Option<bool>,
-    dma_enabled: Option<bool>,
-    timer_enabled: Option<bool>,
+    pub mode: Option<GameBoyMode>,
+    pub ppu_enabled: Option<bool>,
+    pub apu_enabled: Option<bool>,
+    pub dma_enabled: Option<bool>,
+    pub timer_enabled: Option<bool>,
 }
 
 pub fn build_test(options: TestOptions) -> GameBoy {
     let device = Box::<BufferDevice>::default();
-    let mut game_boy = GameBoy::new(None);
+    let mut game_boy = GameBoy::new(options.mode);
     game_boy.set_ppu_enabled(options.ppu_enabled.unwrap_or(true));
     game_boy.set_apu_enabled(options.apu_enabled.unwrap_or(true));
     game_boy.set_dma_enabled(options.dma_enabled.unwrap_or(true));