diff --git a/shared/hypercall_params.h b/shared/hypercall_params.h
index 17ab1e09504de866786531d8e3fa2d9d0509fc77..ea5ad45721d7b2f6e74ad9f66c6e23d8b823db32 100644
--- a/shared/hypercall_params.h
+++ b/shared/hypercall_params.h
@@ -25,6 +25,10 @@
 #define REG_GFX_INIT_CMD  0x4E700100
 #define REG_GFX_INIT_DATA 0x4E700200
 
+#define REG_SPRITE_ST   0x3E800000
+#define REG_SPRITE_CMD  0x3E800010
+#define REG_SPRITE_DATA 0x3E800020
+
 // --- SHARED STRUCT ---
 
 typedef struct {
diff --git a/vmm/gfx.h b/vmm/gfx.h
index 7e2c646fa424871122fd63ff75230c28d3c559c1..8b2337f3577c84a372a0b44c2145c056dfc87820 100644
--- a/vmm/gfx.h
+++ b/vmm/gfx.h
@@ -3,9 +3,13 @@
 
 #include <stdint.h>
 #include <stdbool.h>
+#include <pthread.h>
 #include <SDL2/SDL.h>
+#include <semaphore.h>
 #include <SDL2/SDL_image.h>
 
+// --- DEFINE ---
+
 #define GFX_RGB(r,g,b) ((pixel_t){b,g,r,0})
 
 #define GFX_COL_BLACK  GFX_RGB(0,0,0)
@@ -17,8 +21,11 @@
 #define GFX_COL_YELLOW GFX_RGB(0,255,255)
 #define GFX_COL_WHITE  GFX_RGB(255,255,255)
 
+#define MAX_SPRITES 8
+
 // Structure of a pixel: 32-bits (ARGB)
 typedef struct __attribute__ ((__packed__)) {
+
     uint8_t b;
     uint8_t g;
     uint8_t r;
@@ -26,6 +33,7 @@ typedef struct __attribute__ ((__packed__)) {
 } pixel_t;
 
 typedef struct {
+
     SDL_Window *window;
     SDL_Renderer *renderer;
     SDL_Texture *background_texture;
@@ -35,16 +43,42 @@ typedef struct {
     int height;
 } gfx_context_t;
 
+typedef struct {
+
+    SDL_Texture *tex;
+    uint32_t width;
+    uint32_t height;
+    uint32_t x;
+    uint32_t y;
+    uint8_t *data;
+    uint32_t toggle; // (1 = visible , 0 = not visible )
+} sprite_t;
+
+// - extern variable for the main thread -
+extern sem_t sem_gfx;
+extern uint32_t width_gfx;
+extern uint32_t height_gfx;
+extern gfx_context_t *ctxt;
+extern sprite_t sprites[MAX_SPRITES];
+
+// --- FUNCTION ---
+
 gfx_context_t* gfx_create(char *text, int width, int height);
+
 void gfx_destroy(gfx_context_t *ctxt);
 
 void gfx_background_putpixel(gfx_context_t *ctxt, int x, int y, pixel_t color);
+
 void gfx_background_clear(gfx_context_t *ctxt, pixel_t color);
+
 void gfx_background_update(gfx_context_t *ctxt);
 
 SDL_Texture *gfx_sprite_load(gfx_context_t *ctxt, char *filename);
+
 SDL_Texture *gfx_sprite_create(gfx_context_t *ctxt, uint8_t *pixels, int width, int height);
+
 void gfx_sprite_destroy(SDL_Texture *sprite);
+
 void gfx_sprite_render(gfx_context_t *ctxt, SDL_Texture *sprite, int x, int y, int sprite_width, int sprite_height);
 
 void gfx_present(gfx_context_t *ctxt);
diff --git a/vmm/operation.c b/vmm/operation.c
index f1eba0556ffb87acceb28af8474027387da7a6e0..e0c8211a9807be167245bcb86d7eacc5447b35f2 100644
--- a/vmm/operation.c
+++ b/vmm/operation.c
@@ -1,6 +1,7 @@
 #include "operation.h"
 
 #include <err.h>
+#include "gfx.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
@@ -31,16 +32,46 @@ state_t STATE_GFX_INIT[] = {
 
 state_t STATE_IDE[] = {
 
-    { OP_READ_INJECT,      REG_IDE_ST,       0x40,             1, op_callback_ide_prepare },
-    { OP_WRITE_EQUAL,      REG_IDE_DATA + 2, 1,                1, NULL },
-    { OP_WRITE_STORE,      REG_IDE_DATA + 3, 0,                1, op_callback_ide_store_sector_1 },
-    { OP_WRITE_STORE,      REG_IDE_DATA + 4, 0,                1, op_callback_ide_store_sector_2 },
-    { OP_WRITE_STORE,      REG_IDE_DATA + 5, 0,                1, op_callback_ide_store_sector_3 },
-    { OP_WRITE_STORE,      REG_IDE_DATA + 6, 0,                1, op_callback_ide_store_sector_4 },
-    { OP_WRITE_EQUAL,      REG_IDE_CMD,      0x30,             1, NULL },
-    { OP_READ_INJECT,      REG_IDE_ST,       0x40,             1, NULL },
-    { OP_WRITE_STORE_LOOP, REG_IDE_DATA,     0,                2, op_callback_ide_store_data },
-    { OP_EMUL_END,         0,                0,                0, op_callback_ide_conclude },
+    { OP_READ_INJECT,      REG_IDE_ST,       0x40, 1, op_callback_ide_prepare },
+    { OP_WRITE_EQUAL,      REG_IDE_DATA + 2, 1,    1, NULL },
+    { OP_WRITE_STORE,      REG_IDE_DATA + 3, 0,    1, op_callback_ide_store_sector_1 },
+    { OP_WRITE_STORE,      REG_IDE_DATA + 4, 0,    1, op_callback_ide_store_sector_2 },
+    { OP_WRITE_STORE,      REG_IDE_DATA + 5, 0,    1, op_callback_ide_store_sector_3 },
+    { OP_WRITE_STORE,      REG_IDE_DATA + 6, 0,    1, op_callback_ide_store_sector_4 },
+    { OP_WRITE_EQUAL,      REG_IDE_CMD,      0x30, 1, NULL },
+    { OP_READ_INJECT,      REG_IDE_ST,       0x40, 1, NULL },
+    { OP_WRITE_STORE_LOOP, REG_IDE_DATA,     0,    2, op_callback_ide_store_data },
+    { OP_EMUL_END,         0,                0,    0, op_callback_ide_conclude },
+};
+
+state_t STATE_SPRITE_INIT[] = {
+
+    { OP_WRITE_EQUAL,      REG_SPRITE_CMD,  0x9,  4, op_callback_sprite_init_prepare },
+    { OP_WRITE_EQUAL,      REG_SPRITE_CMD,  0x1B, 4, NULL },
+    { OP_WRITE_STORE,      REG_SPRITE_DATA, 0,    4, op_callback_sprite_init_store_id },
+    { OP_WRITE_STORE,      REG_SPRITE_DATA, 0,    4, op_callback_sprite_init_store_width },
+    { OP_WRITE_STORE,      REG_SPRITE_DATA, 0,    4, op_callback_sprite_init_store_height },
+    { OP_WRITE_STORE_LOOP, REG_SPRITE_DATA, 0,    1, op_callback_sprite_init_store_pixels },
+    { OP_EMUL_END,         0,               0,    0, op_callback_sprite_init_conclude },
+};
+
+state_t STATE_SPRITE_VIS[] = {
+
+    { OP_WRITE_EQUAL, REG_SPRITE_CMD,  0xE,  4, NULL },
+    { OP_WRITE_EQUAL, REG_SPRITE_CMD,  0x1B, 4, NULL },
+    { OP_WRITE_STORE, REG_SPRITE_DATA, 0,    4, NULL }, // id
+    { OP_WRITE_STORE, REG_SPRITE_DATA, 0,    4, NULL }, // toggle
+    { OP_EMUL_END,    0,               0,    0, NULL },
+};
+
+state_t STATE_SPRITE_POS[] = {
+
+    { OP_WRITE_EQUAL, REG_SPRITE_CMD,  0x23, 4, NULL },
+    { OP_WRITE_EQUAL, REG_SPRITE_CMD,  0x1B, 4, NULL },
+    { OP_WRITE_STORE, REG_SPRITE_DATA, 0,    4, NULL }, // id
+    { OP_WRITE_STORE, REG_SPRITE_DATA, 0,    4, NULL }, // x
+    { OP_WRITE_STORE, REG_SPRITE_DATA, 0,    4, NULL }, // y
+    { OP_EMUL_END,    0,               0,    0, NULL },
 };
 
 state_t *STATE_ALL_STARTERS[] = {
@@ -48,10 +79,21 @@ state_t *STATE_ALL_STARTERS[] = {
     &STATE_TIMER[0],
     &STATE_GFX_INIT[0],
     &STATE_IDE[0],
+    &STATE_SPRITE_INIT[0],
+    &STATE_SPRITE_VIS[0],
+    &STATE_SPRITE_POS[0],
 };
 
 bool flag_stop_loop = false;
 
+extern sem_t sem_gfx;
+extern uint32_t width_gfx;
+extern uint32_t height_gfx;
+extern gfx_context_t *ctxt;
+extern sprite_t sprites[MAX_SPRITES];
+
+extern char *disk_path;
+
 static hyper_timer_sleep_params_t param_timer;
 static hyper_init_gfx_params_t param_gfx_init;
 static hyper_ide_params_t param_ide;
@@ -108,6 +150,8 @@ void op_callback_gfx_init_conclude(void *addr) {
     width_gfx = p_gfx_init->width;
     height_gfx = p_gfx_init->height;
     sem_post(&sem_gfx);
+
+    while (ctxt == NULL); // wait to be sure that the gfx is init
 }
 
 void op_callback_ide_prepare(void *addr) {
@@ -136,7 +180,7 @@ void op_callback_ide_store_sector_3(void *addr) {
 void op_callback_ide_store_sector_4(void *addr) {
 
     param_ide.sector_idx |= ((*(uint8_t *)addr) & 0x0F) << 24;
-    // WARNING: what to do with the mode ?
+    // what to do with the mode ? -> nothing
 }
 
 void op_callback_ide_store_data(void *addr) {
@@ -181,27 +225,40 @@ void op_callback_ide_conclude(void *addr) {
     fclose(disk);
 }
 
+void op_callback_sprite_init_prepare(void *addr) { }
+
+void op_callback_sprite_init_store_id(void *addr) { }
+
+void op_callback_sprite_init_store_width(void *addr) { }
+
+void op_callback_sprite_init_store_height(void *addr) { }
+
+void op_callback_sprite_init_store_pixels(void *addr) { }
+
 void op_callback_sprite_init_conclude(void *addr) {
 
-    hyper_sprite_init_params_t *p_sprite_init = (addr == NULL) ? &param_sprite_init : (hyper_sprite_init_params_t *)addr;
+    hyper_sprite_init_params_t *p_sp_init = (addr == NULL) ? &param_sprite_init : (hyper_sprite_init_params_t *)addr;
+    printf("OPERATION : initializing sprite %d with size %dx%d...\n", p_sp_init->id, p_sp_init->width, p_sp_init->height);
 
-    printf("OPERATION : initializing sprite %d of size %dx%d...\n", p_sprite_init->id, p_sprite_init->width, p_sprite_init->height);
-    // TODO:
+    sprites[p_sp_init->id].width = p_sp_init->width;
+    sprites[p_sp_init->id].height = p_sp_init->height;
+    sprites[p_sp_init->id].data = (uint8_t *)p_sp_init->data;
 }
 
 void op_callback_sprite_visibility_conclude(void *addr) {
 
-    hyper_sprite_visibility_params_t *p_sprite_vis = (addr == NULL) ? &param_sprite_vis : (hyper_sprite_visibility_params_t *)addr;
+    hyper_sprite_visibility_params_t *p_sp_vis = (addr == NULL) ? &param_sprite_vis : (hyper_sprite_visibility_params_t *)addr;
+    printf("OPERATION : setting the visibility of the sprite %d at %d...\n", p_sp_vis->id, p_sp_vis->toggle);
 
-    printf("OPERATION : setting the visibility of the sprite %d at %d...\n", p_sprite_vis->id, p_sprite_vis->toggle);
-    // TODO:
+    sprites[p_sp_vis->id].toggle = p_sp_vis->toggle;
 }
 
 void op_callback_sprite_position_conclude(void *addr) {
 
-    hyper_sprite_position_params_t *p_sprite_pos = (addr == NULL) ? &param_sprite_pos : (hyper_sprite_position_params_t *)addr;
+    hyper_sprite_position_params_t *p_sp_pos = (addr == NULL) ? &param_sprite_pos : (hyper_sprite_position_params_t *)addr;
+    printf("OPERATION : setting the position of the sprite %d at (%d, %d)...\n", p_sp_pos->id, p_sp_pos->x, p_sp_pos->y);
 
-    printf("OPERATION : setting the poistion of the sprite %d at (%d, %d)...\n", p_sprite_pos->id, p_sprite_pos->x, p_sprite_pos->y);
-    // TODO:
+    sprites[p_sp_pos->id].x = p_sp_pos->x;
+    sprites[p_sp_pos->id].y = p_sp_pos->y;
 }
 
diff --git a/vmm/operation.h b/vmm/operation.h
index 8970df9a0b56325c6b9c939f59c08328c539faa8..8fe601008f23c2300309ae3da96a7226e84d1f30 100644
--- a/vmm/operation.h
+++ b/vmm/operation.h
@@ -4,9 +4,6 @@
 #include <stdint.h>
 #include <unistd.h>
 #include <stdbool.h>
-#include <pthread.h>
-#include <semaphore.h>
-
 
 // --- DEFINE ---
 
@@ -31,21 +28,9 @@ typedef struct {
 } state_t;
 
 extern bool flag_stop_loop;
-
-extern sem_t sem_gfx;
-extern uint32_t width_gfx;
-extern uint32_t height_gfx;
-
 extern char *disk_path;
-
 extern state_t *STATE_ALL_STARTERS[];
 
-extern state_t STATE_TIMER[];
-
-extern state_t STATE_GFX_INIT[];
-
-extern state_t STATE_VGA[];
-
 // --- FUNCITON ---
 
 /**
@@ -139,6 +124,16 @@ void op_callback_ide_store_data(void *addr);
  */
 void op_callback_ide_conclude(void *addr);
 
+void op_callback_sprite_init_prepare(void *addr);
+
+void op_callback_sprite_init_store_id(void *addr);
+
+void op_callback_sprite_init_store_width(void *addr);
+
+void op_callback_sprite_init_store_height(void *addr);
+
+void op_callback_sprite_init_store_pixels(void *addr);
+
 void op_callback_sprite_init_conclude(void *addr);
 
 void op_callback_sprite_visibility_conclude(void *addr);
diff --git a/vmm/vmm_main.c b/vmm/vmm_main.c
index 50cceafeea502d435e0b17f3d9c6d7cc9b199094..c22b3809e612af1f61e67ea9395a5682e992d791 100644
--- a/vmm/vmm_main.c
+++ b/vmm/vmm_main.c
@@ -1,3 +1,4 @@
+#include <SDL2/SDL_render.h>
 #include <err.h>
 #include <stdbool.h>
 #include <fcntl.h>
@@ -29,6 +30,8 @@
 sem_t sem_gfx;
 uint32_t width_gfx;
 uint32_t height_gfx;
+gfx_context_t *ctxt;
+sprite_t sprites[MAX_SPRITES];
 
 char *disk_path;
 
@@ -187,9 +190,29 @@ int main(int argc, char* argv[])
 
     // -- 8. Manage gfx --
 
-    gfx_context_t *ctxt = gfx_create("Basic Example", width_gfx, height_gfx);
+    memset(sprites, 0, sizeof(sprites));
+
+    ctxt = gfx_create("Basic Example", width_gfx, height_gfx);
     if (!ctxt) err(1, "KVM_SET_REGS");
 
+    while (1) {
+
+        // gfx_background_update(ctxt);
+
+        for (uint8_t i = 0; i < MAX_SPRITES; i++) {
+
+            if (sprites[i].toggle == 1) {
+
+                if (sprites[i].tex == NULL)
+                    sprites[i].tex = gfx_sprite_create(ctxt, sprites[i].data, sprites[i].width, sprites[i].height);
+
+                gfx_sprite_render(ctxt, sprites[i].tex, sprites[i].x, sprites[i].y, sprites[i].width, sprites[i].height);
+            }
+        }
+
+        gfx_present(ctxt);
+    }
+
     // -- X. Finalize --
     pthread_join(t_hypercall, NULL);