Correct emulation of FF6C (Turns out it controls object priority)
This commit is contained in:
parent
f550360f1a
commit
08eb2f3d98
@ -939,7 +939,7 @@ void GB_display_run(GB_gameboy_t *gb, uint8_t cycles)
|
|||||||
gb->vram[line_address + 1],
|
gb->vram[line_address + 1],
|
||||||
palette,
|
palette,
|
||||||
object->flags & 0x80,
|
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);
|
object->flags & 0x20);
|
||||||
|
|
||||||
gb->n_visible_objs--;
|
gb->n_visible_objs--;
|
||||||
|
@ -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_window_related_write(GB_gameboy_t *gb, uint8_t addr, uint8_t value);
|
||||||
void GB_STAT_update(GB_gameboy_t *gb);
|
void GB_STAT_update(GB_gameboy_t *gb);
|
||||||
void GB_lcd_off(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
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -1008,11 +1008,13 @@ void GB_reset(GB_gameboy_t *gb)
|
|||||||
gb->vram_size = 0x2000 * 2;
|
gb->vram_size = 0x2000 * 2;
|
||||||
memset(gb->vram, 0, gb->vram_size);
|
memset(gb->vram, 0, gb->vram_size);
|
||||||
gb->cgb_mode = true;
|
gb->cgb_mode = true;
|
||||||
|
gb->object_priority = GB_OBJECT_PRIORITY_INDEX;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
gb->ram_size = 0x2000;
|
gb->ram_size = 0x2000;
|
||||||
gb->vram_size = 0x2000;
|
gb->vram_size = 0x2000;
|
||||||
memset(gb->vram, 0, gb->vram_size);
|
memset(gb->vram, 0, gb->vram_size);
|
||||||
|
gb->object_priority = GB_OBJECT_PRIORITY_X;
|
||||||
|
|
||||||
update_dmg_palette(gb);
|
update_dmg_palette(gb);
|
||||||
}
|
}
|
||||||
|
@ -185,7 +185,7 @@ enum {
|
|||||||
// Unfortunately it is not readable or writable after boot has finished, so research of this
|
// 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
|
// register is quite limited. The value written to this register, however, can be controlled
|
||||||
// in some cases.
|
// in some cases.
|
||||||
GB_IO_DMG_EMULATION = 0x4c,
|
GB_IO_MODE = 0x4c,
|
||||||
|
|
||||||
/* General CGB features */
|
/* General CGB features */
|
||||||
GB_IO_KEY1 = 0x4d, // CGB Mode Only - Prepare Speed Switch
|
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_BGPD = 0x69, // CGB Mode Only - Background Palette Data
|
||||||
GB_IO_OBPI = 0x6a, // CGB Mode Only - Sprite Palette Index
|
GB_IO_OBPI = 0x6a, // CGB Mode Only - Sprite Palette Index
|
||||||
GB_IO_OBPD = 0x6b, // CGB Mode Only - Sprite Palette Data
|
GB_IO_OBPD = 0x6b, // CGB Mode Only - Sprite Palette Data
|
||||||
|
GB_IO_OBJECT_PRIORITY = 0x6c, // Affects object priority (X based or index based)
|
||||||
// 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)
|
|
||||||
|
|
||||||
/* Missing */
|
/* Missing */
|
||||||
|
|
||||||
@ -516,6 +514,7 @@ struct GB_gameboy_internal_s {
|
|||||||
bool cgb_palettes_blocked;
|
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.
|
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;
|
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 */
|
/* Unsaved data. This includes all pointers, as well as everything that shouldn't be on a save state */
|
||||||
|
@ -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;
|
return gb->io_registers[GB_IO_TAC] | 0xF8;
|
||||||
case GB_IO_STAT:
|
case GB_IO_STAT:
|
||||||
return gb->io_registers[GB_IO_STAT] | 0x80;
|
return gb->io_registers[GB_IO_STAT] | 0x80;
|
||||||
case GB_IO_DMG_EMULATION_INDICATION:
|
case GB_IO_OBJECT_PRIORITY:
|
||||||
if (!gb->cgb_mode) {
|
if (!GB_is_cgb(gb)) {
|
||||||
return 0xFF;
|
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:
|
case GB_IO_PCM_12:
|
||||||
if (!GB_is_cgb(gb)) return 0xFF;
|
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_OBP1:
|
||||||
case GB_IO_WY:
|
case GB_IO_WY:
|
||||||
case GB_IO_SB:
|
case GB_IO_SB:
|
||||||
case GB_IO_DMG_EMULATION_INDICATION:
|
|
||||||
case GB_IO_UNKNOWN2:
|
case GB_IO_UNKNOWN2:
|
||||||
case GB_IO_UNKNOWN3:
|
case GB_IO_UNKNOWN3:
|
||||||
case GB_IO_UNKNOWN4:
|
case GB_IO_UNKNOWN4:
|
||||||
case GB_IO_UNKNOWN5:
|
case GB_IO_UNKNOWN5:
|
||||||
gb->io_registers[addr & 0xFF] = value;
|
gb->io_registers[addr & 0xFF] = value;
|
||||||
return;
|
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:
|
case GB_IO_LYC:
|
||||||
|
|
||||||
/* TODO: Probably completely wrong in double speed mode */
|
/* 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;
|
gb->boot_rom_finished = true;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case GB_IO_DMG_EMULATION:
|
case GB_IO_MODE:
|
||||||
if (GB_is_cgb(gb) && !gb->boot_rom_finished) {
|
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->cgb_mode = !(value & 0xC); /* The real "contents" of this register aren't quite known yet. */
|
||||||
|
gb->io_registers[GB_IO_MODE] = value;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -266,6 +266,10 @@ int GB_load_state(GB_gameboy_t *gb, const char *path)
|
|||||||
gb->oam_fifo.read_end &= 0xF;
|
gb->oam_fifo.read_end &= 0xF;
|
||||||
gb->oam_fifo.write_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:
|
error:
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return errno;
|
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.read_end &= 0xF;
|
||||||
gb->oam_fifo.write_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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
00:FF69 IO_BGPD
|
00:FF69 IO_BGPD
|
||||||
00:FF6A IO_OBPI
|
00:FF6A IO_OBPI
|
||||||
00:FF6B IO_OBPD
|
00:FF6B IO_OBPD
|
||||||
00:FF6C IO_DMG_EMULATION_INDICATION
|
00:FF6C IO_OBJECT_PRIORITY
|
||||||
00:FF70 IO_SVBK
|
00:FF70 IO_SVBK
|
||||||
00:FF72 IO_UNKNOWN2
|
00:FF72 IO_UNKNOWN2
|
||||||
00:FF73 IO_UNKNOWN3
|
00:FF73 IO_UNKNOWN3
|
||||||
|
Loading…
Reference in New Issue
Block a user