tui

package
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 2, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package tui — breakpoint type and helpers.

The Breakpoints map went from map[uint16]bool to map[uint16]*Breakpoint to support enable/disable, hit counts, conditions, log points, and origin tracking (e.g. resolved-from-source-line).

Package tui — memory access watchpoint type and helpers.

Mirrors the rich exec Breakpoint (see bp.go): enable, hit count, condition, log point. Tracks reads, writes, or both at a single address.

Package tui — bus wrapper that records memory access hits.

WBus sits between the CPU and the underlying RAM (or any cpu.Bus). Each Read/Write checks an addr->MemBP map and, if the access matches a watch, pushes a Hit onto an internal queue. The TUI run-loop drains the queue after every Step() and decides whether to pause / log / increment counters.

Design notes:

  • The map is owned by the Model (not WBus) so :bpr / :bpw command edits don't need any cross-goroutine synchronization. WBus just holds a pointer to the same map header.
  • Hits are pushed to a fixed-capacity ring; if the CPU somehow generates more hits between drains than the ring holds, oldest entries are dropped. This is fine for a debugger — pause-on-hit semantics still fire on the first one that matters.
  • Hot-path branch: if the map is empty we skip the lookup entirely.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DefaultStatePath

func DefaultStatePath(romPath string) string

DefaultStatePath returns ~/.chippy/state-<basename>.json for a given ROM path.

Types

type Breakpoint

type Breakpoint struct {
	Addr     uint16 `json:"addr"`
	Enabled  bool   `json:"enabled"`
	Hits     int    `json:"hits,omitempty"`
	HitLimit int    `json:"hitLimit,omitempty"` // 0 = unlimited; >0 = break on/after Nth hit; -1 = one-shot (auto-delete)
	Cond     string `json:"cond,omitempty"`     // raw expression, "" = unconditional
	Source   string `json:"source,omitempty"`   // optional "file:line" tag from :bp file:line
	Log      string `json:"log,omitempty"`      // log point template; non-empty makes this a logpoint (don't pause)
	Rejected bool   `json:"rejected,omitempty"` // resolution failed; show 💩 marker
	// contains filtered or unexported fields
}

Breakpoint describes a single execution breakpoint. Memory watchpoints have their own type (see wbus.go when implemented).

type MemBP

type MemBP struct {
	Addr     uint16    `json:"addr"`
	Kind     MemBPKind `json:"kind"`
	Enabled  bool      `json:"enabled"`
	Hits     int       `json:"hits,omitempty"`
	HitLimit int       `json:"hitLimit,omitempty"` // 0 unlimited; >0 Nth; -1 one-shot
	Cond     string    `json:"cond,omitempty"`
	Log      string    `json:"log,omitempty"`
	// contains filtered or unexported fields
}

MemBP describes a memory access watchpoint.

type MemBPKind

type MemBPKind string

MemBPKind is one of "r", "w", "rw".

const (
	MemBPRead      MemBPKind = "r"
	MemBPWrite     MemBPKind = "w"
	MemBPReadWrite MemBPKind = "rw"
)

type MemHit

type MemHit struct {
	Addr   uint16
	Kind   MemBPKind // "r" or "w" (never "rw" — that's the watch kind, not the access)
	Value  byte      // value read or written
	PC     uint16    // CPU PC at moment of access
	Cycles uint64    // CPU cycle count at moment of access
}

MemHit is one recorded access to a watched address.

type Model

type Model struct {
	CPU         *cpu.CPU
	RAM         *cpu.RAM
	WBus        *WBus // optional: bus wrapper that records mem watch hits
	Syms        *symbols.Table
	Running     bool
	Breakpoints map[uint16]*Breakpoint
	MemBPs      map[uint16]*MemBP
	MemViewAddr uint16
	Status      string

	// Modals
	ShowHelp bool
	ShowBPs  bool
	BPCursor int // selected row in BP manager

	// Source view
	ShowSource  bool                      // toggle source panel vs disassembly
	SourceFiles map[string][]string       // filename -> lines (1-indexed via [i-1])
	PCToSrc     map[uint16]symbols.SrcLoc // PC -> (file, line)
	DataRanges  []symbols.Range           // [start,end) regions to render as .byte

	// Watch list
	Watches []Watch

	// Run-speed control: target Hz (0 = unthrottled).
	TargetHz int

	// Command prompt ( `:` line editor )
	PromptActive bool
	PromptBuf    string

	// State persistence
	StatePath string

	// Disassembly viewport: when DisasmFollow is true (default), the panel
	// re-anchors on PC each frame. User scroll keys flip it off and pin
	// DisasmAnchor as the address shown at the top of the window.
	DisasmFollow bool
	DisasmAnchor uint16

	W, H int
	// contains filtered or unexported fields
}

func New

func New(c *cpu.CPU, r *cpu.RAM) Model

func (Model) Init

func (m Model) Init() tea.Cmd

func (Model) Update

func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd)

func (Model) View

func (m Model) View() string

func (Model) WithSourceMap

func (m Model) WithSourceMap(sm *symbols.SourceMap) Model

WithSourceMap loads PC->(file,line) mapping from cc65 .dbg file lines.

func (Model) WithStatePath

func (m Model) WithStatePath(p string) Model

WithStatePath enables persistence of breakpoints/mem cursor/watches.

func (Model) WithSymbols

func (m Model) WithSymbols(s *symbols.Table) Model

func (Model) WithWBus

func (m Model) WithWBus(w *WBus) Model

WithWBus attaches a bus wrapper that records memory watchpoint hits. The CPU should already be using this same WBus as its bus. Call after New.

type WBus

type WBus struct {
	Inner cpu.Bus

	// Watches points at Model.MemBPs. nil or empty map -> hot-path skips.
	Watches map[uint16]*MemBP
	// contains filtered or unexported fields
}

WBus wraps an underlying cpu.Bus and reports watched accesses.

func NewWBus

func NewWBus(inner cpu.Bus) *WBus

NewWBus wraps inner. The CPU pointer is needed so hits carry PC/cycle context; pass it after cpu.New(wbus) returns.

func (*WBus) AttachCPU

func (w *WBus) AttachCPU(c *cpu.CPU)

AttachCPU stores the CPU pointer used for hit context. Call once after cpu.New(wbus) so the WBus can record PC/Cycles on each hit.

func (*WBus) Drain

func (w *WBus) Drain() []MemHit

Drain returns up to all currently pending hits in FIFO order and clears the ring. Caller is the Model's run-loop.

func (*WBus) Read

func (w *WBus) Read(addr uint16) byte

func (*WBus) SetWatches

func (w *WBus) SetWatches(m map[uint16]*MemBP)

SetWatches points the wrapper at the live map. Pass Model.MemBPs directly; edits to that map are seen by the wrapper without re-attach.

func (*WBus) Write

func (w *WBus) Write(addr uint16, v byte)

type Watch

type Watch struct {
	// Kind is "mem" (default) or "reg". Empty string treated as "mem" for
	// backward compat with state files written before registers existed.
	Kind  string `json:"kind,omitempty"`
	Addr  uint16 `json:"addr,omitempty"`
	Label string `json:"label,omitempty"`
	Width int    `json:"width,omitempty"` // mem: 1 = byte, 2 = word (LE)
	Reg   string `json:"reg,omitempty"`   // reg: A,X,Y,P,SP,PC
}

Watch is a pinned memory address shown in the watch panel.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL