HW: stabilize original BootMii interaction
This commit is contained in:
@@ -77,7 +77,11 @@ void ProcessorInterfaceManager::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
|||||||
mmio->Register(base | PI_INTERRUPT_CAUSE, MMIO::DirectRead<u32>(&m_interrupt_cause),
|
mmio->Register(base | PI_INTERRUPT_CAUSE, MMIO::DirectRead<u32>(&m_interrupt_cause),
|
||||||
MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
|
MMIO::ComplexWrite<u32>([](Core::System& system, u32, u32 val) {
|
||||||
auto& processor_interface = system.GetProcessorInterface();
|
auto& processor_interface = system.GetProcessorInterface();
|
||||||
processor_interface.m_interrupt_cause &= ~val;
|
// The reset-button bit is a live, active-low input state rather than an
|
||||||
|
// interrupt latch. Software can acknowledge the other causes, but must not be
|
||||||
|
// able to turn an unpressed reset button into a permanently pressed one.
|
||||||
|
processor_interface.m_interrupt_cause =
|
||||||
|
AcknowledgeInterruptCauses(processor_interface.m_interrupt_cause, val);
|
||||||
processor_interface.UpdateException();
|
processor_interface.UpdateException();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@@ -78,6 +78,11 @@ enum ErrorCause : u32
|
|||||||
Reserved = 7,
|
Reserved = 7,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr u32 AcknowledgeInterruptCauses(u32 current, u32 acknowledged)
|
||||||
|
{
|
||||||
|
return current & ~(acknowledged & ~static_cast<u32>(INT_CAUSE_RST_BUTTON));
|
||||||
|
}
|
||||||
|
|
||||||
class ProcessorInterfaceManager
|
class ProcessorInterfaceManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -320,9 +320,12 @@ void VideoInterfaceManager::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
|||||||
return 1 + (vi.m_half_line_count) / 2;
|
return 1 + (vi.m_half_line_count) / 2;
|
||||||
}),
|
}),
|
||||||
MMIO::ComplexWrite<u16>([](Core::System& system, u32, u16 val) {
|
MMIO::ComplexWrite<u16>([](Core::System& system, u32, u16 val) {
|
||||||
WARN_LOG_FMT(
|
auto& vi = system.GetVideoInterface();
|
||||||
VIDEOINTERFACE,
|
const u32 total_half_lines = vi.GetHalfLinesPerEvenField() + vi.GetHalfLinesPerOddField();
|
||||||
"Changing vertical beam position to {:#06x} - not documented or implemented yet", val);
|
const u32 line = val == 0 ? 0 : static_cast<u32>(val - 1);
|
||||||
|
const u32 target_half_line = line * 2 + (vi.m_half_line_count & 1);
|
||||||
|
vi.m_half_line_count =
|
||||||
|
total_half_lines == 0 ? target_half_line : target_half_line % total_half_lines;
|
||||||
}));
|
}));
|
||||||
mmio->Register(
|
mmio->Register(
|
||||||
base | VI_HORIZONTAL_BEAM_POSITION, MMIO::ComplexRead<u16>([](Core::System& system, u32) {
|
base | VI_HORIZONTAL_BEAM_POSITION, MMIO::ComplexRead<u16>([](Core::System& system, u32) {
|
||||||
@@ -334,10 +337,20 @@ void VideoInterfaceManager::RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
|||||||
return std::clamp<u16>(value, 1, vi.m_h_timing_0.HLW * 2);
|
return std::clamp<u16>(value, 1, vi.m_h_timing_0.HLW * 2);
|
||||||
}),
|
}),
|
||||||
MMIO::ComplexWrite<u16>([](Core::System& system, u32, u16 val) {
|
MMIO::ComplexWrite<u16>([](Core::System& system, u32, u16 val) {
|
||||||
WARN_LOG_FMT(
|
auto& vi = system.GetVideoInterface();
|
||||||
VIDEOINTERFACE,
|
const u32 half_line_width = vi.m_h_timing_0.HLW;
|
||||||
"Changing horizontal beam position to {:#06x} - not documented or implemented yet",
|
if (half_line_width == 0)
|
||||||
val);
|
return;
|
||||||
|
|
||||||
|
const u32 horizontal_position =
|
||||||
|
std::clamp<u32>(val, 1, static_cast<u32>(half_line_width) * 2);
|
||||||
|
const u32 target_half_line = horizontal_position > half_line_width ? 1 : 0;
|
||||||
|
vi.m_half_line_count = (vi.m_half_line_count & ~1u) | target_half_line;
|
||||||
|
|
||||||
|
const u64 ticks_into_line =
|
||||||
|
static_cast<u64>(horizontal_position - 1) * vi.GetTicksPerHalfLine() / half_line_width;
|
||||||
|
const u64 ticks = system.GetCoreTiming().GetTicks();
|
||||||
|
vi.m_ticks_last_line_start = ticks >= ticks_into_line ? ticks - ticks_into_line : 0;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// The following MMIOs are interrupts related and update interrupt status
|
// The following MMIOs are interrupts related and update interrupt status
|
||||||
@@ -972,9 +985,10 @@ void VideoInterfaceManager::Update(u64 ticks)
|
|||||||
// the beginning of a new full-line, update the timer
|
// the beginning of a new full-line, update the timer
|
||||||
|
|
||||||
++m_half_line_count;
|
++m_half_line_count;
|
||||||
if (m_half_line_count == GetHalfLinesPerEvenField() + GetHalfLinesPerOddField())
|
const u32 total_half_lines = GetHalfLinesPerEvenField() + GetHalfLinesPerOddField();
|
||||||
|
if (total_half_lines != 0 && m_half_line_count >= total_half_lines)
|
||||||
{
|
{
|
||||||
m_half_line_count = 0;
|
m_half_line_count %= total_half_lines;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(m_half_line_count & 1))
|
if (!(m_half_line_count & 1))
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Core/HW/GPFifo.h"
|
#include "Core/HW/GPFifo.h"
|
||||||
#include "Core/HW/MMIO.h"
|
#include "Core/HW/MMIO.h"
|
||||||
|
#include "Core/HW/ProcessorInterface.h"
|
||||||
#include "Core/System.h"
|
#include "Core/System.h"
|
||||||
|
|
||||||
// Tests that the UniqueID function returns a "unique enough" identifier
|
// Tests that the UniqueID function returns a "unique enough" identifier
|
||||||
@@ -53,6 +54,14 @@ TEST(IsMMIOAddress, SpecialAddresses)
|
|||||||
EXPECT_TRUE(MMIO::IsMMIOAddress(0x0D800F10, is_wii)); // Mirror of Wii MMIOs
|
EXPECT_TRUE(MMIO::IsMMIOAddress(0x0D800F10, is_wii)); // Mirror of Wii MMIOs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ProcessorInterface, ResetButtonStateCannotBeAcknowledged)
|
||||||
|
{
|
||||||
|
constexpr u32 reset = ProcessorInterface::INT_CAUSE_RST_BUTTON;
|
||||||
|
EXPECT_EQ(reset, ProcessorInterface::AcknowledgeInterruptCauses(
|
||||||
|
reset | ProcessorInterface::INT_CAUSE_VI, 0xffffffffu));
|
||||||
|
EXPECT_EQ(0u, ProcessorInterface::AcknowledgeInterruptCauses(0, 0xffffffffu));
|
||||||
|
}
|
||||||
|
|
||||||
class MappingTest : public testing::Test
|
class MappingTest : public testing::Test
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
+15
-3
@@ -295,10 +295,21 @@ An isolated boot probe using the local, mutually matching dumps has executed thi
|
|||||||
EXI paths, published its EXI Broadway boot vector, released Broadway, and ran the original
|
EXI paths, published its EXI Broadway boot vector, released Broadway, and ran the original
|
||||||
`ppcboot.elf`. The interactive four-icon BootMii menu rendered without a host-side firmware
|
`ppcboot.elf`. The interactive four-icon BootMii menu rendered without a host-side firmware
|
||||||
jump, a patched BootMii binary, or a synthesized SI reply.
|
jump, a patched BootMii binary, or a synthesized SI reply.
|
||||||
|
21. BootMii exposed two remaining Broadway hardware differences. Its VI setup writes the vertical
|
||||||
|
and horizontal beam-position registers; ignoring those writes let Dolphin's half-line counter
|
||||||
|
escape the active field and prevented the next VI interrupt. The beam writes now reposition the
|
||||||
|
emulated raster and field wrapping tolerates an out-of-range position. BootMii also clears the
|
||||||
|
PI interrupt-cause register before polling the front-panel controls. The reset-button bit is a
|
||||||
|
live active-low input, not an acknowledgeable interrupt latch, so PI acknowledgements now
|
||||||
|
preserve it. This removed the false held-RESET state that selected the Wii icon and issued
|
||||||
|
`IPC_BOOT2_RUN(1, 2)` immediately. Cold-boot BootMii and HBC -> IOS254 -> MINI -> BootMii both
|
||||||
|
remain in the original interactive menu, and keyboard-backed GameCube navigation was validated
|
||||||
|
without modifying `armboot.bin`, `ppcboot.elf`, or `bootmii.ini`.
|
||||||
|
|
||||||
The probe never prints ROM, NAND, key, or firmware instruction bytes. The committed unit suite
|
The probe never prints ROM, NAND, key, or firmware instruction bytes. The committed unit suite
|
||||||
covers ARM-to-Thumb loads into PC, high Starlet exception vectors, privileged `LDM ... ^` user-bank
|
covers ARM-to-Thumb loads into PC, high Starlet exception vectors, privileged `LDM ... ^` user-bank
|
||||||
transfers, latched bidirectional IPC control bits, empty-slot SDHCI reset/clock/status behavior,
|
transfers, latched bidirectional IPC control bits, the PI reset-button state surviving interrupt
|
||||||
|
acknowledgements, empty-slot SDHCI reset/clock/status behavior,
|
||||||
timer equal/future comparator matches with independent IRQ write-one-to-clear acknowledgement,
|
timer equal/future comparator matches with independent IRQ write-one-to-clear acknowledgement,
|
||||||
OHCI power-good/root-hub state, and a complete three-TD USB device-descriptor transaction. Targeted
|
OHCI power-good/root-hub state, and a complete three-TD USB device-descriptor transaction. Targeted
|
||||||
development probes additionally exercised NAND read/program/erase and program-time ECC, SEEPROM
|
development probes additionally exercised NAND read/program/erase and program-time ECC, SEEPROM
|
||||||
@@ -317,8 +328,8 @@ the three pre-existing bad-ECC pages in the source dump, a valid EXI reset vecto
|
|||||||
|
|
||||||
The current end-to-end boundary is a rendered, controller-connected and post-health-screen System
|
The current end-to-end boundary is a rendered, controller-connected and post-health-screen System
|
||||||
Menu with its populated channel grid, followed by a successful original IOS80-to-IOS58 reload, a
|
Menu with its populated channel grid, followed by a successful original IOS80-to-IOS58 reload, a
|
||||||
rendered Homebrew Channel, LetterBomb reaching the interactive HackMii Installer menu, and the
|
rendered Homebrew Channel, LetterBomb reaching the interactive HackMii Installer menu, and both
|
||||||
dump's BootMii-as-boot2 installation reaching its original interactive UI through MINI and
|
cold-boot and IOS254 launches reaching a stable, navigable original BootMii UI through MINI and
|
||||||
`ppcboot.elf`. The path sustains PPC-to-original-IOS filesystem, DI, Bluetooth HID, SDIO/Wi-Fi and
|
`ppcboot.elf`. The path sustains PPC-to-original-IOS filesystem, DI, Bluetooth HID, SDIO/Wi-Fi and
|
||||||
network-service traffic. The stabilized Menu has been measured at 59.91 FPS and HBC at 59.94 FPS.
|
network-service traffic. The stabilized Menu has been measured at 59.91 FPS and HBC at 59.94 FPS.
|
||||||
It proves the emulated first Wii Remote's pairing, L2CAP setup, command exchange and input-report
|
It proves the emulated first Wii Remote's pairing, L2CAP setup, command exchange and input-report
|
||||||
@@ -387,6 +398,7 @@ than a drop-in replacement for Dolphin's mature IOS HLE mode.
|
|||||||
| Address space and devices | `Core/IOS/Starlet/StarletMemory.{h,cpp}` |
|
| Address space and devices | `Core/IOS/Starlet/StarletMemory.{h,cpp}` |
|
||||||
| Bluetooth pairing and Wii Remote HID | `Core/IOS/USB/Bluetooth/{BTBase,WiimoteDevice}.{h,cpp}` |
|
| Bluetooth pairing and Wii Remote HID | `Core/IOS/USB/Bluetooth/{BTBase,WiimoteDevice}.{h,cpp}` |
|
||||||
| IPC and Broadway reset | `Core/HW/WII_IPC.{h,cpp}` |
|
| IPC and Broadway reset | `Core/HW/WII_IPC.{h,cpp}` |
|
||||||
|
| Broadway VI and front-panel state | `Core/HW/VideoInterface.cpp`, `Core/HW/ProcessorInterface.{h,cpp}` |
|
||||||
| Mode selection/lifetime | `Core/HW/HW.cpp`, `Core/System.{h,cpp}` |
|
| Mode selection/lifetime | `Core/HW/HW.cpp`, `Core/System.{h,cpp}` |
|
||||||
| Boot-path separation | `Core/Boot/Boot.cpp`, `Core/ConfigManager.cpp`, `Core/Core.cpp` |
|
| Boot-path separation | `Core/Boot/Boot.cpp`, `Core/ConfigManager.cpp`, `Core/Core.cpp` |
|
||||||
| Configuration | `Core/Config/MainSettings.{h,cpp}` |
|
| Configuration | `Core/Config/MainSettings.{h,cpp}` |
|
||||||
|
|||||||
Reference in New Issue
Block a user