Gopher2600/debugger/prompt.go
JetSetIlly 92376586ca CoProcIsActive() replaced with CoProcState()
returns a CoProcState value rather than a boolean value

updated prompt building and debugger reflection overlays to work with
new type and values

commentary introduces the idea that coprocessor state is about VCS
synchronisation

ELF will call ExecutionStart() and ExecutionEnd() as appropriate for the
change of state. this needs work because the meaning of "Execution" in
context of StrongARM type synchronisation is unclear
2022-08-20 21:00:20 +01:00

87 lines
3 KiB
Go

// This file is part of Gopher2600.
//
// Gopher2600 is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Gopher2600 is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Gopher2600. If not, see <https://www.gnu.org/licenses/>.
package debugger
import (
"fmt"
"strings"
"github.com/jetsetilly/gopher2600/debugger/terminal"
"github.com/jetsetilly/gopher2600/disassembly"
"github.com/jetsetilly/gopher2600/hardware/memory/cartridge/mapper"
)
func (dbg *Debugger) buildPrompt() terminal.Prompt {
content := strings.Builder{}
// to keep things simple for now, only the idle coprocessor state will
// result in a detailed 6507 prompt. the other states are better served
// (for now) by a descriptive prompt without any disassembly
//
// TODO: better prompts for non-idle coprocessor states
switch dbg.vcs.Mem.Cart.CoProcState() {
case mapper.CoProcNOPFeed:
content.WriteString(fmt.Sprintf("$%04x (NOP feed)", dbg.vcs.CPU.PC.Address()))
case mapper.CoProcStrongARMFeed:
content.WriteString(fmt.Sprintf("$%04x (StrongARM feed)", dbg.vcs.CPU.PC.Address()))
case mapper.CoProcParallel:
content.WriteString(fmt.Sprintf("$%04x (parallel)", dbg.vcs.CPU.PC.Address()))
case mapper.CoProcIdle:
var e *disassembly.Entry
// decide which address value to use
if dbg.vcs.CPU.LastResult.Final || dbg.vcs.CPU.HasReset() {
e = dbg.Disasm.GetEntryByAddress(dbg.vcs.CPU.PC.Address())
} else {
// if we're in the middle of an instruction then use the addresss in
// lastResult. in these instances we want the prompt to report the
// instruction that the CPU is working on, not the next one to be
// stepped into.
e = dbg.liveDisasmEntry
}
// build prompt based on how confident we are of the contents of the
// disassembly entry. starting with the condition of no disassembly at all
if e == nil {
content.WriteString(fmt.Sprintf("$%04x", dbg.vcs.CPU.PC.Address()))
} else if e.Level == disassembly.EntryLevelUnmappable {
content.WriteString(e.Address)
} else {
// this is the ideal path. the address is in the disassembly and we've
// decoded it already
content.WriteString(fmt.Sprintf("%s %s", e.Address, e.Operator))
if e.Operand.String() != "" {
content.WriteString(fmt.Sprintf(" %s", e.Operand))
}
}
}
p := terminal.Prompt{
Content: content.String(),
Recording: dbg.scriptScribe.IsActive(),
CPURdy: dbg.vcs.CPU.RdyFlg,
}
// LastResult final is false on CPU reset so we must check for that also
if dbg.vcs.CPU.LastResult.Final || dbg.vcs.CPU.HasReset() {
p.Type = terminal.PromptTypeCPUStep
} else {
p.Type = terminal.PromptTypeVideoStep
}
return p
}