From 18007f0e5389d6a68488cd0130e9aeca321b0420 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Sat, 23 Oct 2021 23:28:54 +0300 Subject: [PATCH] MGB support --- BootROMs/dmg_boot.asm | 4 + BootROMs/mgb_boot.asm | 2 + Cocoa/Document.m | 8 + Cocoa/MainMenu.xib | 6 + Core/apu.c | 11 +- Core/gb.c | 29 ++- Core/gb.h | 2 +- Core/graphics/mgb_border.inc | 477 +++++++++++++++++++++++++++++++++++ Core/memory.c | 11 +- Core/save_state.c | 1 + Core/sm83_cpu.c | 2 +- Makefile | 8 +- SDL/gui.c | 2 +- SDL/gui.h | 1 + SDL/main.c | 1 + 15 files changed, 551 insertions(+), 14 deletions(-) create mode 100644 BootROMs/mgb_boot.asm create mode 100644 Core/graphics/mgb_border.inc diff --git a/BootROMs/dmg_boot.asm b/BootROMs/dmg_boot.asm index 97a12e7..5517683 100644 --- a/BootROMs/dmg_boot.asm +++ b/BootROMs/dmg_boot.asm @@ -115,7 +115,11 @@ Start: call WaitBFrames ; Set registers to match the original DMG boot +IF DEF(MGB) + ld hl, $FFB0 +ELSE ld hl, $01B0 +ENDC push hl pop af ld hl, $014D diff --git a/BootROMs/mgb_boot.asm b/BootROMs/mgb_boot.asm new file mode 100644 index 0000000..3a98aef --- /dev/null +++ b/BootROMs/mgb_boot.asm @@ -0,0 +1,2 @@ +MGB EQU 1 +include "dmg_boot.asm" \ No newline at end of file diff --git a/Cocoa/Document.m b/Cocoa/Document.m index 2a54a13..74fc98e 100644 --- a/Cocoa/Document.m +++ b/Cocoa/Document.m @@ -20,6 +20,7 @@ enum model { MODEL_CGB, MODEL_AGB, MODEL_SGB, + MODEL_MGB, }; @interface Document () @@ -245,6 +246,9 @@ static void infraredStateChanged(GB_gameboy_t *gb, bool on) return model; } + case MODEL_MGB: + return GB_MODEL_MGB; + case MODEL_AGB: return GB_MODEL_AGB; } @@ -606,6 +610,7 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency) [[NSUserDefaults standardUserDefaults] setBool:current_model == MODEL_DMG forKey:@"EmulateDMG"]; [[NSUserDefaults standardUserDefaults] setBool:current_model == MODEL_SGB forKey:@"EmulateSGB"]; [[NSUserDefaults standardUserDefaults] setBool:current_model == MODEL_AGB forKey:@"EmulateAGB"]; + [[NSUserDefaults standardUserDefaults] setBool:current_model == MODEL_MGB forKey:@"EmulateMGB"]; } /* Reload the ROM, SAV and SYM files */ @@ -779,6 +784,9 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency) else if ([[NSUserDefaults standardUserDefaults] boolForKey:@"EmulateSGB"]) { current_model = MODEL_SGB; } + else if ([[NSUserDefaults standardUserDefaults] boolForKey:@"EmulateMGB"]) { + current_model = MODEL_MGB; + } else { current_model = [[NSUserDefaults standardUserDefaults] boolForKey:@"EmulateAGB"]? MODEL_AGB : MODEL_CGB; } diff --git a/Cocoa/MainMenu.xib b/Cocoa/MainMenu.xib index 348e960..ca15de4 100644 --- a/Cocoa/MainMenu.xib +++ b/Cocoa/MainMenu.xib @@ -339,6 +339,12 @@ + + + + + + diff --git a/Core/apu.c b/Core/apu.c index 537ae01..c40ce61 100644 --- a/Core/apu.c +++ b/Core/apu.c @@ -303,11 +303,6 @@ static inline void update_wave_sample(GB_gameboy_t *gb, unsigned cycles) } } -/* the effects of NRX2 writes on current volume are not well documented and differ - between models and variants. The exact behavior can only be verified on CGB as it - requires the PCM12 register. The behavior implemented here was verified on *my* - CGB, which might behave differently from other CGB revisions, as well as from the - DMG, MGB or SGB/2 */ static void _nrx2_glitch(uint8_t *volume, uint8_t value, uint8_t old_value, uint8_t *countdown, GB_envelope_clock_t *lock) { if (lock->clock) { @@ -868,6 +863,7 @@ static inline uint16_t effective_channel4_counter(GB_gameboy_t *gb) break; #endif case GB_MODEL_DMG_B: + case GB_MODEL_MGB: case GB_MODEL_SGB_NTSC: case GB_MODEL_SGB_PAL: case GB_MODEL_SGB_NTSC_NO_SFC: @@ -1232,10 +1228,13 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) DMG-B: Most of them behave as emulated. A few behave differently. SGB: As far as I know, all tested instances behave as emulated. MGB, SGB2: Most instances behave non-deterministically, a few behave as emulated. + + For DMG-B emulation I emulate the most common behavior, which blargg's tests expect (not my own DMG-B, which fails it) + For MGB emulation, I emulate my Game Boy Light, which happens to be deterministic. Additionally, I believe DMGs, including those we behave differently than emulated, are all deterministic. */ - if (offset < 4) { + if (offset < 4 && gb->model != GB_MODEL_MGB) { gb->io_registers[GB_IO_WAV_START] = gb->io_registers[GB_IO_WAV_START + offset]; } else { diff --git a/Core/gb.c b/Core/gb.c index a845797..6bd1f50 100644 --- a/Core/gb.c +++ b/Core/gb.c @@ -125,6 +125,17 @@ static void load_default_border(GB_gameboy_t *gb) #include "graphics/agb_border.inc" LOAD_BORDER(); } + else if (gb->model == GB_MODEL_MGB) { + #include "graphics/mgb_border.inc" + LOAD_BORDER(); + if (gb->dmg_palette && + gb->dmg_palette->colors[4].b > gb->dmg_palette->colors[4].r) { + for (unsigned i = 0; i < 7; i++) { + gb->borrowed_border.map[13 + 24 * 32 + i] = i + 1; + gb->borrowed_border.map[13 + 25 * 32 + i] = i + 8; + } + } + } else if (GB_is_cgb(gb)) { #include "graphics/cgb_border.inc" LOAD_BORDER(); @@ -1420,6 +1431,7 @@ void GB_set_user_data(GB_gameboy_t *gb, void *data) static void reset_ram(GB_gameboy_t *gb) { switch (gb->model) { + case GB_MODEL_MGB: case GB_MODEL_CGB_E: case GB_MODEL_AGB: /* Unverified */ for (unsigned i = 0; i < gb->ram_size; i++) { @@ -1475,6 +1487,7 @@ static void reset_ram(GB_gameboy_t *gb) break; case GB_MODEL_DMG_B: + case GB_MODEL_MGB: case GB_MODEL_SGB_NTSC: /* Unverified*/ case GB_MODEL_SGB_PAL: /* Unverified */ case GB_MODEL_SGB_NTSC_NO_SFC: /* Unverified */ @@ -1501,6 +1514,7 @@ static void reset_ram(GB_gameboy_t *gb) break; case GB_MODEL_DMG_B: + case GB_MODEL_MGB: case GB_MODEL_SGB_NTSC: /* Unverified */ case GB_MODEL_SGB_PAL: /* Unverified */ case GB_MODEL_SGB_NTSC_NO_SFC: /* Unverified */ @@ -1528,7 +1542,17 @@ static void reset_ram(GB_gameboy_t *gb) case GB_MODEL_AGB: /* Initialized by CGB-A and newer, 0s in CGB-0*/ break; - + case GB_MODEL_MGB: { + for (unsigned i = 0; i < GB_IO_WAV_END - GB_IO_WAV_START; i++) { + if (i & 1) { + gb->io_registers[GB_IO_WAV_START + i] = GB_random() & GB_random(); + } + else { + gb->io_registers[GB_IO_WAV_START + i] = GB_random() | GB_random(); + } + } + break; + } case GB_MODEL_DMG_B: case GB_MODEL_SGB_NTSC: /* Unverified*/ case GB_MODEL_SGB_PAL: /* Unverified */ @@ -1572,6 +1596,9 @@ static void request_boot_rom(GB_gameboy_t *gb) case GB_MODEL_DMG_B: type = GB_BOOT_ROM_DMG; break; + case GB_MODEL_MGB: + type = GB_BOOT_ROM_MGB; + break; case GB_MODEL_SGB_NTSC: case GB_MODEL_SGB_PAL: case GB_MODEL_SGB_NTSC_NO_SFC: diff --git a/Core/gb.h b/Core/gb.h index ea4fe7d..0a1b358 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -127,7 +127,7 @@ typedef enum { GB_MODEL_SGB_NTSC_NO_SFC = GB_MODEL_SGB | GB_MODEL_NO_SFC_BIT, GB_MODEL_SGB_NO_SFC = GB_MODEL_SGB_NTSC_NO_SFC, GB_MODEL_SGB_PAL_NO_SFC = GB_MODEL_SGB | GB_MODEL_NO_SFC_BIT | GB_MODEL_PAL_BIT, - // GB_MODEL_MGB = 0x100, + GB_MODEL_MGB = 0x100, GB_MODEL_SGB2 = 0x101, GB_MODEL_SGB2_NO_SFC = GB_MODEL_SGB2 | GB_MODEL_NO_SFC_BIT, // GB_MODEL_CGB_0 = 0x200, diff --git a/Core/graphics/mgb_border.inc b/Core/graphics/mgb_border.inc new file mode 100644 index 0000000..f19ed8a --- /dev/null +++ b/Core/graphics/mgb_border.inc @@ -0,0 +1,477 @@ +static const uint16_t palette[] = { + 0x0000, 0x0000, 0x0011, 0x001A, 0x39CE, 0x6B5A, 0x739C, 0x5265, + 0x3DC5, 0x2924, 0x18A4, 0x20E6, 0x2D49, 0x1484, 0x5694, 0x20EC, +}; + + +static const uint16_t tilemap[] = { + 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, + 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, + 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, + 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, + 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, + 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, + 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, + 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, + 0x000F, 0x0010, 0x0011, 0x0012, 0x0012, 0x0012, 0x0012, 0x0012, + 0x0012, 0x0012, 0x0012, 0x0012, 0x0012, 0x0012, 0x0012, 0x0012, + 0x0012, 0x0012, 0x0012, 0x0012, 0x0012, 0x0012, 0x0012, 0x0012, + 0x0012, 0x0012, 0x0012, 0x0012, 0x0012, 0x4011, 0x4010, 0x000F, + 0x000F, 0x0013, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, + 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, + 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, + 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x4013, 0x000F, + 0x000F, 0x0015, 0x0014, 0x0014, 0x0014, 0x0016, 0x0017, 0x0017, + 0x0017, 0x0017, 0x0017, 0x0017, 0x0017, 0x0017, 0x0017, 0x0017, + 0x0017, 0x0017, 0x0017, 0x0017, 0x0017, 0x0017, 0x0017, 0x0017, + 0x0017, 0x0017, 0x4016, 0x0014, 0x0014, 0x0014, 0x4015, 0x000F, + 0x000F, 0x0015, 0x0014, 0x0014, 0x0014, 0x0018, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x4018, 0x0014, 0x0014, 0x0014, 0x4015, 0x000F, + 0x000F, 0x0015, 0x0014, 0x0014, 0x0014, 0x0018, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x4018, 0x0014, 0x0014, 0x0014, 0x4015, 0x000F, + 0x000F, 0x0015, 0x0014, 0x0014, 0x0014, 0x0018, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x4018, 0x0014, 0x0014, 0x0014, 0x4015, 0x000F, + 0x000F, 0x0015, 0x0014, 0x0014, 0x0014, 0x0018, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x4018, 0x0014, 0x0014, 0x0014, 0x4015, 0x000F, + 0x000F, 0x0015, 0x0014, 0x0014, 0x0014, 0x0018, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x4018, 0x0014, 0x0014, 0x0014, 0x4015, 0x000F, + 0x000F, 0x0015, 0x0019, 0x001A, 0x4019, 0x0018, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x4018, 0x0014, 0x0014, 0x0014, 0x4015, 0x000F, + 0x000F, 0x0015, 0x8019, 0x001B, 0xC019, 0x0018, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x4018, 0x0014, 0x0014, 0x0014, 0x4015, 0x000F, + 0x000F, 0x0015, 0x0014, 0x0014, 0x0014, 0x0018, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x4018, 0x0014, 0x0014, 0x0014, 0x4015, 0x000F, + 0x000F, 0x0015, 0x0014, 0x0014, 0x0014, 0x0018, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x4018, 0x0014, 0x0014, 0x0014, 0x4015, 0x000F, + 0x000F, 0x0015, 0x0014, 0x0014, 0x0014, 0x0018, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x4018, 0x0014, 0x0014, 0x0014, 0x4015, 0x000F, + 0x000F, 0x0015, 0x0014, 0x0014, 0x0014, 0x0018, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x4018, 0x0014, 0x0014, 0x0014, 0x4015, 0x000F, + 0x000F, 0x0015, 0x0014, 0x0014, 0x0014, 0x0018, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x4018, 0x0014, 0x0014, 0x0014, 0x4015, 0x000F, + 0x000F, 0x0015, 0x0014, 0x0014, 0x0014, 0x0018, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x4018, 0x0014, 0x0014, 0x0014, 0x4015, 0x000F, + 0x000F, 0x0015, 0x0014, 0x0014, 0x0014, 0x0018, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x4018, 0x0014, 0x0014, 0x0014, 0x4015, 0x000F, + 0x000F, 0x0015, 0x0014, 0x0014, 0x0014, 0x0018, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x4018, 0x0014, 0x0014, 0x0014, 0x4015, 0x000F, + 0x000F, 0x0015, 0x0014, 0x0014, 0x0014, 0x0018, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x4018, 0x0014, 0x0014, 0x0014, 0x4015, 0x000F, + 0x000F, 0x0015, 0x0014, 0x0014, 0x0014, 0x0018, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x4018, 0x0014, 0x0014, 0x0014, 0x4015, 0x000F, + 0x000F, 0x0015, 0x0014, 0x0014, 0x0014, 0x0018, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x4018, 0x0014, 0x0014, 0x0014, 0x4015, 0x000F, + 0x000F, 0x0015, 0x0014, 0x0014, 0x0014, 0x001C, 0x001D, 0x001D, + 0x001D, 0x001D, 0x001D, 0x001D, 0x001D, 0x001D, 0x001D, 0x001D, + 0x001D, 0x001D, 0x001D, 0x001D, 0x001D, 0x001D, 0x001D, 0x001D, + 0x001D, 0x001D, 0x401C, 0x0014, 0x0014, 0x0014, 0x001E, 0x000F, + 0x000F, 0x0015, 0x0014, 0x001F, 0x0020, 0x0021, 0x0022, 0x0023, + 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002A, 0x002B, + 0x002C, 0x002D, 0x002E, 0x002F, 0x0014, 0x0014, 0x0014, 0x0014, + 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0030, 0x0031, 0x000F, + 0x000F, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, + 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x0040, + 0x0041, 0x0042, 0x0043, 0x0044, 0x0014, 0x0014, 0x0014, 0x0014, + 0x0014, 0x0014, 0x0014, 0x0014, 0x0045, 0x0046, 0x000F, 0x000F, + 0x000F, 0x0047, 0x0048, 0x0049, 0x0049, 0x0049, 0x0049, 0x0049, + 0x0049, 0x0049, 0x0049, 0x0049, 0x0049, 0x0049, 0x0049, 0x0049, + 0x0049, 0x0049, 0x0049, 0x0049, 0x0049, 0x0049, 0x0049, 0x0049, + 0x0049, 0x0049, 0x004A, 0x004B, 0x004C, 0x000F, 0x000F, 0x000F, + 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, + 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, + 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, + 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, 0x000F, +}; + + + +const uint8_t tiles[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x3D, + 0x42, 0x7F, 0x81, 0xFF, 0x01, 0xFD, 0x01, + 0xFD, 0x01, 0xFF, 0x03, 0xFF, 0x03, 0xFF, + 0xFF, 0xBC, 0x7F, 0xFD, 0xFE, 0xFD, 0xFE, + 0xFD, 0xFE, 0xFD, 0xFE, 0xFF, 0xFC, 0xFF, + 0xFC, 0xFF, 0x00, 0xBF, 0x41, 0xFE, 0xC0, + 0xBF, 0xC1, 0xFF, 0x81, 0x7D, 0x03, 0x7F, + 0x01, 0x7F, 0x01, 0xFF, 0xFF, 0x3E, 0xFF, + 0xBE, 0x7F, 0xBF, 0x7E, 0xFF, 0x7E, 0x7D, + 0xFE, 0x7D, 0xFE, 0x7D, 0xFE, 0xFF, 0x00, + 0xFF, 0x00, 0xBF, 0x83, 0xBF, 0x87, 0xFC, + 0x8D, 0xED, 0x8E, 0xDB, 0xF8, 0xBF, 0xD8, + 0xFF, 0xFF, 0x3E, 0xFF, 0xBB, 0x7C, 0xB7, + 0x78, 0xAC, 0x73, 0xAD, 0x73, 0x9B, 0x67, + 0x9B, 0x67, 0xFF, 0x00, 0xB7, 0x08, 0xFF, + 0xF8, 0x3F, 0x38, 0xFF, 0x08, 0xFE, 0x01, + 0x87, 0x00, 0xFB, 0x78, 0xFF, 0xFF, 0x07, + 0xFF, 0xFB, 0x07, 0x3B, 0xC7, 0xE7, 0xFF, + 0xFE, 0xFF, 0x82, 0xFF, 0xFA, 0x87, 0xFF, + 0x00, 0xFE, 0x81, 0x5F, 0x40, 0xDE, 0xC0, + 0xFE, 0xC0, 0xE0, 0xDE, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x1E, 0xFF, 0x5E, 0xBF, + 0xDE, 0x3F, 0xDE, 0x3F, 0xC0, 0x3F, 0xFF, + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xCF, 0x30, + 0xDF, 0xEF, 0xFF, 0xCF, 0xFF, 0xC1, 0xBD, + 0x81, 0xBD, 0x81, 0xFF, 0x83, 0xFF, 0xFF, + 0x00, 0xFF, 0xCF, 0x30, 0xEF, 0x30, 0xFD, + 0x3E, 0xBD, 0x7E, 0xBD, 0x7E, 0xBF, 0x7C, + 0xFF, 0x00, 0xFF, 0x08, 0xF7, 0xF0, 0xFF, + 0xF0, 0xBF, 0xC0, 0xFF, 0x80, 0x7F, 0x00, + 0x7F, 0x00, 0xFF, 0xFF, 0x07, 0xFF, 0xF7, + 0x0F, 0xF7, 0x0F, 0xBF, 0x7F, 0xFF, 0x7F, + 0x7F, 0xFF, 0x7F, 0xFF, 0xFB, 0x07, 0xFF, + 0x03, 0xFF, 0x03, 0xFB, 0x03, 0xFB, 0x03, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFB, + 0xFC, 0xFB, 0xFC, 0xFB, 0xFC, 0xFB, 0xFC, + 0xFB, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFD, 0x01, 0xFD, 0x81, 0xFF, 0x0B, + 0xF7, 0xF3, 0xFB, 0xF7, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0x00, 0x7D, 0xFE, 0x7D, 0xFE, + 0x07, 0xFC, 0xF7, 0x0C, 0xF3, 0x0C, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x98, + 0x7B, 0x38, 0x7C, 0x1D, 0xFF, 0x0F, 0xFB, + 0x0B, 0xFD, 0x03, 0xFF, 0x00, 0xFF, 0x00, + 0xDB, 0x67, 0x5B, 0xE7, 0x7C, 0xE3, 0x6F, + 0xF0, 0x73, 0xFC, 0xFC, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x9E, 0x18, 0xFE, 0x3C, 0x5A, + 0xDC, 0xFF, 0xF9, 0xED, 0xE3, 0xBF, 0xC0, + 0xFF, 0x00, 0xFF, 0x00, 0x9A, 0xE7, 0xDA, + 0xE7, 0x1A, 0xE7, 0xFF, 0x06, 0xE5, 0x1E, + 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, + 0xFD, 0xBF, 0x81, 0xBF, 0x81, 0xBD, 0x81, + 0xFD, 0x81, 0xFF, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0xC1, 0x3E, 0xBD, 0x7E, 0xBD, 0x7E, + 0xBD, 0x7E, 0xBD, 0x7E, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0xBB, 0xC7, + 0xFF, 0x83, 0xFF, 0x83, 0x7B, 0x03, 0xFF, + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xBF, 0x7C, + 0xBB, 0x7C, 0xFB, 0x7C, 0xFB, 0x7C, 0x7B, + 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x80, 0x7F, + 0x80, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0x7F, 0xFF, 0x7F, 0xFF, 0x7F, + 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0x00, 0xFE, 0x00, 0xF9, 0x00, + 0xF7, 0x00, 0xEE, 0x00, 0xDD, 0x04, 0xDF, + 0x04, 0xBF, 0x08, 0xFF, 0x00, 0xFF, 0x01, + 0xFF, 0x07, 0xFF, 0x0F, 0xFF, 0x1F, 0xFB, + 0x3F, 0xFB, 0x3F, 0xF7, 0x7F, 0x80, 0x00, + 0x7F, 0x00, 0xFF, 0x00, 0x80, 0x00, 0x7F, + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, + 0x08, 0xFF, 0x10, 0xFF, 0x10, 0xFF, 0x10, + 0xFF, 0x10, 0xFF, 0x10, 0xFF, 0x10, 0xFF, + 0x10, 0xF7, 0x7F, 0xEF, 0x7F, 0xEF, 0x7F, + 0xEF, 0x7F, 0xEF, 0x7F, 0xEF, 0x7F, 0xEF, + 0x7F, 0xEF, 0x7F, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x10, 0xFF, 0x10, 0xFF, 0x10, 0xFF, + 0x10, 0xFF, 0x10, 0xFF, 0x10, 0xFF, 0x10, + 0xFF, 0x10, 0xEF, 0x7F, 0xEF, 0x7F, 0xEF, + 0x7F, 0xEF, 0x7F, 0xEF, 0x7F, 0xEF, 0x7F, + 0xEF, 0x7F, 0xEF, 0x7F, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xFE, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, + 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, + 0xFE, 0xFE, 0xFF, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x01, + 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xC3, 0x7E, + 0xBD, 0xFF, 0x66, 0xFF, 0x7E, 0xFF, 0x7E, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC3, 0xFF, 0x81, 0xC3, 0x18, 0x81, 0x00, + 0x00, 0x00, 0x00, 0x7E, 0xFF, 0x3C, 0xFF, + 0x00, 0x7E, 0x81, 0xBD, 0xC3, 0x42, 0xFF, + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x81, 0x00, 0xC3, 0x81, 0xFF, + 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x01, 0xFF, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x08, 0xFD, 0x12, 0xFD, 0x12, + 0xFD, 0x12, 0xFD, 0x12, 0xFB, 0x24, 0xFB, + 0x24, 0xFB, 0x24, 0xF7, 0xFE, 0xEF, 0xFC, + 0xEF, 0xFC, 0xEF, 0xFC, 0xEF, 0xFC, 0xDF, + 0xF8, 0xDF, 0xF8, 0xDF, 0xF8, 0xFF, 0x00, + 0xF0, 0x1E, 0xC0, 0x3F, 0x8D, 0x72, 0x0E, + 0xF3, 0x8F, 0xF0, 0x01, 0xFC, 0xA0, 0x1E, + 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xE0, 0xFF, + 0xC0, 0x7C, 0x9F, 0x7F, 0x9F, 0x7F, 0x87, + 0xFF, 0xC0, 0xFF, 0x00, 0xFC, 0x00, 0x78, + 0x87, 0x78, 0x87, 0xF0, 0x07, 0xF8, 0x07, + 0xE2, 0x0F, 0xE2, 0x1C, 0xFF, 0xFF, 0xFF, + 0xFE, 0xFB, 0xFC, 0x7F, 0xFC, 0xFF, 0xF8, + 0xFF, 0xF2, 0xFD, 0xF3, 0xFF, 0xE6, 0xFF, + 0x00, 0x7C, 0x02, 0xFC, 0x01, 0x3C, 0xC3, + 0x3C, 0x83, 0x3E, 0xC1, 0x3C, 0xC3, 0x18, + 0xC7, 0xFF, 0xFF, 0xFD, 0xFE, 0xFF, 0x7C, + 0xBF, 0x7E, 0xFF, 0x3E, 0xFF, 0x7C, 0xFF, + 0x3C, 0xFB, 0x3C, 0xFF, 0x00, 0x1E, 0x01, + 0x1E, 0xE1, 0x1E, 0xE3, 0x1C, 0xF3, 0x0C, + 0xE7, 0x08, 0xF7, 0x19, 0x6F, 0xFF, 0xFF, + 0xFE, 0x3F, 0xFF, 0x3F, 0xFD, 0x1E, 0xEF, + 0x1E, 0xFB, 0x8C, 0xFF, 0xDD, 0xF6, 0x49, + 0xFF, 0x00, 0x18, 0x14, 0x08, 0xE3, 0x08, + 0xE3, 0x18, 0xF7, 0x1D, 0xE2, 0x18, 0xE7, + 0xB8, 0x47, 0xFF, 0xFF, 0xEB, 0x1C, 0xFF, + 0x0C, 0xFF, 0x18, 0xEF, 0x1C, 0xFF, 0x98, + 0xFF, 0x98, 0xFF, 0x18, 0xFF, 0x00, 0x06, + 0x05, 0x02, 0xF8, 0x02, 0xF9, 0xFE, 0x01, + 0xFF, 0x00, 0x06, 0xF9, 0x04, 0xF3, 0xFF, + 0xFF, 0xFA, 0x07, 0xFF, 0x02, 0xFF, 0x07, + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0x0E, 0xFD, + 0x06, 0xFF, 0x00, 0x03, 0x00, 0x01, 0xFF, + 0x30, 0xCF, 0x70, 0x8F, 0x30, 0xC6, 0x21, + 0xDC, 0x01, 0xFE, 0xFF, 0xFF, 0xFF, 0x0F, + 0xFE, 0x01, 0xFF, 0x01, 0xF7, 0x39, 0xFF, + 0x79, 0xFF, 0x01, 0xFF, 0x03, 0xFF, 0x00, + 0xF8, 0x01, 0xF0, 0x1F, 0xE1, 0x3E, 0x83, + 0x78, 0x87, 0x30, 0xCF, 0x30, 0x8F, 0x70, + 0xFF, 0xFF, 0xFF, 0xFD, 0xEF, 0xF8, 0xDF, + 0xE0, 0xBF, 0xC3, 0xFF, 0x87, 0xFF, 0x8F, + 0xFF, 0x9F, 0xFF, 0x00, 0x3C, 0xA0, 0x0C, + 0xE1, 0x07, 0xF0, 0x86, 0x38, 0xC7, 0x3C, + 0xC3, 0x18, 0xC7, 0x3C, 0xFF, 0xFF, 0xDF, + 0xBE, 0xFF, 0x0C, 0xFF, 0x06, 0xFF, 0x87, + 0xFB, 0xE7, 0xFF, 0xC7, 0xFB, 0xE7, 0xFF, + 0x00, 0x7C, 0x40, 0x78, 0x83, 0x39, 0xEE, + 0x19, 0xE7, 0x81, 0x7C, 0x03, 0x78, 0xC7, + 0x38, 0xFF, 0xFF, 0xBF, 0x7E, 0xFF, 0x38, + 0xD7, 0x38, 0xFE, 0x31, 0xFF, 0x13, 0xFF, + 0x83, 0xFF, 0x8F, 0xFF, 0x00, 0x3C, 0x43, + 0x7C, 0x83, 0xFC, 0x03, 0xFC, 0x03, 0xFC, + 0x03, 0xFD, 0x02, 0xFC, 0x03, 0xFF, 0xFF, + 0xBF, 0x7C, 0xFF, 0xFC, 0xFF, 0xFC, 0xFF, + 0xFC, 0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFD, + 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x04, + 0xA3, 0xFD, 0xB6, 0x8C, 0x3A, 0x8B, 0x7C, + 0x99, 0x62, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0xF8, 0x4B, 0xFC, 0xF7, 0xCC, + 0xF3, 0xCD, 0xFF, 0xCB, 0xFF, 0x00, 0x00, + 0xFF, 0x00, 0xFF, 0x90, 0x3F, 0xD8, 0x46, + 0x09, 0xF6, 0x0D, 0xF1, 0x12, 0xF4, 0xFF, + 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xCF, 0x78, + 0xBF, 0xD9, 0x7F, 0x9F, 0xFE, 0x9B, 0xEF, + 0x9B, 0xFF, 0x00, 0x00, 0xFC, 0x02, 0xFC, + 0x46, 0x59, 0x13, 0xAC, 0x82, 0x68, 0x07, + 0xFC, 0x14, 0xE8, 0xFF, 0xFF, 0xFF, 0x03, + 0xFF, 0x02, 0xBF, 0x73, 0x5F, 0xB6, 0xFF, + 0x23, 0xFB, 0x07, 0xFF, 0x26, 0xFF, 0x00, + 0x00, 0xFF, 0x00, 0xFF, 0x03, 0x9F, 0x21, + 0x55, 0x48, 0xB7, 0x8F, 0x60, 0x80, 0x6F, + 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFC, + 0x27, 0xBA, 0xCD, 0x7F, 0x9D, 0xFF, 0x8F, + 0xF7, 0xD8, 0xFF, 0x00, 0x00, 0xFF, 0x0C, + 0xF3, 0x18, 0xF3, 0xD8, 0x2F, 0x90, 0x67, + 0xB0, 0x4F, 0x10, 0xEF, 0xFF, 0xFF, 0xFF, + 0x08, 0xFF, 0x18, 0xEF, 0xBC, 0xF7, 0xBC, + 0xFF, 0xD0, 0xFF, 0xD8, 0xFF, 0x30, 0xFF, + 0x00, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, + 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, + 0x80, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x7F, + 0xFF, 0x7F, 0xFF, 0x7F, 0xFF, 0x7F, 0xFF, + 0x7F, 0xFF, 0x7F, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0xFF, + 0x02, 0xFF, 0x04, 0xFF, 0x08, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFD, 0xFF, 0xFB, 0xFF, 0xF7, 0xFF, + 0xF7, 0x48, 0xF7, 0x48, 0xEF, 0x90, 0xEF, + 0x90, 0xDF, 0x20, 0xBF, 0x40, 0xBF, 0x40, + 0x7F, 0x80, 0xBF, 0xF0, 0xBF, 0xF0, 0x7F, + 0xE0, 0x7F, 0xE0, 0xFF, 0xC0, 0xFF, 0x80, + 0xFF, 0x80, 0xFF, 0x00, 0xFF, 0x10, 0xFF, + 0x10, 0xFF, 0x10, 0xFF, 0x10, 0xFF, 0x10, + 0xFF, 0x10, 0xFF, 0x10, 0xBF, 0x48, 0xEF, + 0x7F, 0xEF, 0x7F, 0xEF, 0x7F, 0xEF, 0x7F, + 0xEF, 0x7F, 0xEF, 0x7F, 0xEF, 0x7F, 0xF7, + 0x3F, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFE, 0x00, 0xFE, 0x01, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x0F, + 0xF8, 0x07, 0x00, 0x57, 0x01, 0xFF, 0x05, + 0xF8, 0x87, 0x48, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0xF8, 0xFF, 0xFC, 0xEF, 0x99, 0xFE, + 0x01, 0xFF, 0x83, 0xB7, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xC0, 0x3F, 0x80, 0x7F, 0x80, + 0x7F, 0x0F, 0x70, 0x8F, 0x70, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xE7, 0xBF, + 0xC0, 0xFF, 0xCF, 0xFF, 0x9F, 0xEF, 0x1F, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x18, + 0xE3, 0x18, 0xE3, 0x98, 0x77, 0x08, 0x67, + 0x1D, 0xE2, 0xFF, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0x3C, 0xFF, 0x18, 0xEF, 0x1C, + 0xFF, 0x0C, 0x7F, 0x88, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x01, 0x3E, 0xC2, 0xFF, + 0xC2, 0x3C, 0xE2, 0x18, 0xC6, 0x39, 0xFF, + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x8B, + 0x3C, 0xC3, 0xFF, 0xC7, 0xFF, 0xC6, 0xFF, + 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x18, 0xEF, 0x10, 0xE6, 0x10, 0xC6, 0x30, + 0xEF, 0x30, 0xCF, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xF7, 0x39, 0xFF, 0x39, 0xFF, + 0x10, 0xDF, 0x38, 0xFF, 0x38, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x0C, 0x09, 0xFC, + 0x01, 0x0C, 0x0B, 0x04, 0xFB, 0x06, 0xF1, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xF7, + 0x0E, 0xFF, 0xFC, 0xF7, 0x0E, 0xFF, 0x0E, + 0xFF, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x00, 0xCE, 0x70, 0xCF, 0x70, 0xFE, + 0x01, 0xFE, 0x0B, 0xF0, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0x00, 0xFF, 0x69, 0xB7, 0x79, + 0x8F, 0x79, 0xFF, 0x03, 0xFF, 0x03, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0x70, + 0x87, 0x78, 0x88, 0x72, 0x80, 0x7F, 0xC0, + 0x3F, 0xFC, 0x05, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x9F, 0xF7, 0x8F, 0xFD, 0xC7, 0xBF, + 0xC0, 0xDF, 0xF0, 0xFA, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xE7, 0x18, 0x87, 0x38, 0x17, + 0xE8, 0x1F, 0xF0, 0x3F, 0xC0, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xC7, 0xFF, + 0x8F, 0xF7, 0x8F, 0xEF, 0x1F, 0xFF, 0x7F, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, + 0x78, 0x8F, 0x70, 0xDF, 0x20, 0x8F, 0x70, + 0x8F, 0x70, 0xFF, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0xF7, 0xCF, 0xFF, 0xCF, 0xFF, 0x8F, + 0xFF, 0x9F, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFC, 0x02, 0xFD, 0x03, + 0xFD, 0x02, 0xFF, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFC, + 0xFE, 0xFD, 0xFF, 0xFD, 0xFF, 0xFD, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x9F, 0x30, 0xA0, 0x9E, 0x00, 0x7F, 0x00, + 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xEF, 0xF9, 0x6F, 0xF8, 0xFF, + 0x00, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x90, 0xCF, 0xE1, + 0x1E, 0x40, 0xBF, 0x00, 0xFF, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x7C, + 0xDB, 0xFF, 0xF3, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x3D, 0x82, 0x86, 0x79, 0x80, 0x7F, + 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0x00, 0xFF, 0xA6, 0xBF, 0xEC, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x88, 0x27, + 0xD6, 0xA0, 0x00, 0xFF, 0x00, 0xFF, 0xFF, + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFE, 0xDF, 0x7F, 0xCE, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x18, 0x47, 0x10, 0xC7, 0x00, + 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x10, 0xFF, + 0x18, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, + 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0x7F, 0xFF, 0x7F, 0xFF, 0x7F, + 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0xFF, + 0x02, 0xFF, 0x0C, 0xFF, 0x10, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFD, 0xFF, 0xF3, 0xFF, 0xEF, 0xFF, + 0xFE, 0x11, 0xFD, 0x22, 0xFB, 0x44, 0xF7, + 0x88, 0xEF, 0x10, 0xDF, 0x20, 0xBF, 0x40, + 0x7F, 0x80, 0xEF, 0xFE, 0xDF, 0xFC, 0xBF, + 0xF8, 0x7F, 0xF0, 0xFF, 0xE0, 0xFF, 0xC0, + 0xFF, 0x80, 0xFF, 0x00, 0xBF, 0x48, 0xDF, + 0x24, 0xDF, 0x22, 0xEF, 0x11, 0xF7, 0x08, + 0xF9, 0x06, 0xFE, 0x01, 0xFF, 0x00, 0xF7, + 0x3F, 0xFB, 0x1F, 0xFD, 0x1F, 0xFE, 0x0F, + 0xFF, 0x07, 0xFF, 0x01, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x80, 0xFF, 0x7F, 0xFF, 0x00, 0x7F, + 0x80, 0x80, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0x7F, 0xFF, 0x80, 0xFF, 0xFF, + 0xFF, 0xFF, 0x7F, 0xFF, 0x00, 0xFF, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, + 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0x03, 0xFF, 0xFC, 0xFF, 0x00, + 0xFC, 0x03, 0x03, 0xFC, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0x03, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0x03, 0xFF, 0x1C, 0xFF, 0xE0, + 0xFC, 0x03, 0xE3, 0x1C, 0x1F, 0xE0, 0xFF, + 0x00, 0xFF, 0xFF, 0xFC, 0xFF, 0xE3, 0xFF, + 0x1F, 0xFF, 0xFF, 0xFC, 0xFF, 0xE0, 0xFF, + 0x00, 0xFF, 0x00, 0xFC, 0xE3, 0xF3, 0x0C, + 0xEF, 0x10, 0x1F, 0xE0, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x1F, 0xFC, + 0xFF, 0xF0, 0xFF, 0xE0, 0xFF, 0x00, 0xFF, + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, +}; diff --git a/Core/memory.c b/Core/memory.c index 1720356..297656c 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -206,7 +206,11 @@ void GB_trigger_oam_bug_read(GB_gameboy_t *gb, uint16_t address) } else if ((gb->accessed_oam_row & 0x18) == 0x00) { /* Everything in this specific case is *extremely* revision and instance specific. */ - if (gb->accessed_oam_row == 0x40) { + if (gb->model == GB_MODEL_MGB) { + /* TODO: This is rather simplified, research further */ + oam_bug_tertiary_read_corruption(gb, bitwise_glitch_tertiary_read_3); + } + else if (gb->accessed_oam_row == 0x40) { oam_bug_quaternary_read_corruption(gb, ((gb->model & ~GB_MODEL_NO_SFC_BIT) == GB_MODEL_SGB2)? bitwise_glitch_quaternary_read_sgb2: @@ -240,6 +244,9 @@ void GB_trigger_oam_bug_read(GB_gameboy_t *gb, uint16_t address) if (gb->accessed_oam_row == 0x80) { memcpy(gb->oam, gb->oam + gb->accessed_oam_row, 8); } + else if (gb->model == GB_MODEL_MGB && gb->accessed_oam_row == 0x40) { + memcpy(gb->oam, gb->oam + gb->accessed_oam_row, 8); + } } } } @@ -507,6 +514,7 @@ static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr) return gb->extra_oam[addr - 0xfea0]; case GB_MODEL_DMG_B: + case GB_MODEL_MGB: case GB_MODEL_SGB_NTSC: case GB_MODEL_SGB_PAL: case GB_MODEL_SGB_NTSC_NO_SFC: @@ -1015,6 +1023,7 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value) gb->extra_oam[addr - 0xfea0] = value; break; case GB_MODEL_DMG_B: + case GB_MODEL_MGB: case GB_MODEL_SGB_NTSC: case GB_MODEL_SGB_PAL: case GB_MODEL_SGB_NTSC_NO_SFC: diff --git a/Core/save_state.c b/Core/save_state.c index 6e7ca9d..cdbde2b 100644 --- a/Core/save_state.c +++ b/Core/save_state.c @@ -580,6 +580,7 @@ static int save_state_internal(GB_gameboy_t *gb, virtual_file_t *file, bool appe switch (gb->model) { case GB_MODEL_DMG_B: bess_core.full_model = BE32('GDB '); break; + case GB_MODEL_MGB: bess_core.full_model = BE32('GM '); break; case GB_MODEL_SGB_NTSC: case GB_MODEL_SGB_NTSC_NO_SFC: diff --git a/Core/sm83_cpu.c b/Core/sm83_cpu.c index a918081..92adf46 100644 --- a/Core/sm83_cpu.c +++ b/Core/sm83_cpu.c @@ -207,7 +207,7 @@ static void cycle_write(GB_gameboy_t *gb, uint16_t addr, uint8_t value) uint8_t old_value = GB_read_memory(gb, addr); GB_advance_cycles(gb, gb->pending_cycles - 2); - if (/* gb->model != GB_MODEL_MGB && */ gb->position_in_line == 0 && (old_value & 2) && !(value & 2)) { + if (gb->model != GB_MODEL_MGB && gb->position_in_line == 0 && (old_value & 2) && !(value & 2)) { old_value &= ~2; } diff --git a/Makefile b/Makefile index 7bfe580..fadc025 100644 --- a/Makefile +++ b/Makefile @@ -199,9 +199,9 @@ endif cocoa: $(BIN)/SameBoy.app quicklook: $(BIN)/SameBoy.qlgenerator -sdl: $(SDL_TARGET) $(BIN)/SDL/dmg_boot.bin $(BIN)/SDL/cgb_boot.bin $(BIN)/SDL/agb_boot.bin $(BIN)/SDL/sgb_boot.bin $(BIN)/SDL/sgb2_boot.bin $(BIN)/SDL/LICENSE $(BIN)/SDL/registers.sym $(BIN)/SDL/background.bmp $(BIN)/SDL/Shaders -bootroms: $(BIN)/BootROMs/agb_boot.bin $(BIN)/BootROMs/cgb_boot.bin $(BIN)/BootROMs/dmg_boot.bin $(BIN)/BootROMs/sgb_boot.bin $(BIN)/BootROMs/sgb2_boot.bin -tester: $(TESTER_TARGET) $(BIN)/tester/dmg_boot.bin $(BIN)/tester/cgb_boot.bin $(BIN)/tester/agb_boot.bin $(BIN)/tester/sgb_boot.bin $(BIN)/tester/sgb2_boot.bin +sdl: $(SDL_TARGET) $(BIN)/SDL/dmg_boot.bin $(BIN)/SDL/mgb_boot.bin $(BIN)/SDL/cgb_boot.bin $(BIN)/SDL/agb_boot.bin $(BIN)/SDL/sgb_boot.bin $(BIN)/SDL/sgb2_boot.bin $(BIN)/SDL/LICENSE $(BIN)/SDL/registers.sym $(BIN)/SDL/background.bmp $(BIN)/SDL/Shaders +bootroms: $(BIN)/BootROMs/agb_boot.bin $(BIN)/BootROMs/mgb_boot.bin $(BIN)/BootROMs/cgb_boot.bin $(BIN)/BootROMs/dmg_boot.bin $(BIN)/BootROMs/sgb_boot.bin $(BIN)/BootROMs/sgb2_boot.bin +tester: $(TESTER_TARGET) $(BIN)/tester/dmg_boot.bin $(BIN)/tester/mgb_boot.bin $(BIN)/tester/cgb_boot.bin $(BIN)/tester/agb_boot.bin $(BIN)/tester/sgb_boot.bin $(BIN)/tester/sgb2_boot.bin all: cocoa sdl tester libretro # Get a list of our source files and their respective object file targets @@ -279,6 +279,7 @@ $(BIN)/SameBoy.app: $(BIN)/SameBoy.app/Contents/MacOS/SameBoy \ Cocoa/Info.plist \ Misc/registers.sym \ $(BIN)/SameBoy.app/Contents/Resources/dmg_boot.bin \ + $(BIN)/SameBoy.app/Contents/Resources/mgb_boot.bin \ $(BIN)/SameBoy.app/Contents/Resources/cgb_boot.bin \ $(BIN)/SameBoy.app/Contents/Resources/agb_boot.bin \ $(BIN)/SameBoy.app/Contents/Resources/sgb_boot.bin \ @@ -417,6 +418,7 @@ $(OBJ)/BootROMs/SameBoyLogo.pb12: $(OBJ)/BootROMs/SameBoyLogo.2bpp $(PB12_COMPRE $(PB12_COMPRESS): BootROMs/pb12.c $(NATIVE_CC) -std=c99 -Wall -Werror $< -o $@ +$(BIN)/BootROMs/mgb_boot.bin: BootROMs/mgb_boot.asm $(BIN)/BootROMs/agb_boot.bin: BootROMs/cgb_boot.asm $(BIN)/BootROMs/cgb_boot_fast.bin: BootROMs/cgb_boot.asm $(BIN)/BootROMs/sgb2_boot: BootROMs/sgb_boot.asm diff --git a/SDL/gui.c b/SDL/gui.c index 6bccd87..d6afe60 100644 --- a/SDL/gui.c +++ b/SDL/gui.c @@ -388,7 +388,7 @@ static void cycle_model_backwards(unsigned index) const char *current_model_string(unsigned index) { - return (const char *[]){"Game Boy", "Game Boy Color", "Game Boy Advance", "Super Game Boy"} + return (const char *[]){"Game Boy", "Game Boy Color", "Game Boy Advance", "Super Game Boy", "Game Boy Pocket"} [configuration.model]; } diff --git a/SDL/gui.h b/SDL/gui.h index 1764c8b..1fe8a54 100644 --- a/SDL/gui.h +++ b/SDL/gui.h @@ -88,6 +88,7 @@ typedef struct { MODEL_CGB, MODEL_AGB, MODEL_SGB, + MODEL_MGB, MODEL_MAX, } model; diff --git a/SDL/main.c b/SDL/main.c index c0fd186..2e9911e 100644 --- a/SDL/main.c +++ b/SDL/main.c @@ -623,6 +623,7 @@ restart: [MODEL_DMG] = GB_MODEL_DMG_B, [MODEL_CGB] = GB_MODEL_CGB_E, [MODEL_AGB] = GB_MODEL_AGB, + [MODEL_MGB] = GB_MODEL_MGB, [MODEL_SGB] = (GB_model_t []) { [SGB_NTSC] = GB_MODEL_SGB_NTSC,