From e072be6dc6e80b6db6cb5344d2746cf2753b4e98 Mon Sep 17 00:00:00 2001 From: fleroviux Date: Fri, 12 Aug 2022 00:24:22 +0200 Subject: [PATCH 1/4] EEPROM: automatically detect save size (closes #219) --- src/nba/include/nba/config.hpp | 3 ++- src/nba/include/nba/rom/backup/eeprom.hpp | 5 +++- src/nba/include/nba/rom/rom.hpp | 6 +++++ src/nba/src/hw/dma/dma.cpp | 31 +++++++++++++++++------ src/nba/src/hw/dma/dma.hpp | 6 ++--- src/nba/src/hw/rom/backup/eeprom.cpp | 20 ++++++++++++--- src/platform/core/src/loader/rom.cpp | 31 ++++++++--------------- 7 files changed, 65 insertions(+), 37 deletions(-) diff --git a/src/nba/include/nba/config.hpp b/src/nba/include/nba/config.hpp index 02e63cfa3..1dbcd7e0d 100644 --- a/src/nba/include/nba/config.hpp +++ b/src/nba/include/nba/config.hpp @@ -26,7 +26,8 @@ struct Config { FLASH_64, FLASH_128, EEPROM_4, - EEPROM_64 + EEPROM_64, + EEPROM_DETECT // for internal use }; struct Audio { diff --git a/src/nba/include/nba/rom/backup/eeprom.hpp b/src/nba/include/nba/rom/backup/eeprom.hpp index 37d2937fc..4b75ae3de 100644 --- a/src/nba/include/nba/rom/backup/eeprom.hpp +++ b/src/nba/include/nba/rom/backup/eeprom.hpp @@ -16,7 +16,8 @@ namespace nba { struct EEPROM : Backup { enum Size { SIZE_4K = 0, - SIZE_64K = 1 + SIZE_64K = 1, + DETECT = 2 }; EEPROM(std::string const& save_path, Size size_hint); @@ -28,6 +29,8 @@ struct EEPROM : Backup { void LoadState(SaveState const& state) final; void CopyState(SaveState& state) final; + void SetSizeHint(Size size); + private: enum State { STATE_ACCEPT_COMMAND = 1 << 0, diff --git a/src/nba/include/nba/rom/rom.hpp b/src/nba/include/nba/rom/rom.hpp index 0f9bfef7d..0c274c3b4 100644 --- a/src/nba/include/nba/rom/rom.hpp +++ b/src/nba/include/nba/rom/rom.hpp @@ -106,6 +106,12 @@ struct ROM { } } + void SetEEPROMSizeHint(EEPROM::Size size) { + if (backup_eeprom) { + ((EEPROM*)backup_eeprom.get())->SetSizeHint(size); + } + } + auto ALWAYS_INLINE ReadROM16(u32 address) -> u16 { address &= 0x01FF'FFFE; diff --git a/src/nba/src/hw/dma/dma.cpp b/src/nba/src/hw/dma/dma.cpp index 850b38587..8bb07a3c7 100644 --- a/src/nba/src/hw/dma/dma.cpp +++ b/src/nba/src/hw/dma/dma.cpp @@ -151,13 +151,13 @@ bool DMA::HasVideoTransferDMA() { } void DMA::Run() { - memory.Idle(); + bus.Idle(); do { RunChannel(); } while (IsRunning()); - memory.Idle(); + bus.Idle(); } void DMA::RunChannel() { @@ -203,7 +203,7 @@ void DMA::RunChannel() { u16 value; if (likely(src_addr >= 0x02000000)) { - value = memory.ReadHalf(src_addr, access_src); + value = bus.ReadHalf(src_addr, access_src); channel.latch.bus = (value << 16) | value; latch = channel.latch.bus; } else { @@ -212,19 +212,19 @@ void DMA::RunChannel() { } else { value = channel.latch.bus; } - memory.Idle(); + bus.Idle(); } - memory.WriteHalf(dst_addr, value, access_dst); + bus.WriteHalf(dst_addr, value, access_dst); } else { if (likely(src_addr >= 0x02000000)) { - channel.latch.bus = memory.ReadWord(src_addr, access_src); + channel.latch.bus = bus.ReadWord(src_addr, access_src); latch = channel.latch.bus; } else { - memory.Idle(); + bus.Idle(); } - memory.WriteWord(dst_addr, channel.latch.bus, access_dst); + bus.WriteWord(dst_addr, channel.latch.bus, access_dst); } channel.latch.src_addr += src_modify; @@ -374,6 +374,21 @@ void DMA::OnChannelWritten(Channel& channel, bool enable_old) { } else { AddChannelToDMASet(channel); } + + /* Try to auto-detect EEPROM size from the first EEPROM DMA transfer, + * since we cannot always determine the size at load time. + */ + if (channel.dst_addr >= 0x0D000000) { + int length = channel.length; + + if (length == 9 || length == 73) { + bus.memory.rom.SetEEPROMSizeHint(EEPROM::Size::SIZE_4K); + } + + if (length == 17 || length == 81) { + bus.memory.rom.SetEEPROMSizeHint(EEPROM::Size::SIZE_64K); + } + } } } else { // DMA enable bit: 1 -> 1 (remains set) diff --git a/src/nba/src/hw/dma/dma.hpp b/src/nba/src/hw/dma/dma.hpp index e281f2a22..2b447d0ac 100644 --- a/src/nba/src/hw/dma/dma.hpp +++ b/src/nba/src/hw/dma/dma.hpp @@ -19,8 +19,8 @@ namespace nba::core { struct Bus; struct DMA { - DMA(Bus& memory, IRQ& irq, Scheduler& scheduler) - : memory(memory) + DMA(Bus& bus, IRQ& irq, Scheduler& scheduler) + : bus(bus) , irq(irq) , scheduler(scheduler) { Reset(); @@ -117,7 +117,7 @@ struct DMA { void RemoveChannelFromDMASets(Channel& channel); void RunChannel(); - Bus& memory; + Bus& bus; IRQ& irq; Scheduler& scheduler; diff --git a/src/nba/src/hw/rom/backup/eeprom.cpp b/src/nba/src/hw/rom/backup/eeprom.cpp index 0bfff715f..5f673402e 100644 --- a/src/nba/src/hw/rom/backup/eeprom.cpp +++ b/src/nba/src/hw/rom/backup/eeprom.cpp @@ -11,8 +11,8 @@ namespace nba { -static constexpr int g_addr_bits[2] = { 6, 14 }; -static constexpr int g_save_size[2] = { 512, 8192 }; +static constexpr int g_addr_bits[3] = { 6, 14, 14 }; +static constexpr int g_save_size[3] = { 512, 8192, 8192 }; EEPROM::EEPROM(std::string const& save_path, Size size_hint) : size(size_hint) @@ -27,10 +27,10 @@ void EEPROM::Reset() { int bytes = g_save_size[size]; - file = BackupFile::OpenOrCreate(save_path, { 512, 8192 }, bytes); + file = BackupFile::OpenOrCreate(save_path, {512, 8192}, bytes); if (bytes == g_save_size[0]) { size = SIZE_4K; - } else { + } else if (size != DETECT) { // DETECT has same size as SIZE_64K size = SIZE_64K; } } @@ -127,4 +127,16 @@ void EEPROM::Write(u32 address, u8 value) { } } +void EEPROM::SetSizeHint(Size size) { + if (this->size == DETECT) { + int bytes = g_save_size[size]; + + this->size = size; + + if (file->Size() != bytes) { + file = BackupFile::OpenOrCreate(save_path, {bytes}, bytes); + } + } +} + } // namespace nba diff --git a/src/platform/core/src/loader/rom.cpp b/src/platform/core/src/loader/rom.cpp index 726582b8b..ef326a0ad 100644 --- a/src/platform/core/src/loader/rom.cpp +++ b/src/platform/core/src/loader/rom.cpp @@ -192,11 +192,11 @@ auto ROMLoader::GetBackupType( std::vector& file_data ) -> BackupType { static constexpr std::pair signatures[6] { - { "EEPROM_V", BackupType::EEPROM_64 }, - { "SRAM_V", BackupType::SRAM }, - { "SRAM_F_V", BackupType::SRAM }, - { "FLASH_V", BackupType::FLASH_64 }, - { "FLASH512_V", BackupType::FLASH_64 }, + { "EEPROM_V", BackupType::EEPROM_DETECT }, + { "SRAM_V", BackupType::SRAM }, + { "SRAM_F_V", BackupType::SRAM }, + { "FLASH_V", BackupType::FLASH_64 }, + { "FLASH512_V", BackupType::FLASH_64 }, { "FLASH1M_V", BackupType::FLASH_128 } }; @@ -219,21 +219,12 @@ auto ROMLoader::CreateBackup( BackupType backup_type ) -> std::unique_ptr { switch (backup_type) { - case BackupType::SRAM: { - return std::make_unique(save_path); - } - case BackupType::FLASH_64: { - return std::make_unique(save_path, FLASH::SIZE_64K); - } - case BackupType::FLASH_128: { - return std::make_unique(save_path, FLASH::SIZE_128K); - } - case BackupType::EEPROM_4: { - return std::make_unique(save_path, EEPROM::SIZE_4K); - } - case BackupType::EEPROM_64: { - return std::make_unique(save_path, EEPROM::SIZE_64K); - } + case BackupType::SRAM: return std::make_unique(save_path); + case BackupType::FLASH_64: return std::make_unique(save_path, FLASH::SIZE_64K); + case BackupType::FLASH_128: return std::make_unique(save_path, FLASH::SIZE_128K); + case BackupType::EEPROM_4: return std::make_unique(save_path, EEPROM::SIZE_4K); + case BackupType::EEPROM_64: return std::make_unique(save_path, EEPROM::SIZE_64K); + case BackupType::EEPROM_DETECT: return std::make_unique(save_path, EEPROM::DETECT); } return {}; From aa134f47e86e803608f986940de23d87ceb19179 Mon Sep 17 00:00:00 2001 From: fleroviux Date: Fri, 12 Aug 2022 00:38:49 +0200 Subject: [PATCH 2/4] EEPROM: automatically detect save size (2) --- src/nba/include/nba/rom/backup/eeprom.hpp | 2 ++ src/nba/src/hw/rom/backup/eeprom.cpp | 17 +++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/nba/include/nba/rom/backup/eeprom.hpp b/src/nba/include/nba/rom/backup/eeprom.hpp index 4b75ae3de..1b71ca6c3 100644 --- a/src/nba/include/nba/rom/backup/eeprom.hpp +++ b/src/nba/include/nba/rom/backup/eeprom.hpp @@ -53,6 +53,8 @@ struct EEPROM : Backup { int address; u64 serial_buffer; int transmitted_bits; + + bool detect_size; }; } // namespace nba diff --git a/src/nba/src/hw/rom/backup/eeprom.cpp b/src/nba/src/hw/rom/backup/eeprom.cpp index 5f673402e..74827a662 100644 --- a/src/nba/src/hw/rom/backup/eeprom.cpp +++ b/src/nba/src/hw/rom/backup/eeprom.cpp @@ -11,8 +11,8 @@ namespace nba { -static constexpr int g_addr_bits[3] = { 6, 14, 14 }; -static constexpr int g_save_size[3] = { 512, 8192, 8192 }; +static constexpr int g_addr_bits[2] = { 6, 14 }; +static constexpr int g_save_size[2] = { 512, 8192 }; EEPROM::EEPROM(std::string const& save_path, Size size_hint) : size(size_hint) @@ -25,12 +25,20 @@ void EEPROM::Reset() { address = 0; ResetSerialBuffer(); + if (size == DETECT) { + size = SIZE_64K; // default to 8 KiB size + detect_size = true; + } else { + detect_size = false; + } + int bytes = g_save_size[size]; file = BackupFile::OpenOrCreate(save_path, {512, 8192}, bytes); + if (bytes == g_save_size[0]) { size = SIZE_4K; - } else if (size != DETECT) { // DETECT has same size as SIZE_64K + } else { size = SIZE_64K; } } @@ -128,10 +136,11 @@ void EEPROM::Write(u32 address, u8 value) { } void EEPROM::SetSizeHint(Size size) { - if (this->size == DETECT) { + if (detect_size) { int bytes = g_save_size[size]; this->size = size; + detect_size = false; if (file->Size() != bytes) { file = BackupFile::OpenOrCreate(save_path, {bytes}, bytes); From 66076c3e4e924b585c1a91f5ec2050e65a493656 Mon Sep 17 00:00:00 2001 From: fleroviux Date: Fri, 12 Aug 2022 01:18:15 +0200 Subject: [PATCH 3/4] Qt: reload cartridge when resetting due to config change (fixes #244) --- src/platform/qt/src/widget/main_window.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/platform/qt/src/widget/main_window.cpp b/src/platform/qt/src/widget/main_window.cpp index b3e0e42f7..4eb5f2596 100644 --- a/src/platform/qt/src/widget/main_window.cpp +++ b/src/platform/qt/src/widget/main_window.cpp @@ -467,6 +467,11 @@ void MainWindow::PromptUserForReset() { box.setDefaultButton(QMessageBox::No); if (box.exec() == QMessageBox::Yes) { + // Reload the ROM in case its config (e.g. save type or GPIO) has changed: + if (game_loaded) { + LoadROM(game_path); + } + Reset(); } } From a81097f9624132dfb5a9c09de51ef32a9814ccc7 Mon Sep 17 00:00:00 2001 From: fleroviux Date: Fri, 12 Aug 2022 01:29:19 +0200 Subject: [PATCH 4/4] Fix Clang build (hopefully) --- src/nba/src/hw/rom/backup/eeprom.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nba/src/hw/rom/backup/eeprom.cpp b/src/nba/src/hw/rom/backup/eeprom.cpp index 74827a662..e7e1a5f6a 100644 --- a/src/nba/src/hw/rom/backup/eeprom.cpp +++ b/src/nba/src/hw/rom/backup/eeprom.cpp @@ -143,7 +143,7 @@ void EEPROM::SetSizeHint(Size size) { detect_size = false; if (file->Size() != bytes) { - file = BackupFile::OpenOrCreate(save_path, {bytes}, bytes); + file = BackupFile::OpenOrCreate(save_path, {(size_t)bytes}, bytes); } } }