Index: proj/include/proj_func.h
===================================================================
--- proj/include/proj_func.h	(revision 310)
+++ proj/include/proj_func.h	(revision 311)
@@ -3,6 +3,7 @@
 
 #include "ent.h"
 #include "font.h"
+#include "proj_structures.h"
 
 #include <stdint.h>
 
@@ -13,17 +14,6 @@
  */
 int cleanup(void);
 
-typedef struct keys {
-    uint8_t w_pressed       : 1;
-    uint8_t a_pressed       : 1;
-    uint8_t s_pressed       : 1;
-    uint8_t d_pressed       : 1;
-    uint8_t ctrl_pressed    : 1;
-    uint8_t plus_pressed    : 1;
-    uint8_t minus_pressed   : 1;
-    uint8_t lb_pressed      : 1;
-} keys_t;
-
 void update_key_presses(void);
 
 /**
Index: proj/libs/uart/include/hltp.h
===================================================================
--- proj/libs/uart/include/hltp.h	(revision 310)
+++ proj/libs/uart/include/hltp.h	(revision 311)
@@ -2,13 +2,17 @@
 #define HLTP_H_INCLUDED
 
 #include "uart.h"
+#include "proj_structures.h"
 
 typedef enum{
     hltp_type_invalid = 0x00,
-    hltp_type_string  = 0x53
+    hltp_type_string  = 0x53,
+    hltp_type_host    = 0x54,
+    hltp_type_remote  = 0x55
 } hltp_type;
 
 int hltp_send_string(const char *p);
+int hltp_send_host_info(const host_info_t *p);
+int hltp_send_remote_info(const remote_info_t *p);
 hltp_type hltp_interpret(const uint8_t *p, const size_t sz, void **dest);
-
 #endif //HLTP_H_INCLUDED
Index: proj/libs/uart/src/hltp.c
===================================================================
--- proj/libs/uart/src/hltp.c	(revision 310)
+++ proj/libs/uart/src/hltp.c	(revision 311)
@@ -17,10 +17,130 @@
     return nctp_send(2, ptr, sz);
 }
 
+static host_info_t* hltp_interpret_host_info(const uint8_t *p) {
+    host_info_t *ret = (host_info_t*)malloc(sizeof(host_info_t));
+    size_t pos = 0;
+    // players information
+    memcpy(ret, p + pos, sizeof(double)*8);
+    pos += sizeof(double)*8;
+    // size of arrays
+    memcpy(&(ret->no_bullets), p + pos, sizeof(size_t));
+    pos += sizeof(size_t);
+    size_t sz = ret->no_bullets;
+    // array containing the X positions of the bullets
+    (ret->bullets_x) = (double*)malloc(sizeof(double)*sz);
+    memcpy((ret->bullets_x), p + pos, sizeof(double)*sz);
+    pos += sizeof(double)*sz;
+    // array containing the Y positions of the bullets
+    (ret->bullets_y) = (double*)malloc(sizeof(double)*(ret->no_bullets));
+    memcpy((ret->bullets_y), p + pos, sizeof(double)*sz);
+    pos += sizeof(double)*sz;
+    // array containing the X velocity of the bullets
+    (ret->bullets_vx) = (double*)malloc(sizeof(double)*(ret->no_bullets));
+    memcpy((ret->bullets_vx), p + pos, sizeof(double)*sz);
+    pos += sizeof(double)*sz;
+    // array containing the Y velocity of the bullets
+    (ret->bullets_vy) = (double*)malloc(sizeof(double)*(ret->no_bullets));
+    memcpy((ret->bullets_vy), p + pos, sizeof(double)*sz);
+    pos += sizeof(double)*sz;
+    // array containing the shooter id of the bullets
+    (ret->bullets_shooter) = (bool*)malloc(sizeof(bool)*(ret->no_bullets));
+    memcpy((ret->bullets_shooter), p + pos, sizeof(bool)*sz);
+
+    return ret;
+}
+int hltp_send_host_info(const host_info_t *p) {
+    // struct size
+    size_t struct_size = sizeof(double) * (8 + 4*p->no_bullets) + p->no_bullets * sizeof(bool) + sizeof(size_t);
+    uint8_t *base = (uint8_t*)malloc(struct_size);
+    uint8_t *aux = base;
+    // players information
+    memcpy(aux, p, sizeof(double) * 8);
+    aux = aux + sizeof(double) * 8;
+    // size of arrays
+    memcpy(aux, &(p->no_bullets), sizeof(size_t));
+    aux = aux + sizeof(size_t);
+    // array containing the X positions of the bullets
+    memcpy(aux, p->bullets_x, sizeof(double) * (p->no_bullets));
+    aux = aux + sizeof(double) * (p->no_bullets);
+    // array containing the Y positions of the bullets
+    memcpy(aux, p->bullets_y, sizeof(double) * (p->no_bullets));
+    aux = aux + sizeof(double) * (p->no_bullets);
+    // array containing the X velocity of the bullets
+    memcpy(aux, p->bullets_vx, sizeof(double) * (p->no_bullets));
+    aux = aux + sizeof(double) * (p->no_bullets);
+    // array containing the Y velocity of the bullets
+    memcpy(aux, p->bullets_vy, sizeof(double) * (p->no_bullets));
+    aux = aux + sizeof(double) * (p->no_bullets);
+    // array containing the shooter id of the bullets
+    memcpy(aux, p->bullets_shooter, sizeof(bool) * (p->no_bullets));
+
+    uint8_t type = hltp_type_host;
+    uint8_t* ptr[2]; ptr[0] = &type; ptr[1] = base;
+    size_t    sz[2]; sz [0] =     1; sz [1] = struct_size;
+    return nctp_send(2, ptr, sz);
+}
+
+static remote_info_t* hltp_interpret_remote_info(const uint8_t *p) {
+    remote_info_t *ret = (remote_info_t*)malloc(sizeof(remote_info_t));
+    size_t pos = 0;
+    // keys pressed
+    memcpy(&(ret->remote_keys_pressed), p + pos, sizeof(keys_t));
+    pos += sizeof(keys_t);
+    // mouse positions
+    memcpy(&(ret->remote_mouse_x), p + pos, sizeof(int32_t));
+    pos += sizeof(int32_t);
+    memcpy(&(ret->remote_mouse_y), p + pos, sizeof(int32_t));
+    pos += sizeof(int32_t);
+    // bullets shot
+    memcpy(&(ret->bullets_shot), p + pos, sizeof(size_t));
+    pos += sizeof(size_t);
+    size_t sz = ret->bullets_shot;
+    // array containing the X positions of the bullets
+    (ret->bullets_x) = (double*)malloc(sizeof(double)*sz);
+    memcpy((ret->bullets_x), p + pos, sizeof(double)*sz);
+    pos += sizeof(double)*sz;
+    // array containing the Y positions of the bullets
+    (ret->bullets_y) = (double*)malloc(sizeof(double)*sz);
+    memcpy((ret->bullets_y), p + pos, sizeof(double)*sz);
+    pos += sizeof(double)*sz;
+    // array containing the angle of the bullets
+    (ret->bullets_angle) = (double*)malloc(sizeof(double)*sz);
+    memcpy((ret->bullets_angle), p + pos, sizeof(double)*sz);
+    pos += sizeof(double)*sz;
+
+    return ret;
+}
+
+int hltp_send_remote_info(const remote_info_t *p) {
+    // struct size
+    size_t struct_size = sizeof(keys_t) + sizeof(int32_t) * 2 + sizeof(size_t) + sizeof(double) * (3 *p->bullets_shot);
+    uint8_t *base = (uint8_t*)malloc(struct_size);
+    uint8_t *aux = base;
+    memcpy(aux, p, sizeof(keys_t));
+    aux = aux + sizeof(keys_t);
+    memcpy(aux, p, sizeof(int32_t)*2);
+    aux = aux + sizeof(int32_t)*2;
+    memcpy(aux, &(p->bullets_shot), sizeof(size_t));
+    aux = aux + sizeof(size_t);
+    memcpy(aux, p->bullets_x, sizeof(double)*(p->bullets_shot));
+    aux = aux + sizeof(double)*(p->bullets_shot);
+    memcpy(aux, p->bullets_y, sizeof(double)*(p->bullets_shot));
+    aux = aux + sizeof(double)*(p->bullets_shot);
+    memcpy(aux, p->bullets_angle, sizeof(double)*(p->bullets_shot));
+
+    uint8_t type = hltp_type_remote;
+    uint8_t* ptr[2]; ptr[0] = &type; ptr[1] = base;
+    size_t    sz[2]; sz [0] =     1; sz [1] = struct_size;
+    return nctp_send(2, ptr, sz);
+}
+
 hltp_type hltp_interpret(const uint8_t *p, const size_t sz, void **dest){
     uint8_t ret = p[0];
     switch(ret){
         case hltp_type_string: *dest = hltp_interpret_string(p+1, sz-1); break;
+        case hltp_type_host  : *dest = hltp_interpret_host_info(p+1); break;
+        case hltp_type_remote: *dest = hltp_interpret_remote_info(p+1); break;
         default: *dest = NULL; break;
     }
     return ret;
Index: proj/src/proj.c
===================================================================
--- proj/src/proj.c	(revision 310)
+++ proj/src/proj.c	(revision 311)
@@ -60,7 +60,7 @@
 sprite_t             *sp_crosshair  = NULL;
 
 static int (singleplayer)(void);
-//static int (multiplayer)(void);
+static int (multiplayer)(void);
 static int (chat)(void);
 int(proj_main_loop)(int argc, char *argv[]) {
 
@@ -130,7 +130,7 @@
                     switch(menu_update_state(main_menu, click)){
                         case -1: break;
                         case  0: singleplayer(); break; //campaign(); break;
-                        case  1: break;
+                        case  1: multiplayer() ; break;
                         case  2: chat(); break;
                         case  3: good = false; break;
                     }
@@ -184,50 +184,95 @@
     return 0;
 }
 
-typedef struct __attribute__((packed)) {
-    // player 1
-    double player1_x;
-    double player1_y;
-    double player1_health;
-    double player1_current_health;
+host_info_t     *host   = NULL;
+remote_info_t   *remote = NULL;
 
-    // player 2
-    double player2_x;
-    double player2_y;
-    double player2_health;
-    double player2_current_health;
+static void multiplayer_process(const uint8_t *p, const size_t sz) {
+    void *dest = NULL;
+    hltp_type tp = hltp_interpret(p, sz, &dest);
+    switch(tp){
+        case hltp_type_host:
+            host_info_dtor(host);
+            host = (host_info_t*)dest;
+            break;
+        case hltp_type_remote:
+            remote_info_dtor(remote);
+            remote = (remote_info_t*)dest;
+            break;
+        default: break;
+    }
+}
+static int (multiplayer_host)(void);
+static int (multiplayer_remote)(void);
+static int (multiplayer)(void) {
+    int r;
 
-    // bullets
-    size_t no_bullets;
-    double *bullets_x;
-    double *bullets_y;
-    double *bullets_vx;
-    double *bullets_vy;
-    bool   *bullet_shooter; // 0 for player 1, otherwise 1 for player 2
-} host_info;
+    menu_t *main_menu = menu_ctor(consolas);
+    menu_add_item(main_menu, "Create");
+    menu_add_item(main_menu, "Connect");
+    menu_add_item(main_menu, "Back");
 
-typedef struct __attribute__((packed)) {
-    keys_t client_keys_pressed;
-    int32_t client_mouse_x;
-    int32_t client_mouse_y;
-    size_t bullets_shot;
-    double *bullets_x;
-    double *bullets_y;
-} client_info;
-/*
-static void host_to_client_process(const uint8_t *p, const size_t sz) {
+    //uint32_t refresh_count_value = sys_hz() / REFRESH_RATE;
+    uint8_t last_lb = 0;
+    struct packet pp;
+    keys_t *keys = get_key_presses();
 
-}
+    /// loop stuff
+    int click = 0;
+    uint32_t int_vector = 0;
+    int good = true;
+    while (good) {
+        /* Get a request message. */
+        if((r = get_interrupts_vector(&int_vector))) return r;
+        for (uint32_t i = 0, n = 1; i < 32; i++, n <<= 1) {
+            if (int_vector & n) {
+                interrupt_handler(i);
+                switch (i) {
+                    case TIMER0_IRQ:
 
-static void client_to_host_process(const uint8_t *p, const size_t sz) {
+                    graph_clear_screen();
+                    switch(menu_update_state(main_menu, click)){
+                        case -1: break;
+                        case  0: multiplayer_host(); break;
+                        case  1: multiplayer_remote(); break;
+                        case  2: good = false; break;
+                    }
+                    menu_draw(main_menu);
+
+                    click = 0;
+
+                    sprite_set_pos(sp_crosshair, *get_mouse_X(), *get_mouse_Y());
+                    sprite_draw(sp_crosshair);
+                    graph_draw();
+
+                    break;
+                    case KBC_IRQ:
+                    if ((scancode[0]) == ESC_BREAK_CODE) good = false;
+                    case MOUSE_IRQ:
+                    if (counter_mouse_ih >= 3) {
+                        mouse_parse_packet(packet_mouse_ih, &pp);
+                        update_mouse(&pp);
+                        if (!click) click = last_lb ^ keys->lb_pressed && keys->lb_pressed;
+                        last_lb = keys->lb_pressed;
+                        counter_mouse_ih = 0;
+                    }
+                    break;
+                    case COM1_IRQ: nctp_ih(); break;
+                }
+            }
+        }
+    }
+    return 0;
 }
 
