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],
|
||||
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--;
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user