Gopher2600/disassembly/preferences.go
2024-01-16 10:54:54 +00:00

131 lines
3.5 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 disassembly
import (
"fmt"
"github.com/jetsetilly/gopher2600/hardware/memory/memorymap"
"github.com/jetsetilly/gopher2600/prefs"
"github.com/jetsetilly/gopher2600/resources"
)
type Preferences struct {
dsm *Disassembly
dsk *prefs.Disk
// whether to apply the high mirror bits to the displayed address
FxxxMirror prefs.Bool
Symbols prefs.Bool
// the lowest value to use when formatting address values. changed by the
// preferences system
mirrorOrigin uint16
}
func (p *Preferences) String() string {
return p.dsk.String()
}
// newPreferences is the preferred method of initialisation for the Preferences type.
func newPreferences(dsm *Disassembly) (*Preferences, error) {
p := &Preferences{dsm: dsm}
p.FxxxMirror.SetHookPost(func(v prefs.Value) error {
if v.(bool) {
p.mirrorOrigin = memorymap.OriginCartFxxxMirror
} else {
p.mirrorOrigin = memorymap.OriginCart
}
dsm.setCartMirror()
return nil
})
p.SetDefaults()
pth, err := resources.JoinPath(prefs.DefaultPrefsFile)
if err != nil {
return nil, err
}
p.dsk, err = prefs.NewDisk(pth)
if err != nil {
return nil, err
}
err = p.dsk.Add("disassembly.fxxxMirror", &p.FxxxMirror)
if err != nil {
return nil, err
}
err = p.dsk.Add("disassembly.symbols", &p.Symbols)
if err != nil {
return nil, err
}
err = p.dsk.Load(true)
if err != nil {
return nil, err
}
return p, nil
}
// SetDefaults reverts all settings to default values.
func (p *Preferences) SetDefaults() {
p.FxxxMirror.Set(true)
p.Symbols.Set(true)
p.mirrorOrigin = memorymap.OriginCartFxxxMirror
}
// Load disassembly preferences and apply to the current disassembly.
func (p *Preferences) Load() error {
return p.dsk.Load(false)
}
// Save current disassembly preferences to disk.
func (p *Preferences) Save() error {
return p.dsk.Save()
}
// setCartMirror sets the mirror bits to the user's preference. called by the
// FxxxMirror callback.
func (dsm *Disassembly) setCartMirror() {
dsm.crit.Lock()
defer dsm.crit.Unlock()
for b := range dsm.disasmEntries.Entries {
for _, e := range dsm.disasmEntries.Entries[b] {
if e == nil {
continue
}
// mask off bits that indicate the cartridge/segment origin and reset
// them with the chosen origin
a := e.Result.Address&memorymap.CartridgeBits | dsm.Prefs.mirrorOrigin
e.Address = fmt.Sprintf("$%04x", a)
// branch instructions need special handling because for readability we
// translate the offset to an absolute address, which has changed.
if e.Result.Defn != nil && e.Result.Defn.IsBranch() {
// mask off bits that indicate the cartridge/segment origin and reset
// them with the chosen origin
a := e.Result.Address&memorymap.CartridgeBits | dsm.Prefs.mirrorOrigin
e.Operand.partial = fmt.Sprintf("$%04x", absoluteBranchDestination(a, e.Result.InstructionData))
}
}
}
}