-static int (multiplayer)(void) {
-
+static int (multiplayer_host)(void) {
     //int r;
 
+    nctp_dump();
+    nctp_set_processor(multiplayer_process);/*
+
     ent_set_scale(DEFAULT_SCALE);
-    //text_timer_t *in_game_timer = timer_ctor(consolas);
+    text_timer_t *in_game_timer = timer_ctor(consolas);
 
     list_t *shooter_list = list_ctor();
 
@@ -258,12 +303,97 @@
     /// loop stuff
     uint32_t int_vector = 0;
     int good = true;
+    int state = 0; // -1 for remote win, 0 for draw, 1 for host win
+    while (good) {
+        if ((r = get_interrupts_vector(&int_vector))) return r;
+        for (uint32_t i = 0, n = 1; i < 32; i++, n <<= 1) {
+            interrupt_handler(i);
+            switch (i) {
+                case TIMER0_IRQ:
 
-    // incomplete
+                break;
 
+                case KBC_IRQ:
+
+                break;
+
+                case MOUSE_IRQ:
+
+
+                break;
+
+                case COM1_IRQ: nctp_ih(); break;
+            }
+        }
+    }*/
+
     return 0;
-}*/
+}
+static int (multiplayer_remote)(void) {/*
+    int r;
 
+    nctp_dump();
+    nctp_set_processor(multiplayer_process);
+
+    ent_set_scale(DEFAULT_SCALE);
+    text_timer_t *in_game_timer = timer_ctor(consolas);
+
+    list_t *shooter_list = list_ctor();
+
+    gunner_t *shooter1 = gunner_ctor(bsp_shooter, bsp_pistol, gunner_player, 1); if(shooter1 == NULL) printf("Failed to get shooter1\n");
+    gunner_set_spawn(shooter1, 75, 75);
+
+    gunner_t *shooter2 = gunner_ctor(bsp_shooter, bsp_pistol, gunner_player, 1); if(shooter2 == NULL) printf("Failed to get shooter2\n");
+    gunner_set_spawn(shooter2, 975, 75);
+
+    list_insert(shooter_list, list_end(shooter_list), shooter1);
+    list_insert(shooter_list, list_end(shooter_list), shooter2);
+
+    do {
+        get_random_spawn(map1, shooter1, shooter_list);
+        get_random_spawn(map1, shooter2, shooter_list);
+    } while (distance_gunners(shooter1, shooter2) < 700);
+
+    list_t *bullet_list  = list_ctor();
+
+    ent_set_origin(gunner_get_x(shooter1)-ent_get_XLength()/2.0,
+    gunner_get_y(shooter1)-ent_get_YLength()/2.0);
+
+    //uint32_t refresh_count_value = sys_hz() / REFRESH_RATE;
+    uint8_t last_lb = 0;
+    struct packet pp;
+    keys_t *keys = get_key_presses();
+
+    /// loop stuff
+    uint32_t int_vector = 0;
+    int good = true;
+    int state = 0; // -1 for remote win, 0 for draw, 1 for host win
+    while (good) {
+        if ((r = get_interrupts_vector(&int_vector))) return r;
+        for (uint32_t i = 0, n = 1; i < 32; i++, n <<= 1) {
+            interrupt_handler(i);
+            switch (i) {
+                case TIMER0_IRQ:
+
+                break;
+
+                case KBC_IRQ:
+
+                break;
+
+                case MOUSE_IRQ:
+
+
+                break;
+
+                case COM1_IRQ: nctp_ih(); break;
+            }
+        }
+    }*/
+
+    return 0;
+}
+
 static int (campaign)(void);
 static int (zombies)(void);
 static int (singleplayer)(void) {
@@ -649,17 +779,17 @@
     rectangle_set_outline_width(r_text, 2);
     rectangle_set_outline_color(r_text, GRAPH_WHITE);
     rectangle_set_fill_trans(r_text, GRAPH_TRANSPARENT);
+    }
+    /** t_text */ {
+    for(size_t i = 0; i < CHAT_MAX_NUM; ++i){
+        t_text[i] = text_ctor(consolas, " ");
+        text_set_pos(t_text[i], rectangle_get_x(r_text)+50,
+        rectangle_get_y(r_text)+rectangle_get_h(r_text)-30-25*i);
+        text_set_halign(t_text[i], text_halign_left);
+        text_set_valign(t_text[i], text_valign_bottom);
+        text_set_color (t_text[i], TEXT_COLOR);
+    }
 }
