diff --git a/CHANGELOG.md b/CHANGELOG.md
index a92c0b596ec916a3de2d1d80f27cfa11680b3e0f..290c3c3bccd6b56ba8f3799684049075f842ee09 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 * Support for Python 3 API - [#36](https://gitlab.stage.hive.pt/joamag/boytacean/-/issues/36)
 * `next_frame()` method for frame by frame navigation
+* Support for palette switching option in Libretro - [#37](https://gitlab.stage.hive.pt/joamag/boytacean/-/issues/37)
 
 ### Changed
 
diff --git a/frontends/libretro/src/consts.rs b/frontends/libretro/src/consts.rs
index 9b35e0e2bb2d641653465026d5dc0879f5614a15..51082f85836ab04d04548a52920830b50769f4ff 100644
--- a/frontends/libretro/src/consts.rs
+++ b/frontends/libretro/src/consts.rs
@@ -2,6 +2,9 @@ pub const RETRO_API_VERSION: u32 = 1;
 pub const REGION_NTSC: u32 = 0;
 
 pub const RETRO_ENVIRONMENT_SET_PIXEL_FORMAT: u32 = 10;
+pub const RETRO_ENVIRONMENT_GET_VARIABLE: u32 = 15;
+pub const RETRO_ENVIRONMENT_SET_VARIABLES: u32 = 16;
+pub const RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE: u32 = 17;
 
 pub const RETRO_PIXEL_FORMAT_0RGB1555: usize = 0;
 pub const RETRO_PIXEL_FORMAT_XRGB8888: usize = 1;
diff --git a/frontends/libretro/src/lib.rs b/frontends/libretro/src/lib.rs
index 3893b0d27d15c49fd12a6fab91f92160fe17d413..cb8d838fce9cf50f6eafd31e3293570cbbc4e8d8 100644
--- a/frontends/libretro/src/lib.rs
+++ b/frontends/libretro/src/lib.rs
@@ -1,6 +1,7 @@
 #![allow(clippy::uninlined_format_args)]
 
 pub mod consts;
+pub mod palettes;
 
 use boytacean::{
     debugln,
@@ -19,8 +20,11 @@ use consts::{
     RETRO_DEVICE_ID_JOYPAD_R2, RETRO_DEVICE_ID_JOYPAD_R3, RETRO_DEVICE_ID_JOYPAD_RIGHT,
     RETRO_DEVICE_ID_JOYPAD_SELECT, RETRO_DEVICE_ID_JOYPAD_START, RETRO_DEVICE_ID_JOYPAD_UP,
     RETRO_DEVICE_ID_JOYPAD_X, RETRO_DEVICE_ID_JOYPAD_Y, RETRO_DEVICE_JOYPAD,
-    RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, RETRO_PIXEL_FORMAT_XRGB8888,
+    RETRO_ENVIRONMENT_GET_VARIABLE, RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE,
+    RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, RETRO_ENVIRONMENT_SET_VARIABLES,
+    RETRO_PIXEL_FORMAT_XRGB8888,
 };
+use palettes::get_palette;
 use std::{
     collections::HashMap,
     ffi::CStr,
@@ -60,6 +64,11 @@ static mut INPUT_POLL_CALLBACK: Option<extern "C" fn()> = None;
 static mut INPUT_STATE_CALLBACK: Option<
     extern "C" fn(port: u32, device: u32, index: u32, id: u32) -> i16,
 > = None;
+static mut UPDATED: bool = false;
+static mut VARIABLE: RetroVariable = RetroVariable {
+    key: "palette\0".as_ptr() as *const c_char,
+    value: std::ptr::null(),
+};
 
 const KEYS: [RetroJoypad; 8] = [
     RetroJoypad::RetroDeviceIdJoypadUp,
@@ -71,6 +80,17 @@ const KEYS: [RetroJoypad; 8] = [
     RetroJoypad::RetroDeviceIdJoypadA,
     RetroJoypad::RetroDeviceIdJoypadB,
 ];
+const VARIABLES: [RetroVariable; 2] = [
+    RetroVariable {
+        key: "palette\0".as_ptr() as *const c_char,
+        value: "DMG color palette; basic|hogwards|christmas|goldsilver|pacman|mariobros|pokemon\0"
+            .as_ptr() as *const c_char,
+    },
+    RetroVariable {
+        key: std::ptr::null(),
+        value: std::ptr::null(),
+    },
+];
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
 pub enum RetroJoypad {
@@ -159,6 +179,12 @@ pub struct RetroSystemTiming {
     sample_rate: f64,
 }
 
+#[repr(C)]
+pub struct RetroVariable {
+    key: *const c_char,
+    value: *const c_char,
+}
+
 #[no_mangle]
 pub extern "C" fn retro_api_version() -> c_uint {
     debugln!("retro_api_version()");
@@ -233,6 +259,11 @@ pub extern "C" fn retro_set_environment(
     debugln!("retro_set_environment()");
     unsafe {
         ENVIRONMENT_CALLBACK = callback;
+        let environment_cb = ENVIRONMENT_CALLBACK.as_ref().unwrap();
+        environment_cb(
+            RETRO_ENVIRONMENT_SET_VARIABLES,
+            &VARIABLES as *const _ as *const c_void,
+        );
     }
 }
 
@@ -244,6 +275,7 @@ pub extern "C" fn retro_set_controller_port_device() {
 #[no_mangle]
 pub extern "C" fn retro_run() {
     let emulator = unsafe { EMULATOR.as_mut().unwrap() };
+    let environment_cb = unsafe { ENVIRONMENT_CALLBACK.as_ref().unwrap() };
     let video_refresh_cb = unsafe { VIDEO_REFRESH_CALLBACK.as_ref().unwrap() };
     let sample_batch_cb = unsafe { AUDIO_SAMPLE_BATCH_CALLBACK.as_ref().unwrap() };
     let input_poll_cb = unsafe { INPUT_POLL_CALLBACK.as_ref().unwrap() };
@@ -257,6 +289,20 @@ pub extern "C" fn retro_run() {
         / GameBoy::VISUAL_FREQ)
         .round() as u32;
 
+    // determines if any of the variable has changed value
+    // if that's the case all of them must be polled for
+    // update, and if needed action is triggered
+    unsafe {
+        environment_cb(
+            RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE,
+            &UPDATED as *const _ as *const c_void,
+        );
+        if UPDATED {
+            update_vars();
+            UPDATED = false;
+        }
+    }
+
     loop {
         // limits the number of ticks to the typical number
         // of cycles expected for the current logic cycle
@@ -340,6 +386,7 @@ pub unsafe extern "C" fn retro_load_game(game: *const RetroGameInfo) -> bool {
     instance.reset();
     instance.load(true);
     instance.load_cartridge(rom);
+    update_vars();
     true
 }
 
@@ -488,6 +535,25 @@ pub extern "C" fn retro_set_input_state(
     }
 }
 
+unsafe fn update_vars() {
+    update_palette();
+}
+
+unsafe fn update_palette() {
+    let emulator = EMULATOR.as_mut().unwrap();
+    let environment_cb = ENVIRONMENT_CALLBACK.as_ref().unwrap();
+    environment_cb(
+        RETRO_ENVIRONMENT_GET_VARIABLE,
+        &VARIABLE as *const _ as *const c_void,
+    );
+    if VARIABLE.value.is_null() {
+        return;
+    }
+    let palette_name = String::from(CStr::from_ptr(VARIABLE.value).to_str().unwrap());
+    let palette_info: boytacean::ppu::PaletteInfo = get_palette(palette_name);
+    emulator.ppu().set_palette_colors(palette_info.colors());
+}
+
 fn retro_key_to_pad(retro_key: RetroJoypad) -> Option<PadKey> {
     match retro_key {
         RetroJoypad::RetroDeviceIdJoypadUp => Some(PadKey::Up),
diff --git a/frontends/libretro/src/palettes.rs b/frontends/libretro/src/palettes.rs
new file mode 100644
index 0000000000000000000000000000000000000000..f0340a59d7c351bf90f64dffebe9fed8dabc08ca
--- /dev/null
+++ b/frontends/libretro/src/palettes.rs
@@ -0,0 +1,91 @@
+use boytacean::ppu::{Palette, PaletteInfo};
+
+pub struct PaletteInfoStatic {
+    name: &'static str,
+    colors: Palette,
+}
+
+impl PaletteInfoStatic {
+    pub fn into_palette_info(&self) -> PaletteInfo {
+        PaletteInfo::new(self.name, self.colors)
+    }
+}
+
+static PALETTES: [PaletteInfoStatic; 7] = [
+    PaletteInfoStatic {
+        name: "basic",
+        colors: [
+            [0xff, 0xff, 0xff],
+            [0xc0, 0xc0, 0xc0],
+            [0x60, 0x60, 0x60],
+            [0x00, 0x00, 0x00],
+        ],
+    },
+    PaletteInfoStatic {
+        name: "hogwards",
+        colors: [
+            [0xb6, 0xa5, 0x71],
+            [0x8b, 0x7e, 0x56],
+            [0x55, 0x4d, 0x35],
+            [0x20, 0x1d, 0x13],
+        ],
+    },
+    PaletteInfoStatic {
+        name: "christmas",
+        colors: [
+            [0xe8, 0xe7, 0xdf],
+            [0x8b, 0xab, 0x95],
+            [0x9e, 0x5c, 0x5e],
+            [0x53, 0x4d, 0x57],
+        ],
+    },
+    PaletteInfoStatic {
+        name: "goldsilver",
+        colors: [
+            [0xc5, 0xc6, 0x6d],
+            [0x97, 0xa1, 0xb0],
+            [0x58, 0x5e, 0x67],
+            [0x23, 0x52, 0x29],
+        ],
+    },
+    PaletteInfoStatic {
+        name: "pacman",
+        colors: [
+            [0xff, 0xff, 0x00],
+            [0xff, 0xb8, 0x97],
+            [0x37, 0x32, 0xff],
+            [0x00, 0x00, 0x00],
+        ],
+    },
+    PaletteInfoStatic {
+        name: "mariobros",
+        colors: [
+            [0xf7, 0xce, 0xc3],
+            [0xcc, 0x9e, 0x22],
+            [0x92, 0x34, 0x04],
+            [0x00, 0x00, 0x00],
+        ],
+    },
+    PaletteInfoStatic {
+        name: "pokemon",
+        colors: [
+            [0xf8, 0x78, 0x00],
+            [0xb8, 0x60, 0x00],
+            [0x78, 0x38, 0x00],
+            [0x00, 0x00, 0x00],
+        ],
+    },
+];
+
+pub fn get_palette_names() -> Vec<String> {
+    PALETTES.iter().map(|p| p.name.to_string()).collect()
+}
+
+pub fn get_palette(name: String) -> PaletteInfo {
+    for palette in PALETTES.iter() {
+        if palette.name == name {
+            return palette.into_palette_info();
+        }
+    }
+    PALETTES[0].into_palette_info()
+}
diff --git a/src/ppu.rs b/src/ppu.rs
index 542d92d365bf4a6586e140308e8cb870ad71bde8..87287b576e22bc98faae3b840c743d467886a4e0 100644
--- a/src/ppu.rs
+++ b/src/ppu.rs
@@ -127,8 +127,8 @@ pub type Palette = [Pixel; PALETTE_SIZE];
 /// with alpha within the Game Boy context.
 pub type PaletteAlpha = [PixelAlpha; PALETTE_SIZE];
 
-/// Represents a palette with the metadata that is
-/// associated with it.
+/// Represents a palette together with the metadata
+/// that is associated with it.
 #[cfg_attr(feature = "wasm", wasm_bindgen)]
 #[derive(Clone, PartialEq, Eq)]
 pub struct PaletteInfo {