This commit is contained in:
Connor McLaughlin 2021-04-15 02:44:22 +10:00
parent 88618bde1c
commit da0417bb46
4 changed files with 124 additions and 33 deletions

View File

@ -189,6 +189,8 @@ bool DoState(StateWrapper& sw)
void SetExpansionROM(std::vector<u8> data)
{
m_exp1_rom = std::move(data);
if (m_exp1_rom.size() < 256 * 1024)
m_exp1_rom.resize(256 * 1024, 0xFF);
}
void SetBIOS(const std::vector<u8>& image)
@ -813,24 +815,38 @@ ALWAYS_INLINE static TickCount DoBIOSAccess(u32 offset, u32& value)
return m_bios_access_time[static_cast<u32>(size)];
}
static bool flash_unlocked = false;
static bool chip_id_mode = false;
static u8 chip_id[] = {0x1F, 0xA4};
static u8 flash_command_key[] = {0xAA, 0x55};
static u8 flash_command_sequence = 0;
template<MemoryAccessType type, MemoryAccessSize size>
static TickCount DoEXP1Access(u32 offset, u32& value)
{
constexpr u32 transfer_size = u32(1) << static_cast<u32>(size);
if constexpr (type == MemoryAccessType::Read)
{
if (m_exp1_rom.empty())
if (chip_id_mode)
{
if ((offset + transfer_size) > sizeof(chip_id))
value = 0;
else
std::memcpy(&value, &chip_id[offset], sizeof(value));
}
else if (m_exp1_rom.empty())
{
// EXP1 not present.
value = UINT32_C(0xFFFFFFFF);
}
else if (offset == 0x20018)
else if (offset == 0x60000)
{
// Bit 0 - Action Replay On/Off
value = UINT32_C(1);
}
else
{
const u32 transfer_size = u32(1) << static_cast<u32>(size);
if ((offset + transfer_size) > m_exp1_rom.size())
{
value = UINT32_C(0);
@ -861,6 +877,69 @@ static TickCount DoEXP1Access(u32 offset, u32& value)
else
{
Log_WarningPrintf("EXP1 write: 0x%08X <- 0x%08X", EXP1_BASE | offset, value);
if (offset == 0x5555 && value == 0xAA && flash_command_sequence == 0)
{
flash_command_sequence = 1;
return 0;
}
else if (offset == 0x2AAA && value == 0x55 && flash_command_sequence == 1)
{
flash_command_sequence = 2;
return 0;
}
else if (offset == 0x5555 && flash_command_sequence == 2)
{
flash_command_sequence = 0;
switch (value)
{
case 0xA0:
{
Log_DevPrintf("Flash unlocked");
flash_unlocked = true;
}
break;
case 0x90:
{
Log_DevPrintf("Enter ID mode");
chip_id_mode = true;
}
break;
case 0xF0:
{
Log_DevPrintf("Exit ID mode");
chip_id_mode = false;
}
break;
case 0x80:
{
Log_WarningPrintf("Erase chip 1");
}
break;
case 0x10:
{
Log_WarningPrintf("Erase chip 2");
}
break;
default:
{
Log_ErrorPrintf("Unknown flash command 0x%02X", value);
}
break;
}
return 0;
}
if ((offset + transfer_size) <= m_exp1_rom.size())
std::memcpy(&m_exp1_rom[offset], &value, sizeof(value));
return 0;
}
}
@ -1294,12 +1373,25 @@ ALWAYS_INLINE_RELEASE bool DoInstructionRead(PhysicalMemoryAddress address, void
}
else if (address >= BIOS_BASE && address < (BIOS_BASE + BIOS_SIZE))
{
std::memcpy(data, &g_bios[(address - BIOS_BASE) & BIOS_MASK], sizeof(u32) * word_count);
std::memcpy(data, &g_bios[address - BIOS_BASE], sizeof(u32) * word_count);
if constexpr (add_ticks)
g_state.pending_ticks += m_bios_access_time[static_cast<u32>(MemoryAccessSize::Word)] * word_count;
return true;
}
else if (address >= EXP1_BASE && address < (EXP1_BASE + EXP1_SIZE))
{
const u32 offset = (address - EXP1_BASE);
if ((offset + (word_count * sizeof(u32))) <= m_exp1_rom.size())
std::memcpy(data, m_exp1_rom.data() + offset, sizeof(u32) * word_count);
else
std::memset(data, 0, sizeof(u32) * word_count);
if constexpr (add_ticks)
g_state.pending_ticks += m_exp1_access_time[static_cast<u32>(MemoryAccessSize::Word)] * word_count;
return true;
}
else
{
if (raise_exceptions)

View File

@ -399,6 +399,19 @@ bool HostInterface::HasAnyBIOSImages()
return (FindBIOSImageInDirectory(ConsoleRegion::Auto, dir.c_str()).has_value());
}
std::optional<std::vector<u8>> HostInterface::GetExpansionROMImage()
{
std::string filename = GetStringSettingValue("BIOS", "ExpansionROMPath", "");
if (filename.empty())
return {};
std::optional<std::vector<u8>> ret(FileSystem::ReadBinaryFile(filename.c_str()));
if (!ret)
return {};
return ret;
}
bool HostInterface::LoadState(const char* filename)
{
std::unique_ptr<ByteStream> stream = FileSystem::OpenFile(filename, BYTESTREAM_OPEN_READ | BYTESTREAM_OPEN_STREAMED);

View File

@ -142,6 +142,9 @@ public:
/// Returns true if any BIOS images are found in the configured BIOS directory.
bool HasAnyBIOSImages();
/// Loads the configured expansion ROM image, if any.
std::optional<std::vector<u8>> GetExpansionROMImage();
/// Opens a file in the DuckStation "package".
/// This is the APK for Android builds, or the program directory for standalone builds.
virtual std::unique_ptr<ByteStream> OpenPackageFile(const char* path, u32 flags) = 0;

View File

@ -64,7 +64,6 @@ static bool SaveMemoryState(MemorySaveState* mss);
static bool LoadMemoryState(const MemorySaveState& mss);
static bool LoadEXE(const char* filename);
static bool SetExpansionROM(const char* filename);
/// Opens CD image, preloading if needed.
static std::unique_ptr<CDImage> OpenCDImage(const char* path, Common::Error* error, bool force_preload);
@ -804,6 +803,15 @@ bool Boot(const SystemBootParameters& params)
return false;
}
// Load expansion ROM image.
std::optional<std::vector<u8>> expansion_rom = g_host_interface->GetExpansionROMImage();
if (!expansion_rom)
{
g_host_interface->ReportError(g_host_interface->TranslateString("System", "Failed to expansion ROM image."));
Shutdown();
return false;
}
// Notify change of disc.
UpdateRunningGame(media ? media->GetFileName().c_str() : params.filename.c_str(), media.get());
@ -831,6 +839,9 @@ bool Boot(const SystemBootParameters& params)
}
Bus::SetBIOS(*bios_image);
if (expansion_rom && !expansion_rom->empty())
Bus::SetExpansionROM(std::move(*expansion_rom));
UpdateControllers();
UpdateMemoryCards();
UpdateMultitaps();
@ -1683,34 +1694,6 @@ bool InjectEXEFromBuffer(const void* buffer, u32 buffer_size, bool patch_bios)
return true;
}
bool SetExpansionROM(const char* filename)
{
std::FILE* fp = FileSystem::OpenCFile(filename, "rb");
if (!fp)
{
Log_ErrorPrintf("Failed to open '%s'", filename);
return false;
}
std::fseek(fp, 0, SEEK_END);
const u32 size = static_cast<u32>(std::ftell(fp));
std::fseek(fp, 0, SEEK_SET);
std::vector<u8> data(size);
if (std::fread(data.data(), size, 1, fp) != 1)
{
Log_ErrorPrintf("Failed to read ROM data from '%s'", filename);
std::fclose(fp);
return false;
}
std::fclose(fp);
Log_InfoPrintf("Loaded expansion ROM from '%s': %u bytes", filename, size);
Bus::SetExpansionROM(std::move(data));
return true;
}
void StallCPU(TickCount ticks)
{
CPU::AddPendingTicks(ticks);