diff --git a/examples/benchmark/peanut-benchmark.c b/examples/benchmark/peanut-benchmark.c index 0981569..b22f750 100644 --- a/examples/benchmark/peanut-benchmark.c +++ b/examples/benchmark/peanut-benchmark.c @@ -127,11 +127,7 @@ static void lcd_draw_line(struct gb_s *gb, const uint8_t pixels[160], for (unsigned int x = 0; x < LCD_WIDTH; x++) { -#if PEANUT_GB_16BIT_COLOUR - priv->fb[line][x] = palette[pixels[x] & 3]; -#else - priv->fb[line][x] = palette[pixels[x]]; -#endif + priv->fb[line][x] = palette[pixels[x] & LCD_COLOUR]; } } #endif diff --git a/examples/debug/peanut-debug.c b/examples/debug/peanut-debug.c index daa7aa4..bdfe2e7 100644 --- a/examples/debug/peanut-debug.c +++ b/examples/debug/peanut-debug.c @@ -14,16 +14,17 @@ #include "SDL.h" +#define PEANUT_GB_USE_NIBBLE_FOR_PALETTE 1 #define ENABLE_LCD 1 #define ENABLE_SOUND 0 #include "../../peanut_gb.h" -const uint16_t lcd_palette[3][4] = +const uint16_t lcd_palette[4 * 4] = { - { 0x7FFF, 0x5294, 0x294A, 0x0000 }, - { 0x7FFF, 0x5294, 0x294A, 0x0000 }, - { 0x7FFF, 0x5294, 0x294A, 0x0000 } + 0x7FFF, 0x5294, 0x294A, 0x0000, + 0x7FFF, 0x5294, 0x294A, 0x0000, + 0x7FFF, 0x5294, 0x294A, 0x0000 }; struct priv_t @@ -180,9 +181,7 @@ void lcd_draw_line(struct gb_s *gb, const uint8_t pixels[160], for(unsigned int x = 0; x < LCD_WIDTH; x++) { - priv->fb[line][x] = lcd_palette - [(pixels[x] & LCD_PALETTE_ALL) >> 4] - [pixels[x] & 3]; + priv->fb[line][x] = lcd_palette[pixels[x] & (LCD_COLOUR | LCD_PALETTE_ALL)]; } } #endif diff --git a/examples/mini_fb/peanut_minifb.c b/examples/mini_fb/peanut_minifb.c index bfae731..5699d26 100644 --- a/examples/mini_fb/peanut_minifb.c +++ b/examples/mini_fb/peanut_minifb.c @@ -115,7 +115,7 @@ void lcd_draw_line(struct gb_s *gb, const uint8_t pixels[160], const uint32_t palette[] = { 0xFFFFFF, 0xA5A5A5, 0x525252, 0x000000 }; for(unsigned int x = 0; x < LCD_WIDTH; x++) - priv->fb[line][x] = palette[pixels[x] & 3]; + priv->fb[line][x] = palette[pixels[x] & LCD_COLOUR]; } #endif diff --git a/examples/sdl2/peanut_sdl.c b/examples/sdl2/peanut_sdl.c index 24ab521..f6cb6ce 100644 --- a/examples/sdl2/peanut_sdl.c +++ b/examples/sdl2/peanut_sdl.c @@ -17,6 +17,8 @@ # include "minigb_apu/minigb_apu.h" #endif +#define PEANUT_GB_USE_NIBBLE_FOR_PALETTE 1 + #include "../../peanut_gb.h" enum { @@ -36,7 +38,7 @@ struct priv_t uint8_t *bootrom; /* Colour palette for each BG, OBJ0, and OBJ1. */ - uint16_t selected_palette[3][4]; + uint16_t selected_palette[4 * 4]; uint16_t fb[LCD_HEIGHT][LCD_WIDTH]; }; @@ -198,11 +200,11 @@ void auto_assign_palette(struct priv_t *priv, uint8_t game_checksum) case 0x71: case 0xFF: { - const uint16_t palette[3][4] = + const uint16_t palette[3 * 4] = { - { 0x7FFF, 0x7E60, 0x7C00, 0x0000 }, /* OBJ0 */ - { 0x7FFF, 0x7E60, 0x7C00, 0x0000 }, /* OBJ1 */ - { 0x7FFF, 0x7E60, 0x7C00, 0x0000 } /* BG */ + 0x7FFF, 0x7E60, 0x7C00, 0x0000, /* OBJ0 */ + 0x7FFF, 0x7E60, 0x7C00, 0x0000, /* OBJ1 */ + 0x7FFF, 0x7E60, 0x7C00, 0x0000 /* BG */ }; memcpy(priv->selected_palette, palette, palette_bytes); break; @@ -213,11 +215,11 @@ void auto_assign_palette(struct priv_t *priv, uint8_t game_checksum) case 0xDB: case 0x95: /* Not officially */ { - const uint16_t palette[3][4] = + const uint16_t palette[3 * 4] = { - { 0x7FFF, 0x7FE0, 0x7C00, 0x0000 }, /* OBJ0 */ - { 0x7FFF, 0x7FE0, 0x7C00, 0x0000 }, /* OBJ1 */ - { 0x7FFF, 0x7FE0, 0x7C00, 0x0000 } /* BG */ + 0x7FFF, 0x7FE0, 0x7C00, 0x0000, /* OBJ0 */ + 0x7FFF, 0x7FE0, 0x7C00, 0x0000, /* OBJ1 */ + 0x7FFF, 0x7FE0, 0x7C00, 0x0000 /* BG */ }; memcpy(priv->selected_palette, palette, palette_bytes); break; @@ -226,11 +228,11 @@ void auto_assign_palette(struct priv_t *priv, uint8_t game_checksum) /* Donkey Kong */ case 0x19: { - const uint16_t palette[3][4] = + const uint16_t palette[3 * 4] = { - { 0x7FFF, 0x7E10, 0x48E7, 0x0000 }, /* OBJ0 */ - { 0x7FFF, 0x7E10, 0x48E7, 0x0000 }, /* OBJ1 */ - { 0x7FFF, 0x7E60, 0x7C00, 0x0000 } /* BG */ + 0x7FFF, 0x7E10, 0x48E7, 0x0000, /* OBJ0 */ + 0x7FFF, 0x7E10, 0x48E7, 0x0000, /* OBJ1 */ + 0x7FFF, 0x7E60, 0x7C00, 0x0000 /* BG */ }; memcpy(priv->selected_palette, palette, palette_bytes); break; @@ -243,11 +245,11 @@ void auto_assign_palette(struct priv_t *priv, uint8_t game_checksum) /* Pokemon Blue Star */ case 0xD8: { - const uint16_t palette[3][4] = + const uint16_t palette[3 * 4] = { - { 0x7FFF, 0x7E10, 0x48E7, 0x0000 }, /* OBJ0 */ - { 0x7FFF, 0x329F, 0x001F, 0x0000 }, /* OBJ1 */ - { 0x7FFF, 0x329F, 0x001F, 0x0000 } /* BG */ + 0x7FFF, 0x7E10, 0x48E7, 0x0000, /* OBJ0 */ + 0x7FFF, 0x329F, 0x001F, 0x0000, /* OBJ1 */ + 0x7FFF, 0x329F, 0x001F, 0x0000 /* BG */ }; memcpy(priv->selected_palette, palette, palette_bytes); break; @@ -256,11 +258,11 @@ void auto_assign_palette(struct priv_t *priv, uint8_t game_checksum) /* Pokemon Red */ case 0x14: { - const uint16_t palette[3][4] = + const uint16_t palette[3 * 4] = { - { 0x7FFF, 0x3FE6, 0x0200, 0x0000 }, /* OBJ0 */ - { 0x7FFF, 0x7E10, 0x48E7, 0x0000 }, /* OBJ1 */ - { 0x7FFF, 0x7E10, 0x48E7, 0x0000 } /* BG */ + 0x7FFF, 0x3FE6, 0x0200, 0x0000, /* OBJ0 */ + 0x7FFF, 0x7E10, 0x48E7, 0x0000, /* OBJ1 */ + 0x7FFF, 0x7E10, 0x48E7, 0x0000 /* BG */ }; memcpy(priv->selected_palette, palette, palette_bytes); break; @@ -269,11 +271,11 @@ void auto_assign_palette(struct priv_t *priv, uint8_t game_checksum) /* Pokemon Red Star */ case 0x8B: { - const uint16_t palette[3][4] = + const uint16_t palette[3 * 4] = { - { 0x7FFF, 0x7E10, 0x48E7, 0x0000 }, /* OBJ0 */ - { 0x7FFF, 0x329F, 0x001F, 0x0000 }, /* OBJ1 */ - { 0x7FFF, 0x3FE6, 0x0200, 0x0000 } /* BG */ + 0x7FFF, 0x7E10, 0x48E7, 0x0000, /* OBJ0 */ + 0x7FFF, 0x329F, 0x001F, 0x0000, /* OBJ1 */ + 0x7FFF, 0x3FE6, 0x0200, 0x0000 /* BG */ }; memcpy(priv->selected_palette, palette, palette_bytes); break; @@ -285,11 +287,11 @@ void auto_assign_palette(struct priv_t *priv, uint8_t game_checksum) case 0x5C: case 0xB3: { - const uint16_t palette[3][4] = + const uint16_t palette[3 * 4] = { - { 0x7D8A, 0x6800, 0x3000, 0x0000 }, /* OBJ0 */ - { 0x001F, 0x7FFF, 0x7FEF, 0x021F }, /* OBJ1 */ - { 0x527F, 0x7FE0, 0x0180, 0x0000 } /* BG */ + 0x7D8A, 0x6800, 0x3000, 0x0000, /* OBJ0 */ + 0x001F, 0x7FFF, 0x7FEF, 0x021F, /* OBJ1 */ + 0x527F, 0x7FE0, 0x0180, 0x0000 /* BG */ }; memcpy(priv->selected_palette, palette, palette_bytes); break; @@ -301,11 +303,11 @@ void auto_assign_palette(struct priv_t *priv, uint8_t game_checksum) case 0x4B: case 0x6B: { - const uint16_t palette[3][4] = + const uint16_t palette[3 * 4] = { - { 0x7F08, 0x7F40, 0x48E0, 0x2400 }, /* OBJ0 */ - { 0x7FFF, 0x2EFF, 0x7C00, 0x001F }, /* OBJ1 */ - { 0x7FFF, 0x463B, 0x2951, 0x0000 } /* BG */ + 0x7F08, 0x7F40, 0x48E0, 0x2400, /* OBJ0 */ + 0x7FFF, 0x2EFF, 0x7C00, 0x001F, /* OBJ1 */ + 0x7FFF, 0x463B, 0x2951, 0x0000 /* BG */ }; memcpy(priv->selected_palette, palette, palette_bytes); break; @@ -314,11 +316,11 @@ void auto_assign_palette(struct priv_t *priv, uint8_t game_checksum) /* Link's Awakening */ case 0x70: { - const uint16_t palette[3][4] = + const uint16_t palette[3 * 4] = { - { 0x7FFF, 0x03E0, 0x1A00, 0x0120 }, /* OBJ0 */ - { 0x7FFF, 0x329F, 0x001F, 0x001F }, /* OBJ1 */ - { 0x7FFF, 0x7E10, 0x48E7, 0x0000 } /* BG */ + 0x7FFF, 0x03E0, 0x1A00, 0x0120, /* OBJ0 */ + 0x7FFF, 0x329F, 0x001F, 0x001F, /* OBJ1 */ + 0x7FFF, 0x7E10, 0x48E7, 0x0000 /* BG */ }; memcpy(priv->selected_palette, palette, palette_bytes); break; @@ -334,11 +336,11 @@ void auto_assign_palette(struct priv_t *priv, uint8_t game_checksum) case 0x6D: case 0xF6: { - const uint16_t palette[3][4] = + const uint16_t palette[3 * 4] = { - { 0x7FFF, 0x329F, 0x001F, 0x0000 }, /* OBJ0 */ - { 0x7FFF, 0x3FE6, 0x0200, 0x0000 }, /* OBJ1 */ - { 0x7FFF, 0x7EAC, 0x40C0, 0x0000 } /* BG */ + 0x7FFF, 0x329F, 0x001F, 0x0000, /* OBJ0 */ + 0x7FFF, 0x3FE6, 0x0200, 0x0000, /* OBJ1 */ + 0x7FFF, 0x7EAC, 0x40C0, 0x0000 /* BG */ }; memcpy(priv->selected_palette, palette, palette_bytes); break; @@ -346,11 +348,11 @@ void auto_assign_palette(struct priv_t *priv, uint8_t game_checksum) default: { - const uint16_t palette[3][4] = + const uint16_t palette[3 * 4] = { - { 0x7FFF, 0x5294, 0x294A, 0x0000 }, - { 0x7FFF, 0x5294, 0x294A, 0x0000 }, - { 0x7FFF, 0x5294, 0x294A, 0x0000 } + 0x7FFF, 0x5294, 0x294A, 0x0000, + 0x7FFF, 0x5294, 0x294A, 0x0000, + 0x7FFF, 0x5294, 0x294A, 0x0000 }; SDL_LogMessage(LOG_CATERGORY_PEANUTSDL, SDL_LOG_PRIORITY_INFO, @@ -377,11 +379,11 @@ void manual_assign_palette(struct priv_t *priv, uint8_t selection) /* 0x05 (Right) */ case 0: { - const uint16_t palette[3][4] = + const uint16_t palette[3 * 4] = { - { 0x7FFF, 0x2BE0, 0x7D00, 0x0000 }, - { 0x7FFF, 0x2BE0, 0x7D00, 0x0000 }, - { 0x7FFF, 0x2BE0, 0x7D00, 0x0000 } + 0x7FFF, 0x2BE0, 0x7D00, 0x0000, + 0x7FFF, 0x2BE0, 0x7D00, 0x0000, + 0x7FFF, 0x2BE0, 0x7D00, 0x0000 }; memcpy(priv->selected_palette, palette, palette_bytes); break; @@ -390,11 +392,11 @@ void manual_assign_palette(struct priv_t *priv, uint8_t selection) /* 0x07 (A + Down) */ case 1: { - const uint16_t palette[3][4] = + const uint16_t palette[3 * 4] = { - { 0x7FFF, 0x7FE0, 0x7C00, 0x0000 }, - { 0x7FFF, 0x7FE0, 0x7C00, 0x0000 }, - { 0x7FFF, 0x7FE0, 0x7C00, 0x0000 } + 0x7FFF, 0x7FE0, 0x7C00, 0x0000, + 0x7FFF, 0x7FE0, 0x7C00, 0x0000, + 0x7FFF, 0x7FE0, 0x7C00, 0x0000 }; memcpy(priv->selected_palette, palette, palette_bytes); break; @@ -403,11 +405,11 @@ void manual_assign_palette(struct priv_t *priv, uint8_t selection) /* 0x12 (Up) */ case 2: { - const uint16_t palette[3][4] = + const uint16_t palette[3 * 4] = { - { 0x7FFF, 0x7EAC, 0x40C0, 0x0000 }, - { 0x7FFF, 0x7EAC, 0x40C0, 0x0000 }, - { 0x7FFF, 0x7EAC, 0x40C0, 0x0000 } + 0x7FFF, 0x7EAC, 0x40C0, 0x0000, + 0x7FFF, 0x7EAC, 0x40C0, 0x0000, + 0x7FFF, 0x7EAC, 0x40C0, 0x0000 }; memcpy(priv->selected_palette, palette, palette_bytes); break; @@ -416,11 +418,11 @@ void manual_assign_palette(struct priv_t *priv, uint8_t selection) /* 0x13 (B + Right) */ case 3: { - const uint16_t palette[3][4] = + const uint16_t palette[3 * 4] = { - { 0x0000, 0x0210, 0x7F60, 0x7FFF }, - { 0x0000, 0x0210, 0x7F60, 0x7FFF }, - { 0x0000, 0x0210, 0x7F60, 0x7FFF } + 0x0000, 0x0210, 0x7F60, 0x7FFF, + 0x0000, 0x0210, 0x7F60, 0x7FFF, + 0x0000, 0x0210, 0x7F60, 0x7FFF }; memcpy(priv->selected_palette, palette, palette_bytes); break; @@ -430,11 +432,11 @@ void manual_assign_palette(struct priv_t *priv, uint8_t selection) default: case 4: { - const uint16_t palette[3][4] = + const uint16_t palette[3 * 4] = { - { 0x7FFF, 0x5294, 0x294A, 0x0000 }, - { 0x7FFF, 0x5294, 0x294A, 0x0000 }, - { 0x7FFF, 0x5294, 0x294A, 0x0000 } + 0x7FFF, 0x5294, 0x294A, 0x0000, + 0x7FFF, 0x5294, 0x294A, 0x0000, + 0x7FFF, 0x5294, 0x294A, 0x0000 }; memcpy(priv->selected_palette, palette, palette_bytes); break; @@ -443,11 +445,11 @@ void manual_assign_palette(struct priv_t *priv, uint8_t selection) /* 0x17 (Down) */ case 5: { - const uint16_t palette[3][4] = + const uint16_t palette[3 * 4] = { - { 0x7FF4, 0x7E52, 0x4A5F, 0x0000 }, - { 0x7FF4, 0x7E52, 0x4A5F, 0x0000 }, - { 0x7FF4, 0x7E52, 0x4A5F, 0x0000 } + 0x7FF4, 0x7E52, 0x4A5F, 0x0000, + 0x7FF4, 0x7E52, 0x4A5F, 0x0000, + 0x7FF4, 0x7E52, 0x4A5F, 0x0000 }; memcpy(priv->selected_palette, palette, palette_bytes); break; @@ -456,11 +458,11 @@ void manual_assign_palette(struct priv_t *priv, uint8_t selection) /* 0x19 (B + Up) */ case 6: { - const uint16_t palette[3][4] = + const uint16_t palette[3 * 4] = { - { 0x7FFF, 0x7EAC, 0x40C0, 0x0000 }, - { 0x7FFF, 0x7EAC, 0x40C0, 0x0000 }, - { 0x7F98, 0x6670, 0x41A5, 0x2CC1 } + 0x7FFF, 0x7EAC, 0x40C0, 0x0000, + 0x7FFF, 0x7EAC, 0x40C0, 0x0000, + 0x7F98, 0x6670, 0x41A5, 0x2CC1 }; memcpy(priv->selected_palette, palette, palette_bytes); break; @@ -469,11 +471,11 @@ void manual_assign_palette(struct priv_t *priv, uint8_t selection) /* 0x1C (A + Right) */ case 7: { - const uint16_t palette[3][4] = + const uint16_t palette[3 * 4] = { - { 0x7FFF, 0x7E10, 0x48E7, 0x0000 }, - { 0x7FFF, 0x7E10, 0x48E7, 0x0000 }, - { 0x7FFF, 0x3FE6, 0x0198, 0x0000 } + 0x7FFF, 0x7E10, 0x48E7, 0x0000, + 0x7FFF, 0x7E10, 0x48E7, 0x0000, + 0x7FFF, 0x3FE6, 0x0198, 0x0000 }; memcpy(priv->selected_palette, palette, palette_bytes); break; @@ -482,11 +484,11 @@ void manual_assign_palette(struct priv_t *priv, uint8_t selection) /* 0x0D (A + Left) */ case 8: { - const uint16_t palette[3][4] = + const uint16_t palette[3 * 4] = { - { 0x7FFF, 0x7E10, 0x48E7, 0x0000 }, - { 0x7FFF, 0x7EAC, 0x40C0, 0x0000 }, - { 0x7FFF, 0x463B, 0x2951, 0x0000 } + 0x7FFF, 0x7E10, 0x48E7, 0x0000, + 0x7FFF, 0x7EAC, 0x40C0, 0x0000, + 0x7FFF, 0x463B, 0x2951, 0x0000 }; memcpy(priv->selected_palette, palette, palette_bytes); break; @@ -495,11 +497,11 @@ void manual_assign_palette(struct priv_t *priv, uint8_t selection) /* 0x10 (A + Up) */ case 9: { - const uint16_t palette[3][4] = + const uint16_t palette[3 * 4] = { - { 0x7FFF, 0x3FE6, 0x0200, 0x0000 }, - { 0x7FFF, 0x329F, 0x001F, 0x0000 }, - { 0x7FFF, 0x7E10, 0x48E7, 0x0000 } + 0x7FFF, 0x3FE6, 0x0200, 0x0000, + 0x7FFF, 0x329F, 0x001F, 0x0000, + 0x7FFF, 0x7E10, 0x48E7, 0x0000 }; memcpy(priv->selected_palette, palette, palette_bytes); break; @@ -508,11 +510,11 @@ void manual_assign_palette(struct priv_t *priv, uint8_t selection) /* 0x18 (Left) */ case 10: { - const uint16_t palette[3][4] = + const uint16_t palette[3 * 4] = { - { 0x7FFF, 0x7E10, 0x48E7, 0x0000 }, - { 0x7FFF, 0x3FE6, 0x0200, 0x0000 }, - { 0x7FFF, 0x329F, 0x001F, 0x0000 } + 0x7FFF, 0x7E10, 0x48E7, 0x0000, + 0x7FFF, 0x3FE6, 0x0200, 0x0000, + 0x7FFF, 0x329F, 0x001F, 0x0000 }; memcpy(priv->selected_palette, palette, palette_bytes); break; @@ -521,11 +523,11 @@ void manual_assign_palette(struct priv_t *priv, uint8_t selection) /* 0x1A (B + Down) */ case 11: { - const uint16_t palette[3][4] = + const uint16_t palette[3 * 4] = { - { 0x7FFF, 0x329F, 0x001F, 0x0000 }, - { 0x7FFF, 0x3FE6, 0x0200, 0x0000 }, - { 0x7FFF, 0x7FE0, 0x3D20, 0x0000 } + 0x7FFF, 0x329F, 0x001F, 0x0000, + 0x7FFF, 0x3FE6, 0x0200, 0x0000, + 0x7FFF, 0x7FE0, 0x3D20, 0x0000 }; memcpy(priv->selected_palette, palette, palette_bytes); break; @@ -546,9 +548,7 @@ void lcd_draw_line(struct gb_s *gb, const uint8_t pixels[160], for(unsigned int x = 0; x < LCD_WIDTH; x++) { - priv->fb[line][x] = priv->selected_palette - [(pixels[x] & LCD_PALETTE_ALL) >> 4] - [pixels[x] & 3]; + priv->fb[line][x] = priv->selected_palette[pixels[x] & (LCD_COLOUR | LCD_PALETTE_ALL)]; } } #endif diff --git a/peanut_gb.h b/peanut_gb.h index c10963a..dc9d435 100644 --- a/peanut_gb.h +++ b/peanut_gb.h @@ -94,6 +94,27 @@ # define PEANUT_GB_12_COLOUR 1 #endif +/** + * If PEANUT_GB_USE_DOUBLE_WIDTH_PALETTE is enabled, the pixel colour data will be + * duplicated into both nibbles. This allows for faster scaling when rendering to + * a 4 bit per pixel destination. + * + * PEANUT_GB_USE_NIBBLE_FOR_PALETTE must also be defined for this to work. + */ +#ifndef PEANUT_GB_USE_DOUBLE_WIDTH_PALETTE +# define PEANUT_GB_USE_DOUBLE_WIDTH_PALETTE 0 +#endif + +/** + * If PEANUT_GB_USE_NIBBLE_FOR_PALETTE is enabled, the pixel colour data will be + * packed into the four least significant bits of a byte (or nibble). This + * allows for a smaller look-up table (LUT) to be used directly, in comparison + * to performing bit shifts or using a larger LUT. + */ +#ifndef PEANUT_GB_USE_NIBBLE_FOR_PALETTE +# define PEANUT_GB_USE_NIBBLE_FOR_PALETTE PEANUT_GB_USE_DOUBLE_WIDTH_PALETTE +#endif + /* Adds more code to improve LCD rendering accuracy. */ #ifndef PEANUT_GB_HIGH_LCD_ACCURACY # define PEANUT_GB_HIGH_LCD_ACCURACY 1 @@ -464,20 +485,33 @@ struct count_s #define LCD_COLOUR 0x03 # if PEANUT_GB_12_COLOUR - /** - * Bit mask for whether a pixel is OBJ0, OBJ1, or BG. Each may have a different - * palette when playing a DMG game on CGB. - */ - #define LCD_PALETTE_OBJ 0x10 - #define LCD_PALETTE_BG 0x20 - /** - * Bit mask for the two bits listed above. - * LCD_PALETTE_ALL == 0b00 --> OBJ0 - * LCD_PALETTE_ALL == 0b01 --> OBJ1 - * LCD_PALETTE_ALL == 0b10 --> BG - * LCD_PALETTE_ALL == 0b11 --> NOT POSSIBLE - */ - #define LCD_PALETTE_ALL 0x30 +# if PEANUT_GB_USE_NIBBLE_FOR_PALETTE + /** + * Bit mask for whether a pixel is OBJ0, OBJ1, or BG. Each may have a different + * palette when playing a DMG game on CGB. + */ + #define LCD_PALETTE_OBJ 0x04 + #define LCD_PALETTE_BG 0x08 + /** + * Bit mask for the two bits listed above. + * LCD_PALETTE_ALL == 0b00 --> OBJ0 + * LCD_PALETTE_ALL == 0b01 --> OBJ1 + * LCD_PALETTE_ALL == 0b10 --> BG + * LCD_PALETTE_ALL == 0b11 --> NOT POSSIBLE + */ + #define LCD_PALETTE_ALL 0x0c +# else +# if PEANUT_GB_USE_DOUBLE_WIDTH_PALETTE +# error PEANUT_GB_USE_NIBBLE_FOR_PALETTE must be enabled for PEANUT_GB_USE_DOUBLE_WIDTH_PALETTE to work +# endif + #define LCD_PALETTE_OBJ 0x10 + #define LCD_PALETTE_BG 0x20 + #define LCD_PALETTE_ALL 0x30 +# endif +# else + #define LCD_PALETTE_OBJ 0 + #define LCD_PALETTE_BG 0 + #define LCD_PALETTE_ALL 0 # endif #endif @@ -1132,26 +1166,44 @@ void __gb_write(struct gb_s *gb, uint_fast16_t addr, uint8_t val) /* DMG Palette Registers */ case 0x47: gb->hram_io[IO_BGP] = val; - gb->display.bg_palette[0] = (gb->hram_io[IO_BGP] & 0x03); - gb->display.bg_palette[1] = (gb->hram_io[IO_BGP] >> 2) & 0x03; - gb->display.bg_palette[2] = (gb->hram_io[IO_BGP] >> 4) & 0x03; - gb->display.bg_palette[3] = (gb->hram_io[IO_BGP] >> 6) & 0x03; + gb->display.bg_palette[0] = ((gb->hram_io[IO_BGP] & 0x03)) | LCD_PALETTE_BG; + gb->display.bg_palette[1] = ((gb->hram_io[IO_BGP] >> 2) & 0x03) | LCD_PALETTE_BG; + gb->display.bg_palette[2] = ((gb->hram_io[IO_BGP] >> 4) & 0x03) | LCD_PALETTE_BG; + gb->display.bg_palette[3] = ((gb->hram_io[IO_BGP] >> 6) & 0x03) | LCD_PALETTE_BG; +#if PEANUT_GB_USE_DOUBLE_WIDTH_PALETTE + gb->display.bg_palette[0] |= gb->display.bg_palette[0] << 4; + gb->display.bg_palette[1] |= gb->display.bg_palette[1] << 4; + gb->display.bg_palette[2] |= gb->display.bg_palette[2] << 4; + gb->display.bg_palette[3] |= gb->display.bg_palette[3] << 4; +#endif return; case 0x48: gb->hram_io[IO_OBP0] = val; - gb->display.sp_palette[0] = (gb->hram_io[IO_OBP0] & 0x03); - gb->display.sp_palette[1] = (gb->hram_io[IO_OBP0] >> 2) & 0x03; - gb->display.sp_palette[2] = (gb->hram_io[IO_OBP0] >> 4) & 0x03; - gb->display.sp_palette[3] = (gb->hram_io[IO_OBP0] >> 6) & 0x03; + gb->display.sp_palette[0] = ((gb->hram_io[IO_OBP0] & 0x03)); + gb->display.sp_palette[1] = ((gb->hram_io[IO_OBP0] >> 2) & 0x03); + gb->display.sp_palette[2] = ((gb->hram_io[IO_OBP0] >> 4) & 0x03); + gb->display.sp_palette[3] = ((gb->hram_io[IO_OBP0] >> 6) & 0x03); +#if PEANUT_GB_USE_DOUBLE_WIDTH_PALETTE + gb->display.sp_palette[0] |= gb->display.sp_palette[0] << 4; + gb->display.sp_palette[1] |= gb->display.sp_palette[1] << 4; + gb->display.sp_palette[2] |= gb->display.sp_palette[2] << 4; + gb->display.sp_palette[3] |= gb->display.sp_palette[3] << 4; +#endif return; case 0x49: gb->hram_io[IO_OBP1] = val; - gb->display.sp_palette[4] = (gb->hram_io[IO_OBP1] & 0x03); - gb->display.sp_palette[5] = (gb->hram_io[IO_OBP1] >> 2) & 0x03; - gb->display.sp_palette[6] = (gb->hram_io[IO_OBP1] >> 4) & 0x03; - gb->display.sp_palette[7] = (gb->hram_io[IO_OBP1] >> 6) & 0x03; + gb->display.sp_palette[4] = ((gb->hram_io[IO_OBP1] & 0x03)) | LCD_PALETTE_OBJ; + gb->display.sp_palette[5] = ((gb->hram_io[IO_OBP1] >> 2) & 0x03) | LCD_PALETTE_OBJ; + gb->display.sp_palette[6] = ((gb->hram_io[IO_OBP1] >> 4) & 0x03) | LCD_PALETTE_OBJ; + gb->display.sp_palette[7] = ((gb->hram_io[IO_OBP1] >> 6) & 0x03) | LCD_PALETTE_OBJ; +#if PEANUT_GB_USE_DOUBLE_WIDTH_PALETTE + gb->display.sp_palette[4] |= gb->display.sp_palette[4] << 4; + gb->display.sp_palette[5] |= gb->display.sp_palette[5] << 4; + gb->display.sp_palette[6] |= gb->display.sp_palette[6] << 4; + gb->display.sp_palette[7] |= gb->display.sp_palette[7] << 4; +#endif return; /* Window Position Registers */ @@ -1488,9 +1540,6 @@ void __gb_draw_line(struct gb_s *gb) /* copy background */ c = (t1 & 0x1) | ((t2 & 0x1) << 1); pixels[disp_x] = gb->display.bg_palette[c]; -#if PEANUT_GB_12_COLOUR - pixels[disp_x] |= LCD_PALETTE_BG; -#endif t1 = t1 >> 1; t2 = t2 >> 1; px++; @@ -1556,9 +1605,6 @@ void __gb_draw_line(struct gb_s *gb) // copy window c = (t1 & 0x1) | ((t2 & 0x1) << 1); pixels[disp_x] = gb->display.bg_palette[c]; -#if PEANUT_GB_12_COLOUR - pixels[disp_x] |= LCD_PALETTE_BG; -#endif t1 = t1 >> 1; t2 = t2 >> 1; px++; @@ -1684,16 +1730,12 @@ void __gb_draw_line(struct gb_s *gb) uint8_t c = (t1 & 0x1) | ((t2 & 0x1) << 1); // check transparency / sprite overlap / background overlap - if(c && !(OF & OBJ_PRIORITY && !((pixels[disp_x] & 0x3) == gb->display.bg_palette[0]))) + if(c && !(OF & OBJ_PRIORITY && !((pixels[disp_x] & LCD_COLOUR) == (gb->display.bg_palette[0] & LCD_COLOUR)))) { /* Set pixel colour. */ pixels[disp_x] = (OF & OBJ_PALETTE) ? gb->display.sp_palette[c + 4] : gb->display.sp_palette[c]; -#if PEANUT_GB_12_COLOUR - /* Set pixel palette (OBJ0 or OBJ1). */ - pixels[disp_x] |= (OF & OBJ_PALETTE); -#endif } t1 = t1 >> 1;