Improved emulation of SGB multiplayer, fixes #405
This commit is contained in:
parent
164a870189
commit
191f7cee02
@ -12,7 +12,7 @@ void GB_update_joyp(GB_gameboy_t *gb)
|
|||||||
previous_state = gb->io_registers[GB_IO_JOYP] & 0xF;
|
previous_state = gb->io_registers[GB_IO_JOYP] & 0xF;
|
||||||
key_selection = (gb->io_registers[GB_IO_JOYP] >> 4) & 3;
|
key_selection = (gb->io_registers[GB_IO_JOYP] >> 4) & 3;
|
||||||
gb->io_registers[GB_IO_JOYP] &= 0xF0;
|
gb->io_registers[GB_IO_JOYP] &= 0xF0;
|
||||||
uint8_t current_player = gb->sgb? (gb->sgb->current_player & (gb->sgb->player_count - 1) & 3) : 0;
|
uint8_t current_player = gb->sgb? gb->sgb->current_player : 0;
|
||||||
switch (key_selection) {
|
switch (key_selection) {
|
||||||
case 3:
|
case 3:
|
||||||
if (gb->sgb && gb->sgb->player_count > 1) {
|
if (gb->sgb && gb->sgb->player_count > 1) {
|
||||||
|
@ -355,6 +355,12 @@ static void sanitize_state(GB_gameboy_t *gb)
|
|||||||
if (gb->object_priority == GB_OBJECT_PRIORITY_UNDEFINED) {
|
if (gb->object_priority == GB_OBJECT_PRIORITY_UNDEFINED) {
|
||||||
gb->object_priority = gb->cgb_mode? GB_OBJECT_PRIORITY_INDEX : GB_OBJECT_PRIORITY_X;
|
gb->object_priority = gb->cgb_mode? GB_OBJECT_PRIORITY_INDEX : GB_OBJECT_PRIORITY_X;
|
||||||
}
|
}
|
||||||
|
if (gb->sgb) {
|
||||||
|
if (gb->sgb->player_count != 1 && gb->sgb->player_count != 2 && gb->sgb->player_count != 4) {
|
||||||
|
gb->sgb->player_count = 1;
|
||||||
|
}
|
||||||
|
gb->sgb->current_player &= gb->sgb->player_count - 1;
|
||||||
|
}
|
||||||
if (gb->sgb && !gb->sgb->v14_3) {
|
if (gb->sgb && !gb->sgb->v14_3) {
|
||||||
#ifdef GB_BIG_ENDIAN
|
#ifdef GB_BIG_ENDIAN
|
||||||
for (unsigned i = 0; i < sizeof(gb->sgb->border.raw_data) / 2; i++) {
|
for (unsigned i = 0; i < sizeof(gb->sgb->border.raw_data) / 2; i++) {
|
||||||
@ -719,7 +725,7 @@ static int save_state_internal(GB_gameboy_t *gb, virtual_file_t *file, bool appe
|
|||||||
bess_sgb.attribute_files = (BESS_buffer_t){LE32(sizeof(gb->sgb->attribute_files)),
|
bess_sgb.attribute_files = (BESS_buffer_t){LE32(sizeof(gb->sgb->attribute_files)),
|
||||||
LE32(sgb_offset + offsetof(GB_sgb_t, attribute_files))};
|
LE32(sgb_offset + offsetof(GB_sgb_t, attribute_files))};
|
||||||
|
|
||||||
bess_sgb.multiplayer_state = (gb->sgb->player_count << 4) | (gb->sgb->current_player & (gb->sgb->player_count - 1));
|
bess_sgb.multiplayer_state = (gb->sgb->player_count << 4) | gb->sgb->current_player;
|
||||||
if (file->write(file, &bess_sgb, sizeof(bess_sgb)) != sizeof(bess_sgb)) {
|
if (file->write(file, &bess_sgb, sizeof(bess_sgb)) != sizeof(bess_sgb)) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
19
Core/sgb.c
19
Core/sgb.c
@ -382,15 +382,12 @@ static void command_ready(GB_gameboy_t *gb)
|
|||||||
// Not supported, but used by almost all SGB games for hot patching, so let's mute the warning for this
|
// Not supported, but used by almost all SGB games for hot patching, so let's mute the warning for this
|
||||||
break;
|
break;
|
||||||
case MLT_REQ:
|
case MLT_REQ:
|
||||||
if (gb->sgb->player_count == 1) {
|
|
||||||
gb->sgb->current_player = 0;
|
|
||||||
}
|
|
||||||
gb->sgb->player_count = (gb->sgb->command[1] & 3) + 1; /* Todo: When breaking save state comaptibility,
|
gb->sgb->player_count = (gb->sgb->command[1] & 3) + 1; /* Todo: When breaking save state comaptibility,
|
||||||
fix this to be 0 based. */
|
fix this to be 0 based. */
|
||||||
if (gb->sgb->player_count == 3) {
|
if (gb->sgb->player_count == 3) {
|
||||||
gb->sgb->current_player++;
|
gb->sgb->player_count++;
|
||||||
}
|
}
|
||||||
gb->sgb->mlt_lock = true;
|
gb->sgb->current_player &= (gb->sgb->player_count - 1);
|
||||||
break;
|
break;
|
||||||
case CHR_TRN:
|
case CHR_TRN:
|
||||||
gb->sgb->vram_transfer_countdown = 2;
|
gb->sgb->vram_transfer_countdown = 2;
|
||||||
@ -446,18 +443,16 @@ void GB_sgb_write(GB_gameboy_t *gb, uint8_t value)
|
|||||||
command_size = SGB_PACKET_SIZE * 8;
|
command_size = SGB_PACKET_SIZE * 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((value & 0x20) == 0 && (gb->io_registers[GB_IO_JOYP] & 0x20) != 0) {
|
if ((value & 0x20) != 0 && (gb->io_registers[GB_IO_JOYP] & 0x20) == 0) {
|
||||||
gb->sgb->mlt_lock ^= true;
|
if ((gb->sgb->player_count & 1) == 0) {
|
||||||
|
gb->sgb->current_player++;
|
||||||
|
gb->sgb->current_player &= (gb->sgb->player_count - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ((value >> 4) & 3) {
|
switch ((value >> 4) & 3) {
|
||||||
case 3:
|
case 3:
|
||||||
gb->sgb->ready_for_pulse = true;
|
gb->sgb->ready_for_pulse = true;
|
||||||
if ((gb->sgb->player_count & 1) == 0 && !gb->sgb->mlt_lock) {
|
|
||||||
gb->sgb->current_player++;
|
|
||||||
gb->sgb->current_player &= 3;
|
|
||||||
gb->sgb->mlt_lock = true;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: // Zero
|
case 2: // Zero
|
||||||
|
@ -61,7 +61,7 @@ struct GB_sgb_s {
|
|||||||
uint8_t received_header[0x54];
|
uint8_t received_header[0x54];
|
||||||
|
|
||||||
/* Multiplayer (cont) */
|
/* Multiplayer (cont) */
|
||||||
bool mlt_lock;
|
GB_PADDING(bool, mlt_lock);
|
||||||
|
|
||||||
bool v14_3; // True on save states created on 0.14.3 or newer; Remove when breaking save state compatibility!
|
bool v14_3; // True on save states created on 0.14.3 or newer; Remove when breaking save state compatibility!
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user