diff --git a/Core/gb.c b/Core/gb.c index b38715c..99d6c2c 100644 --- a/Core/gb.c +++ b/Core/gb.c @@ -648,6 +648,7 @@ void GB_reset(GB_gameboy_t *gb) if (!gb->sgb) { gb->sgb = malloc(sizeof(*gb->sgb)); } + memset(gb->sgb, 0, sizeof(*gb->sgb)); gb->sgb->player_count = 1; } diff --git a/Core/sgb.c b/Core/sgb.c index f23abfa..c60afff 100644 --- a/Core/sgb.c +++ b/Core/sgb.c @@ -2,8 +2,16 @@ enum { MLT_REQ = 0x11, + MASK_EN = 0x17, }; +typedef enum { + MASK_DISABLED, + MASK_FREEZE, + MASK_COLOR_3, + MASK_COLOR_0, +} mask_mode_t; + #define SGB_PACKET_SIZE 16 static void command_ready(GB_gameboy_t *gb) @@ -46,6 +54,9 @@ static void command_ready(GB_gameboy_t *gb) gb->sgb->player_count = (uint8_t[]){1, 2, 1, 4}[gb->sgb->command[1] & 3]; gb->sgb->current_player = gb->sgb->player_count - 1; break; + case MASK_EN: + gb->sgb->mask_mode = gb->sgb->command[1] & 3; + break; default: GB_log(gb, "Unimplemented SGB command %x: ", gb->sgb->command[0] >> 3); for (unsigned i = 0; i < gb->sgb->command_write_index / 8; i++) { @@ -144,8 +155,28 @@ void GB_sgb_render(GB_gameboy_t *gb) gb->screen[i] = border; } + switch ((mask_mode_t) gb->sgb->mask_mode) { + case MASK_DISABLED: + memcpy(gb->sgb->effective_screen_buffer, + gb->sgb->screen_buffer, + sizeof(gb->sgb->effective_screen_buffer)); + break; + case MASK_FREEZE: + break; + + case MASK_COLOR_3: + memset(gb->sgb->effective_screen_buffer, + 3, + sizeof(gb->sgb->effective_screen_buffer)); + break; + case MASK_COLOR_0: + memset(gb->sgb->effective_screen_buffer, + 0, + sizeof(gb->sgb->effective_screen_buffer)); + } + uint32_t *output = &gb->screen[48 + 39 * 256]; - uint8_t *input = gb->sgb->screen_buffer; + uint8_t *input = gb->sgb->effective_screen_buffer; for (unsigned y = 0; y < 144; y++) { for (unsigned x = 0; x < 160; x++) { *(output++) = colors[*(input++) & 3]; diff --git a/Core/sgb.h b/Core/sgb.h index 5074737..bafde35 100644 --- a/Core/sgb.h +++ b/Core/sgb.h @@ -14,9 +14,14 @@ typedef struct { bool disable_commands; /* Screen buffer */ - uint8_t screen_buffer[160 * 144]; + uint8_t screen_buffer[160 * 144]; // Live image from the Game Boy + uint8_t effective_screen_buffer[160 * 144]; // Image actually rendered to the screen + /* Multiplayer Input */ uint8_t player_count, current_player; + + /* Mask */ + uint8_t mask_mode; } GB_sgb_t; void GB_sgb_write(GB_gameboy_t *gb, uint8_t value);