MGB support

This commit is contained in:
Lior Halphon 2021-10-23 23:28:54 +03:00
parent 5808d4485f
commit 18007f0e53
15 changed files with 551 additions and 14 deletions

View File

@ -115,7 +115,11 @@ Start:
call WaitBFrames call WaitBFrames
; Set registers to match the original DMG boot ; Set registers to match the original DMG boot
IF DEF(MGB)
ld hl, $FFB0
ELSE
ld hl, $01B0 ld hl, $01B0
ENDC
push hl push hl
pop af pop af
ld hl, $014D ld hl, $014D

2
BootROMs/mgb_boot.asm Normal file
View File

@ -0,0 +1,2 @@
MGB EQU 1
include "dmg_boot.asm"

View File

@ -20,6 +20,7 @@ enum model {
MODEL_CGB, MODEL_CGB,
MODEL_AGB, MODEL_AGB,
MODEL_SGB, MODEL_SGB,
MODEL_MGB,
}; };
@interface Document () @interface Document ()
@ -245,6 +246,9 @@ static void infraredStateChanged(GB_gameboy_t *gb, bool on)
return model; return model;
} }
case MODEL_MGB:
return GB_MODEL_MGB;
case MODEL_AGB: case MODEL_AGB:
return GB_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_DMG forKey:@"EmulateDMG"];
[[NSUserDefaults standardUserDefaults] setBool:current_model == MODEL_SGB forKey:@"EmulateSGB"]; [[NSUserDefaults standardUserDefaults] setBool:current_model == MODEL_SGB forKey:@"EmulateSGB"];
[[NSUserDefaults standardUserDefaults] setBool:current_model == MODEL_AGB forKey:@"EmulateAGB"]; [[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 */ /* 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"]) { else if ([[NSUserDefaults standardUserDefaults] boolForKey:@"EmulateSGB"]) {
current_model = MODEL_SGB; current_model = MODEL_SGB;
} }
else if ([[NSUserDefaults standardUserDefaults] boolForKey:@"EmulateMGB"]) {
current_model = MODEL_MGB;
}
else { else {
current_model = [[NSUserDefaults standardUserDefaults] boolForKey:@"EmulateAGB"]? MODEL_AGB : MODEL_CGB; current_model = [[NSUserDefaults standardUserDefaults] boolForKey:@"EmulateAGB"]? MODEL_AGB : MODEL_CGB;
} }

View File

@ -339,6 +339,12 @@
<action selector="reset:" target="-1" id="rxG-cz-s1S"/> <action selector="reset:" target="-1" id="rxG-cz-s1S"/>
</connections> </connections>
</menuItem> </menuItem>
<menuItem title="Game Boy Pocket/Light" tag="5" id="1bM-CT-hoW">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="reset:" target="-1" id="U7l-BM-kB1"/>
</connections>
</menuItem>
<menuItem title="Super Game Boy" tag="4" id="vc7-yy-ARW"> <menuItem title="Super Game Boy" tag="4" id="vc7-yy-ARW">
<modifierMask key="keyEquivalentModifierMask"/> <modifierMask key="keyEquivalentModifierMask"/>
<connections> <connections>

View File

@ -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) 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) { if (lock->clock) {
@ -868,6 +863,7 @@ static inline uint16_t effective_channel4_counter(GB_gameboy_t *gb)
break; break;
#endif #endif
case GB_MODEL_DMG_B: case GB_MODEL_DMG_B:
case GB_MODEL_MGB:
case GB_MODEL_SGB_NTSC: case GB_MODEL_SGB_NTSC:
case GB_MODEL_SGB_PAL: case GB_MODEL_SGB_PAL:
case GB_MODEL_SGB_NTSC_NO_SFC: case GB_MODEL_SGB_NTSC_NO_SFC:
@ -1233,9 +1229,12 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value)
SGB: As far as I know, all tested instances behave as emulated. SGB: As far as I know, all tested instances behave as emulated.
MGB, SGB2: Most instances behave non-deterministically, a few 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, Additionally, I believe DMGs, including those we behave differently than emulated,
are all deterministic. */ 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]; gb->io_registers[GB_IO_WAV_START] = gb->io_registers[GB_IO_WAV_START + offset];
} }
else { else {

View File

@ -125,6 +125,17 @@ static void load_default_border(GB_gameboy_t *gb)
#include "graphics/agb_border.inc" #include "graphics/agb_border.inc"
LOAD_BORDER(); 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)) { else if (GB_is_cgb(gb)) {
#include "graphics/cgb_border.inc" #include "graphics/cgb_border.inc"
LOAD_BORDER(); 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) static void reset_ram(GB_gameboy_t *gb)
{ {
switch (gb->model) { switch (gb->model) {
case GB_MODEL_MGB:
case GB_MODEL_CGB_E: case GB_MODEL_CGB_E:
case GB_MODEL_AGB: /* Unverified */ case GB_MODEL_AGB: /* Unverified */
for (unsigned i = 0; i < gb->ram_size; i++) { for (unsigned i = 0; i < gb->ram_size; i++) {
@ -1475,6 +1487,7 @@ static void reset_ram(GB_gameboy_t *gb)
break; break;
case GB_MODEL_DMG_B: case GB_MODEL_DMG_B:
case GB_MODEL_MGB:
case GB_MODEL_SGB_NTSC: /* Unverified*/ case GB_MODEL_SGB_NTSC: /* Unverified*/
case GB_MODEL_SGB_PAL: /* Unverified */ case GB_MODEL_SGB_PAL: /* Unverified */
case GB_MODEL_SGB_NTSC_NO_SFC: /* Unverified */ case GB_MODEL_SGB_NTSC_NO_SFC: /* Unverified */
@ -1501,6 +1514,7 @@ static void reset_ram(GB_gameboy_t *gb)
break; break;
case GB_MODEL_DMG_B: case GB_MODEL_DMG_B:
case GB_MODEL_MGB:
case GB_MODEL_SGB_NTSC: /* Unverified */ case GB_MODEL_SGB_NTSC: /* Unverified */
case GB_MODEL_SGB_PAL: /* Unverified */ case GB_MODEL_SGB_PAL: /* Unverified */
case GB_MODEL_SGB_NTSC_NO_SFC: /* 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: case GB_MODEL_AGB:
/* Initialized by CGB-A and newer, 0s in CGB-0*/ /* Initialized by CGB-A and newer, 0s in CGB-0*/
break; 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_DMG_B:
case GB_MODEL_SGB_NTSC: /* Unverified*/ case GB_MODEL_SGB_NTSC: /* Unverified*/
case GB_MODEL_SGB_PAL: /* 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: case GB_MODEL_DMG_B:
type = GB_BOOT_ROM_DMG; type = GB_BOOT_ROM_DMG;
break; break;
case GB_MODEL_MGB:
type = GB_BOOT_ROM_MGB;
break;
case GB_MODEL_SGB_NTSC: case GB_MODEL_SGB_NTSC:
case GB_MODEL_SGB_PAL: case GB_MODEL_SGB_PAL:
case GB_MODEL_SGB_NTSC_NO_SFC: case GB_MODEL_SGB_NTSC_NO_SFC:

View File

@ -127,7 +127,7 @@ typedef enum {
GB_MODEL_SGB_NTSC_NO_SFC = GB_MODEL_SGB | GB_MODEL_NO_SFC_BIT, 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_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_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 = 0x101,
GB_MODEL_SGB2_NO_SFC = GB_MODEL_SGB2 | GB_MODEL_NO_SFC_BIT, GB_MODEL_SGB2_NO_SFC = GB_MODEL_SGB2 | GB_MODEL_NO_SFC_BIT,
// GB_MODEL_CGB_0 = 0x200, // GB_MODEL_CGB_0 = 0x200,

View File

@ -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,
};

View File

@ -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) { else if ((gb->accessed_oam_row & 0x18) == 0x00) {
/* Everything in this specific case is *extremely* revision and instance specific. */ /* 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, oam_bug_quaternary_read_corruption(gb,
((gb->model & ~GB_MODEL_NO_SFC_BIT) == GB_MODEL_SGB2)? ((gb->model & ~GB_MODEL_NO_SFC_BIT) == GB_MODEL_SGB2)?
bitwise_glitch_quaternary_read_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) { if (gb->accessed_oam_row == 0x80) {
memcpy(gb->oam, gb->oam + gb->accessed_oam_row, 8); 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]; return gb->extra_oam[addr - 0xfea0];
case GB_MODEL_DMG_B: case GB_MODEL_DMG_B:
case GB_MODEL_MGB:
case GB_MODEL_SGB_NTSC: case GB_MODEL_SGB_NTSC:
case GB_MODEL_SGB_PAL: case GB_MODEL_SGB_PAL:
case GB_MODEL_SGB_NTSC_NO_SFC: 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; gb->extra_oam[addr - 0xfea0] = value;
break; break;
case GB_MODEL_DMG_B: case GB_MODEL_DMG_B:
case GB_MODEL_MGB:
case GB_MODEL_SGB_NTSC: case GB_MODEL_SGB_NTSC:
case GB_MODEL_SGB_PAL: case GB_MODEL_SGB_PAL:
case GB_MODEL_SGB_NTSC_NO_SFC: case GB_MODEL_SGB_NTSC_NO_SFC:

View File

@ -580,6 +580,7 @@ static int save_state_internal(GB_gameboy_t *gb, virtual_file_t *file, bool appe
switch (gb->model) { switch (gb->model) {
case GB_MODEL_DMG_B: bess_core.full_model = BE32('GDB '); break; 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:
case GB_MODEL_SGB_NTSC_NO_SFC: case GB_MODEL_SGB_NTSC_NO_SFC:

View File

@ -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); uint8_t old_value = GB_read_memory(gb, addr);
GB_advance_cycles(gb, gb->pending_cycles - 2); 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; old_value &= ~2;
} }

View File

@ -199,9 +199,9 @@ endif
cocoa: $(BIN)/SameBoy.app cocoa: $(BIN)/SameBoy.app
quicklook: $(BIN)/SameBoy.qlgenerator 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 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/cgb_boot.bin $(BIN)/BootROMs/dmg_boot.bin $(BIN)/BootROMs/sgb_boot.bin $(BIN)/BootROMs/sgb2_boot.bin 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/cgb_boot.bin $(BIN)/tester/agb_boot.bin $(BIN)/tester/sgb_boot.bin $(BIN)/tester/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 all: cocoa sdl tester libretro
# Get a list of our source files and their respective object file targets # 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 \ Cocoa/Info.plist \
Misc/registers.sym \ Misc/registers.sym \
$(BIN)/SameBoy.app/Contents/Resources/dmg_boot.bin \ $(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/cgb_boot.bin \
$(BIN)/SameBoy.app/Contents/Resources/agb_boot.bin \ $(BIN)/SameBoy.app/Contents/Resources/agb_boot.bin \
$(BIN)/SameBoy.app/Contents/Resources/sgb_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 $(PB12_COMPRESS): BootROMs/pb12.c
$(NATIVE_CC) -std=c99 -Wall -Werror $< -o $@ $(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/agb_boot.bin: BootROMs/cgb_boot.asm
$(BIN)/BootROMs/cgb_boot_fast.bin: BootROMs/cgb_boot.asm $(BIN)/BootROMs/cgb_boot_fast.bin: BootROMs/cgb_boot.asm
$(BIN)/BootROMs/sgb2_boot: BootROMs/sgb_boot.asm $(BIN)/BootROMs/sgb2_boot: BootROMs/sgb_boot.asm

View File

@ -388,7 +388,7 @@ static void cycle_model_backwards(unsigned index)
const char *current_model_string(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]; [configuration.model];
} }

View File

@ -88,6 +88,7 @@ typedef struct {
MODEL_CGB, MODEL_CGB,
MODEL_AGB, MODEL_AGB,
MODEL_SGB, MODEL_SGB,
MODEL_MGB,
MODEL_MAX, MODEL_MAX,
} model; } model;

View File

@ -623,6 +623,7 @@ restart:
[MODEL_DMG] = GB_MODEL_DMG_B, [MODEL_DMG] = GB_MODEL_DMG_B,
[MODEL_CGB] = GB_MODEL_CGB_E, [MODEL_CGB] = GB_MODEL_CGB_E,
[MODEL_AGB] = GB_MODEL_AGB, [MODEL_AGB] = GB_MODEL_AGB,
[MODEL_MGB] = GB_MODEL_MGB,
[MODEL_SGB] = (GB_model_t []) [MODEL_SGB] = (GB_model_t [])
{ {
[SGB_NTSC] = GB_MODEL_SGB_NTSC, [SGB_NTSC] = GB_MODEL_SGB_NTSC,