diff --git a/Core/display.c b/Core/display.c index 842c21f..521a386 100644 --- a/Core/display.c +++ b/Core/display.c @@ -939,7 +939,7 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles) gb->vram[line_address + 1], palette, object->flags & 0x80, - gb->cgb_mode? gb->visible_objs[gb->n_visible_objs - 1] : 0, + gb->object_priority == GB_OBJECT_PRIORITY_INDEX? gb->visible_objs[gb->n_visible_objs - 1] : 0, object->flags & 0x20); gb->n_visible_objs--; diff --git a/Core/display.h b/Core/display.h index 69e7905..b9e3149 100644 --- a/Core/display.h +++ b/Core/display.h @@ -11,6 +11,13 @@ void GB_palette_changed(GB_gameboy_t *gb, bool background_palette, uint8_t index void GB_window_related_write(GB_gameboy_t *gb, uint8_t addr, uint8_t value); void GB_STAT_update(GB_gameboy_t *gb); void GB_lcd_off(GB_gameboy_t *gb); + +enum { + GB_OBJECT_PRIORITY_UNDEFINED, // For save state compatibility + GB_OBJECT_PRIORITY_X, + GB_OBJECT_PRIORITY_INDEX, +}; + #endif typedef enum { diff --git a/Core/gb.c b/Core/gb.c index b0eaf68..31fff0d 100644 --- a/Core/gb.c +++ b/Core/gb.c @@ -1008,11 +1008,13 @@ void GB_reset(GB_gameboy_t *gb) gb->vram_size = 0x2000 * 2; memset(gb->vram, 0, gb->vram_size); gb->cgb_mode = true; + gb->object_priority = GB_OBJECT_PRIORITY_INDEX; } else { gb->ram_size = 0x2000; gb->vram_size = 0x2000; memset(gb->vram, 0, gb->vram_size); + gb->object_priority = GB_OBJECT_PRIORITY_X; update_dmg_palette(gb); } diff --git a/Core/gb.h b/Core/gb.h index e803f3c..b413fe5 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -185,7 +185,7 @@ enum { // Unfortunately it is not readable or writable after boot has finished, so research of this // register is quite limited. The value written to this register, however, can be controlled // in some cases. - GB_IO_DMG_EMULATION = 0x4c, + GB_IO_MODE = 0x4c, /* General CGB features */ GB_IO_KEY1 = 0x4d, // CGB Mode Only - Prepare Speed Switch @@ -212,9 +212,7 @@ enum { GB_IO_BGPD = 0x69, // CGB Mode Only - Background Palette Data GB_IO_OBPI = 0x6a, // CGB Mode Only - Sprite Palette Index GB_IO_OBPD = 0x6b, // CGB Mode Only - Sprite Palette Data - - // 1 is written for DMG ROMs on a CGB. Does not appear to have an effect. - GB_IO_DMG_EMULATION_INDICATION = 0x6c, // (FEh) Bit 0 (Read/Write) + GB_IO_OBJECT_PRIORITY = 0x6c, // Affects object priority (X based or index based) /* Missing */ @@ -516,6 +514,7 @@ struct GB_gameboy_internal_s { bool cgb_palettes_blocked; uint8_t current_lcd_line; // The LCD can go out of sync since the vsync signal is skipped in some cases. uint32_t cycles_in_stop_mode; + uint8_t object_priority; ); /* Unsaved data. This includes all pointers, as well as everything that shouldn't be on a save state */ diff --git a/Core/memory.c b/Core/memory.c index 003bb77..8e254bc 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -295,11 +295,11 @@ static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr) return gb->io_registers[GB_IO_TAC] | 0xF8; case GB_IO_STAT: return gb->io_registers[GB_IO_STAT] | 0x80; - case GB_IO_DMG_EMULATION_INDICATION: - if (!gb->cgb_mode) { + case GB_IO_OBJECT_PRIORITY: + if (!GB_is_cgb(gb)) { return 0xFF; } - return gb->io_registers[GB_IO_DMG_EMULATION_INDICATION] | 0xFE; + return gb->io_registers[GB_IO_OBJECT_PRIORITY] | 0xFE; case GB_IO_PCM_12: if (!GB_is_cgb(gb)) return 0xFF; @@ -656,13 +656,22 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value) case GB_IO_OBP1: case GB_IO_WY: case GB_IO_SB: - case GB_IO_DMG_EMULATION_INDICATION: case GB_IO_UNKNOWN2: case GB_IO_UNKNOWN3: case GB_IO_UNKNOWN4: case GB_IO_UNKNOWN5: gb->io_registers[addr & 0xFF] = value; return; + case GB_IO_OBJECT_PRIORITY: + if ((!gb->boot_rom_finished || (gb->io_registers[GB_IO_MODE] & 8)) && GB_is_cgb(gb)) { + gb->io_registers[addr & 0xFF] = value; + gb->object_priority = (value & 1) ? GB_OBJECT_PRIORITY_X : GB_OBJECT_PRIORITY_INDEX; + } + else if (gb->cgb_mode) { + gb->io_registers[addr & 0xFF] = value; + + } + return; case GB_IO_LYC: /* TODO: Probably completely wrong in double speed mode */ @@ -768,9 +777,10 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value) gb->boot_rom_finished = true; return; - case GB_IO_DMG_EMULATION: + case GB_IO_MODE: if (GB_is_cgb(gb) && !gb->boot_rom_finished) { gb->cgb_mode = !(value & 0xC); /* The real "contents" of this register aren't quite known yet. */ + gb->io_registers[GB_IO_MODE] = value; } return; diff --git a/Core/save_state.c b/Core/save_state.c index 8ef99ae..931a319 100644 --- a/Core/save_state.c +++ b/Core/save_state.c @@ -266,6 +266,10 @@ int GB_load_state(GB_gameboy_t *gb, const char *path) gb->oam_fifo.read_end &= 0xF; gb->oam_fifo.write_end &= 0xF; + if (gb->object_priority == GB_OBJECT_PRIORITY_UNDEFINED) { + gb->object_priority = gb->cgb_mode? GB_OBJECT_PRIORITY_INDEX : GB_OBJECT_PRIORITY_X; + } + error: fclose(f); return errno; @@ -371,6 +375,10 @@ int GB_load_state_from_buffer(GB_gameboy_t *gb, const uint8_t *buffer, size_t le gb->oam_fifo.read_end &= 0xF; gb->oam_fifo.write_end &= 0xF; + if (gb->object_priority == GB_OBJECT_PRIORITY_UNDEFINED) { + gb->object_priority = gb->cgb_mode? GB_OBJECT_PRIORITY_INDEX : GB_OBJECT_PRIORITY_X; + } + return 0; } diff --git a/Misc/registers.sym b/Misc/registers.sym index 3bc95bb..ea76ab3 100644 --- a/Misc/registers.sym +++ b/Misc/registers.sym @@ -55,7 +55,7 @@ 00:FF69 IO_BGPD 00:FF6A IO_OBPI 00:FF6B IO_OBPD -00:FF6C IO_DMG_EMULATION_INDICATION +00:FF6C IO_OBJECT_PRIORITY 00:FF70 IO_SVBK 00:FF72 IO_UNKNOWN2 00:FF73 IO_UNKNOWN3 @@ -64,4 +64,4 @@ 00:FF76 IO_PCM_12 00:FF77 IO_PCM_34 00:FF7F IO_UNKNOWN8 -00:FFFF IO_IE \ No newline at end of file +00:FFFF IO_IE