@@ -110,6 +110,9 @@ void MainWindow::debugStep(int mode) {
110110 } else {
111111 disasm.base = static_cast <int32_t >(cpu.registers .PC );
112112 disasmGet (true );
113+
114+ m_stepCtx.active = true ;
115+ m_stepCtx.seqNext = static_cast <uint32_t >(disasm.next );
113116 debug_step (mode, static_cast <uint32_t >(disasm.next ));
114117 }
115118 emu.resume ();
@@ -392,6 +395,7 @@ void MainWindow::debugCommand(int reason, uint32_t data) {
392395
393396 if (reason == DBG_READY) {
394397 guiReset = false ;
398+ navDisasmClear ();
395399 emu.resume ();
396400 return ;
397401 }
@@ -850,6 +854,17 @@ void MainWindow::debugPopulate() {
850854 osUpdate ();
851855 stackUpdate ();
852856 disasmUpdateAddr (m_prevDisasmAddr = cpu.registers .PC , true );
857+ // Track step navigation: append on control-flow (branch taken),
858+ // replace on linear advance. Non-step stops do not modify history
859+ if (m_stepCtx.active ) {
860+ bool tookBranch = (static_cast <uint32_t >(cpu.registers .PC ) != m_stepCtx.seqNext );
861+ if (tookBranch) {
862+ navDisasmPush (m_prevDisasmAddr, true );
863+ } else {
864+ navDisasmReplace (m_prevDisasmAddr, true );
865+ }
866+ m_stepCtx.active = false ;
867+ }
853868
854869 memUpdate ();
855870
@@ -1964,6 +1979,98 @@ void MainWindow::disasmUpdateAddr(int base, bool pane) {
19641979 connect (m_disasm->verticalScrollBar (), &QScrollBar::valueChanged, this , &MainWindow::disasmScroll);
19651980}
19661981
1982+ // ------------------------------------------------
1983+ // Disassembly navigation history helpers
1984+ // ------------------------------------------------
1985+
1986+ uint32_t MainWindow::currentDisasmAddress () const {
1987+ if (m_prevDisasmAddr) {
1988+ return m_prevDisasmAddr;
1989+ }
1990+ QString sel = m_disasm ? m_disasm->getSelectedAddr () : QString ();
1991+ if (!sel.isEmpty ()) {
1992+ return static_cast <uint32_t >(hex2int (sel));
1993+ }
1994+ return cpu.registers .PC ;
1995+ }
1996+
1997+ void MainWindow::navDisasmEnsureSeeded () {
1998+ if (m_disasmNavIndex == -1 ) {
1999+ m_disasmNav.reserve (kMaxDisasmHistory );
2000+ // seed with the last PC location and current pane mode so that fully backing out returns to the same stop context
2001+ m_disasmNav.push_back ({ currentDisasmAddress (), m_disasmPane });
2002+ m_disasmNavIndex = 0 ;
2003+ }
2004+ }
2005+
2006+ void MainWindow::navDisasmPush (uint32_t addr, bool pane) {
2007+ if (m_isApplyingDisasmNav) {
2008+ disasmUpdateAddr (static_cast <int >(addr), pane);
2009+ return ;
2010+ }
2011+ if (m_disasmNavIndex >= 0 && m_disasmNavIndex < m_disasmNav.size ()) {
2012+ const DisasmNavEntry &cur = m_disasmNav[m_disasmNavIndex];
2013+ if (cur.addr == addr && cur.pane == pane) {
2014+ disasmUpdateAddr (static_cast <int >(addr), pane);
2015+ return ;
2016+ }
2017+ }
2018+ if (m_disasmNavIndex + 1 < m_disasmNav.size ()) {
2019+ m_disasmNav.resize (m_disasmNavIndex + 1 );
2020+ }
2021+ if (m_disasmNav.size () >= kMaxDisasmHistory ) {
2022+ m_disasmNav.remove (0 );
2023+ if (m_disasmNavIndex > 0 ) { --m_disasmNavIndex; }
2024+ }
2025+ m_disasmNav.push_back ({addr, pane});
2026+ m_disasmNavIndex = m_disasmNav.size () - 1 ;
2027+ m_isApplyingDisasmNav = true ;
2028+ disasmUpdateAddr (static_cast <int >(addr), pane);
2029+ m_isApplyingDisasmNav = false ;
2030+ }
2031+
2032+ void MainWindow::navDisasmReplace (uint32_t addr, bool pane) {
2033+ if (m_isApplyingDisasmNav) {
2034+ return ;
2035+ }
2036+ navDisasmEnsureSeeded ();
2037+ if (m_disasmNavIndex < 0 ) {
2038+ m_disasmNav.push_back ({addr, pane});
2039+ m_disasmNavIndex = m_disasmNav.size () - 1 ;
2040+ } else {
2041+ m_disasmNav[m_disasmNavIndex] = {addr, pane};
2042+ }
2043+ }
2044+
2045+ bool MainWindow::navDisasmBack () {
2046+ if (m_disasmNavIndex > 0 ) {
2047+ --m_disasmNavIndex;
2048+ const auto &e = m_disasmNav[m_disasmNavIndex];
2049+ m_isApplyingDisasmNav = true ;
2050+ disasmUpdateAddr (static_cast <int >(e.addr ), e.pane );
2051+ m_isApplyingDisasmNav = false ;
2052+ return true ;
2053+ }
2054+ return false ;
2055+ }
2056+
2057+ bool MainWindow::navDisasmForward () {
2058+ if (m_disasmNavIndex >= 0 && m_disasmNavIndex + 1 < m_disasmNav.size ()) {
2059+ ++m_disasmNavIndex;
2060+ const auto &e = m_disasmNav[m_disasmNavIndex];
2061+ m_isApplyingDisasmNav = true ;
2062+ disasmUpdateAddr (static_cast <int >(e.addr ), e.pane );
2063+ m_isApplyingDisasmNav = false ;
2064+ return true ;
2065+ }
2066+ return false ;
2067+ }
2068+
2069+ void MainWindow::navDisasmClear () {
2070+ m_disasmNav.clear ();
2071+ m_disasmNavIndex = -1 ;
2072+ }
2073+
19672074// ------------------------------------------------
19682075// Misc
19692076// ------------------------------------------------
@@ -1993,7 +2100,8 @@ void MainWindow::gotoPressed() {
19932100}
19942101
19952102void MainWindow::gotoDisasmAddr (uint32_t address) {
1996- disasmUpdateAddr (address, false );
2103+ navDisasmEnsureSeeded ();
2104+ navDisasmPush (address, false );
19972105 raiseContainingDock (ui->disasm );
19982106 ui->disasm ->setFocus ();
19992107}
@@ -2111,6 +2219,16 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *e) {
21112219 return QMainWindow::eventFilter (obj, e);
21122220 }
21132221
2222+ // Mouse back/forward in Disassembly view
2223+ if (obj == m_disasm && e->type () == QEvent::MouseButtonPress) {
2224+ auto *me = static_cast <QMouseEvent*>(e);
2225+ if (me->button () == Qt::BackButton) {
2226+ if (navDisasmBack ()) { e->accept (); return true ; }
2227+ } else if (me->button () == Qt::ForwardButton) {
2228+ if (navDisasmForward ()) { e->accept (); return true ; }
2229+ }
2230+ }
2231+
21142232 if (e->type () == QEvent::MouseButtonPress) {
21152233 QString name = obj->objectName ();
21162234
0 commit comments