Emulate built in SGB palettes

This commit is contained in:
Lior Halphon 2019-07-20 16:10:24 +03:00
parent 17793ef361
commit e3672e8293
2 changed files with 93 additions and 10 deletions

View File

@ -68,6 +68,75 @@ static inline void load_attribute_file(GB_gameboy_t *gb, unsigned file_index)
} }
} }
static const uint16_t built_in_palettes[] =
{
0x67BF, 0x265B, 0x10B5, 0x2866,
0x637B, 0x3AD9, 0x0956, 0x0000,
0x7F1F, 0x2A7D, 0x30F3, 0x4CE7,
0x57FF, 0x2618, 0x001F, 0x006A,
0x5B7F, 0x3F0F, 0x222D, 0x10EB,
0x7FBB, 0x2A3C, 0x0015, 0x0900,
0x2800, 0x7680, 0x01EF, 0x2FFF,
0x73BF, 0x46FF, 0x0110, 0x0066,
0x533E, 0x2638, 0x01E5, 0x0000,
0x7FFF, 0x2BBF, 0x00DF, 0x2C0A,
0x7F1F, 0x463D, 0x74CF, 0x4CA5,
0x53FF, 0x03E0, 0x00DF, 0x2800,
0x433F, 0x72D2, 0x3045, 0x0822,
0x7FFA, 0x2A5F, 0x0014, 0x0003,
0x1EED, 0x215C, 0x42FC, 0x0060,
0x7FFF, 0x5EF7, 0x39CE, 0x0000,
0x4F5F, 0x630E, 0x159F, 0x3126,
0x637B, 0x121C, 0x0140, 0x0840,
0x66BC, 0x3FFF, 0x7EE0, 0x2C84,
0x5FFE, 0x3EBC, 0x0321, 0x0000,
0x63FF, 0x36DC, 0x11F6, 0x392A,
0x65EF, 0x7DBF, 0x035F, 0x2108,
0x2B6C, 0x7FFF, 0x1CD9, 0x0007,
0x53FC, 0x1F2F, 0x0E29, 0x0061,
0x36BE, 0x7EAF, 0x681A, 0x3C00,
0x7BBE, 0x329D, 0x1DE8, 0x0423,
0x739F, 0x6A9B, 0x7293, 0x0001,
0x5FFF, 0x6732, 0x3DA9, 0x2481,
0x577F, 0x3EBC, 0x456F, 0x1880,
0x6B57, 0x6E1B, 0x5010, 0x0007,
0x0F96, 0x2C97, 0x0045, 0x3200,
0x67FF, 0x2F17, 0x2230, 0x1548,
};
static const struct {
char name[16];
unsigned palette_index;
} palette_assignments[] =
{
{"ZELDA", 5},
{"SUPER MARIOLAND", 6},
{"MARIOLAND2", 0x14},
{"SUPERMARIOLAND3", 2},
{"KIRBY DREAM LAND", 0xB},
{"HOSHINOKA-BI", 0xB},
{"KIRBY'S PINBALL", 3},
{"YOSSY NO TAMAGO", 0xC},
{"MARIO & YOSHI", 0xC},
{"YOSSY NO COOKIE", 4},
{"YOSHI'S COOKIE", 4},
{"DR.MARIO", 0x12},
{"TETRIS", 0x11},
{"YAKUMAN", 0x13},
{"METROID2", 0x1F},
{"KAERUNOTAMENI", 9},
{"GOLF", 0x18},
{"ALLEY WAY", 0x16},
{"BASEBALL", 0xF},
{"TENNIS", 0x17},
{"F1RACE", 0x1E},
{"KID ICARUS", 0xE},
{"QIX", 0x19},
{"SOLARSTRIKER", 7},
{"X", 0x1C},
{"GBWARS", 0x15},
};
static void command_ready(GB_gameboy_t *gb) static void command_ready(GB_gameboy_t *gb)
{ {
/* SGB header commands are used to send the contents of the header to the SNES CPU. /* SGB header commands are used to send the contents of the header to the SNES CPU.
@ -77,6 +146,8 @@ static void command_ready(GB_gameboy_t *gb)
0xE content bytes. The last command, FB, is padded with zeros, so information past the header is not sent. */ 0xE content bytes. The last command, FB, is padded with zeros, so information past the header is not sent. */
if ((gb->sgb->command[0] & 0xF1) == 0xF1) { if ((gb->sgb->command[0] & 0xF1) == 0xF1) {
if(gb->boot_rom_finished) return;
uint8_t checksum = 0; uint8_t checksum = 0;
for (unsigned i = 2; i < 0x10; i++) { for (unsigned i = 2; i < 0x10; i++) {
checksum += gb->sgb->command[i]; checksum += gb->sgb->command[i];
@ -86,14 +157,23 @@ static void command_ready(GB_gameboy_t *gb)
gb->sgb->disable_commands = true; gb->sgb->disable_commands = true;
return; return;
} }
if (gb->sgb->command[0] == 0xf9) { unsigned index = (gb->sgb->command[0] >> 1) & 7;
if (gb->sgb->command[0xc] != 3) { // SGB Flag if (index > 5) {
gb->sgb->disable_commands = true; return;
}
} }
else if (gb->sgb->command[0] == 0xfb) { memcpy(&gb->sgb->received_header[index * 14], &gb->sgb->command[2], 14);
if (gb->sgb->command[0x3] != 0x33) { // Old licensee code if (gb->sgb->command[0] == 0xfb) {
if (gb->sgb->received_header[0x42] != 3 || gb->sgb->received_header[0x47] != 0x33) {
gb->sgb->disable_commands = true; gb->sgb->disable_commands = true;
for (unsigned i = 0; i < sizeof(palette_assignments) / sizeof(palette_assignments[0]); i++) {
if (memcmp(palette_assignments[i].name, &gb->sgb->received_header[0x30], sizeof(palette_assignments[i].name)) == 0) {
gb->sgb->effective_palettes[0] = built_in_palettes[palette_assignments[i].palette_index * 4 - 4];
gb->sgb->effective_palettes[1] = built_in_palettes[palette_assignments[i].palette_index * 4 + 1 - 4];
gb->sgb->effective_palettes[2] = built_in_palettes[palette_assignments[i].palette_index * 4 + 2 - 4];
gb->sgb->effective_palettes[3] = built_in_palettes[palette_assignments[i].palette_index * 4 + 3 - 4];
break;
}
}
} }
} }
return; return;
@ -675,10 +755,10 @@ void GB_sgb_load_default_data(GB_gameboy_t *gb)
/* Re-center */ /* Re-center */
memmove(&gb->sgb->border.map[25 * 32 + 1], &gb->sgb->border.map[25 * 32], (32 * 3 - 1) * sizeof(gb->sgb->border.map[0])); memmove(&gb->sgb->border.map[25 * 32 + 1], &gb->sgb->border.map[25 * 32], (32 * 3 - 1) * sizeof(gb->sgb->border.map[0]));
} }
gb->sgb->effective_palettes[0] = 0x639E; gb->sgb->effective_palettes[0] = built_in_palettes[0];
gb->sgb->effective_palettes[1] = 0x263A; gb->sgb->effective_palettes[1] = built_in_palettes[1];
gb->sgb->effective_palettes[2] = 0x10D4; gb->sgb->effective_palettes[2] = built_in_palettes[2];
gb->sgb->effective_palettes[3] = 0x2866; gb->sgb->effective_palettes[3] = built_in_palettes[3];
} }
static double fm_synth(double phase) static double fm_synth(double phase)

View File

@ -49,6 +49,9 @@ struct GB_sgb_s {
/* Intro */ /* Intro */
int16_t intro_animation; int16_t intro_animation;
/* GB Header */
uint8_t received_header[0x54];
}; };
void GB_sgb_write(GB_gameboy_t *gb, uint8_t value); void GB_sgb_write(GB_gameboy_t *gb, uint8_t value);