CDROM: Add randomness to repeated seek times

I hate it, but it fixes lockups in Dino Crisis 2, and probably
other games with dodgy code too.

Also Simple 1500 Series Vol. 57 - The Meiro.
pull/3374/head
Stenzek 2 weeks ago
parent 2f5c4d819e
commit 6f25cf31a7
No known key found for this signature in database

@ -25,6 +25,7 @@
#include "common/gsvector.h"
#include "common/heap_array.h"
#include "common/log.h"
#include "common/xorshift_prng.h"
#include "fmt/format.h"
#include "imgui.h"
@ -52,6 +53,7 @@ enum : u32
XA_RESAMPLE_RING_BUFFER_SIZE = 32,
XA_RESAMPLE_ZIGZAG_TABLE_SIZE = 29,
XA_RESAMPLE_NUM_ZIGZAG_TABLES = 7,
PRNG_SEED = 0x4B435544u,
PARAM_FIFO_SIZE = 16,
RESPONSE_FIFO_SIZE = 16,
@ -460,6 +462,8 @@ struct CDROMState
InlineFIFOQueue<u8, RESPONSE_FIFO_SIZE> response_fifo;
InlineFIFOQueue<u8, RESPONSE_FIFO_SIZE> async_response_fifo;
XorShift128PlusPlus prng;
std::array<SectorBuffer, NUM_SECTOR_BUFFERS> sector_buffers;
u32 current_read_sector_buffer = 0;
u32 current_write_sector_buffer = 0;
@ -608,6 +612,7 @@ void CDROM::Reset()
s_state.param_fifo.Clear();
s_state.response_fifo.Clear();
s_state.async_response_fifo.Clear();
s_state.prng.Reset(PRNG_SEED);
UpdateStatusRegister();
@ -758,6 +763,11 @@ bool CDROM::DoState(StateWrapper& sw)
sw.Do(&s_state.response_fifo);
sw.Do(&s_state.async_response_fifo);
if (sw.GetVersion() >= 79)
sw.DoPOD(s_state.prng.GetMutableStatePtr());
else
s_state.prng.Reset(PRNG_SEED);
if (sw.GetVersion() < 65)
{
// Skip over the "copied out data", we don't care about it.
@ -1637,6 +1647,12 @@ TickCount CDROM::GetTicksForSeek(CDImage::LBA new_lba, bool ignore_speed_change)
seek_type = (new_lba > current_lba) ? "sled forward" : "sled backward";
}
// I hate this so much. There's some games that are extremely timing sensitive in their disc code, and if we return
// the same seek times repeatedly, end up locking up in an infinite loop. e.g. Resident Evil, Dino Crisis, etc.
// Add some randomness to timing if we detect them repeatedly seeking, otherwise don't. This somewhat simulates how
// the real hardware behaves, by adding an additional 0.5-1ms to every seek.
ticks += s_state.prng.NextRange<u32>(System::MASTER_CLOCK / 2000, System::MASTER_CLOCK / 1000);
if (g_settings.cdrom_seek_speedup > 1)
ticks = std::max<u32>(ticks / g_settings.cdrom_seek_speedup, MIN_SEEK_TICKS);

@ -6,7 +6,7 @@
#include "common/types.h"
static constexpr u32 SAVE_STATE_MAGIC = 0x43435544;
static constexpr u32 SAVE_STATE_VERSION = 78;
static constexpr u32 SAVE_STATE_VERSION = 79;
static constexpr u32 SAVE_STATE_MINIMUM_VERSION = 42;
static_assert(SAVE_STATE_VERSION >= SAVE_STATE_MINIMUM_VERSION);

Loading…
Cancel
Save