-/** t_text */ {
-for(size_t i = 0; i < CHAT_MAX_NUM; ++i){
-    t_text[i] = text_ctor(consolas, " ");
-    text_set_pos(t_text[i], rectangle_get_x(r_text)+50,
-    rectangle_get_y(r_text)+rectangle_get_h(r_text)-30-25*i);
-    text_set_halign(t_text[i], text_halign_left);
-    text_set_valign(t_text[i], text_valign_bottom);
-    text_set_color (t_text[i], TEXT_COLOR);
-}
-}
 
 /// loop stuff
 uint32_t int_vector = 0;
Index: proj/src/proj_func.c
===================================================================
--- proj/src/proj_func.c	(revision 310)
+++ proj/src/proj_func.c	(revision 311)
@@ -27,6 +27,34 @@
 
 static keys_t key_presses;
 
+void host_info_dtor(host_info_t *p) {
+    if (p==NULL) return;
+
+    if ((p->bullets_x) != NULL){ free(p->bullets_x); p->bullets_x = NULL; }
+
+    if ((p->bullets_y) != NULL){ free(p->bullets_y); p->bullets_y = NULL; }
+
+    if ((p->bullets_vx) != NULL){ free(p->bullets_vx); p->bullets_vx = NULL; }
+
+    if ((p->bullets_vy) != NULL){ free(p->bullets_vy); p->bullets_vy = NULL; }
+
+    if ((p->bullets_shooter) != NULL){ free(p->bullets_shooter); p->bullets_shooter = NULL; }
+
+    free(p);
+}
+
+void remote_info_dtor(remote_info_t *p) {
+    if (p==NULL) return;
+
+    if ((p->bullets_x) != NULL){ free(p->bullets_x); p->bullets_x = NULL; }
+
+    if ((p->bullets_y) != NULL){ free(p->bullets_y); p->bullets_y = NULL; }
+
+    if ((p->bullets_angle) != NULL){ free(p->bullets_angle); p->bullets_angle = NULL; }
+
+    free(p);
+}
+
 void update_key_presses(void) {
     if (sz == 1) {
         switch(scancode[0]) {
