- renamed GopherError to FormattedError
    - reading files now handled by ioutil.ReadAll(), rather than
    os.Read()
This commit is contained in:
steve 2019-03-12 14:38:09 +00:00
parent 5a223794d4
commit 6d597c5035
27 changed files with 96 additions and 123 deletions

View file

@ -106,7 +106,7 @@ func (bp *breakpoints) clear() {
func (bp *breakpoints) drop(num int) error {
if len(bp.breaks)-1 < num {
return errors.NewGopherError(errors.CommandError, fmt.Errorf("breakpoint #%d is not defined", num))
return errors.NewFormattedError(errors.CommandError, fmt.Errorf("breakpoint #%d is not defined", num))
}
h := bp.breaks[:num]
@ -214,7 +214,7 @@ func (bp *breakpoints) parseBreakpoint(tokens *input.Tokens) error {
// make sure we've not left a previous target dangling without a value
if !resolvedTarget {
return errors.NewGopherError(errors.CommandError, fmt.Errorf("need a value to break on (%s)", tgt.Label()))
return errors.NewFormattedError(errors.CommandError, fmt.Errorf("need a value to break on (%s)", tgt.Label()))
}
// possibly switch composition mode
@ -238,7 +238,7 @@ func (bp *breakpoints) parseBreakpoint(tokens *input.Tokens) error {
}
if !resolvedTarget {
return errors.NewGopherError(errors.CommandError, fmt.Errorf("need a value to break on (%s)", tgt.Label()))
return errors.NewFormattedError(errors.CommandError, fmt.Errorf("need a value to break on (%s)", tgt.Label()))
}
// don't add breakpoints that already exist
@ -262,7 +262,7 @@ func (bp *breakpoints) parseBreakpoint(tokens *input.Tokens) error {
// fail on first error
if duplicate {
return errors.NewGopherError(errors.CommandError, fmt.Errorf("breakpoint already exists (%s)", nb))
return errors.NewFormattedError(errors.CommandError, fmt.Errorf("breakpoint already exists (%s)", nb))
}
bp.breaks = append(bp.breaks, nb)

View file

@ -182,7 +182,7 @@ func (dbg *Debugger) parseCommand(userInput string) (bool, error) {
// many cases to ignore the "success" flag when calling tokens.item()
if err := DebuggerCommands.ValidateInput(tokens); err != nil {
switch err := err.(type) {
case errors.GopherError:
case errors.FormattedError:
switch err.Errno {
case errors.InputEmpty:
// user pressed return
@ -253,7 +253,7 @@ func (dbg *Debugger) parseCommand(userInput string) (bool, error) {
table, symbol, address, err := dbg.disasm.Symtable.SearchSymbol(symbol, symbols.UnspecifiedSymTable)
if err != nil {
switch err := err.(type) {
case errors.GopherError:
case errors.FormattedError:
if err.Errno == errors.SymbolUnknown {
dbg.print(ui.Feedback, "%s -> not found", symbol)
return false, nil

View file

@ -455,7 +455,7 @@ func (dbg *Debugger) inputLoop(mainLoop bool) error {
if err != nil {
switch err := err.(type) {
case errors.GopherError:
case errors.FormattedError:
// do not exit input loop when error is a gopher error
// set lastStepError instead and allow emulation to
// halt

View file

@ -15,7 +15,7 @@ func (options Commands) ValidateInput(newInput *Tokens) error {
// if tokens is empty then return
if len(tokens) == 0 {
return errors.NewGopherError(errors.InputEmpty)
return errors.NewFormattedError(errors.InputEmpty)
}
tokens[0] = strings.ToUpper(tokens[0])
@ -23,29 +23,29 @@ func (options Commands) ValidateInput(newInput *Tokens) error {
// basic check for whether command is recognised
var ok bool
if args, ok = options[tokens[0]]; !ok {
return errors.NewGopherError(errors.CommandError, fmt.Sprintf("%s is not a debugging command", tokens[0]))
return errors.NewFormattedError(errors.CommandError, fmt.Sprintf("%s is not a debugging command", tokens[0]))
}
// too *many* arguments have been supplied
if len(tokens)-1 > args.maximumLen() {
return errors.NewGopherError(errors.CommandError, fmt.Sprintf("too many arguments for %s", tokens[0]))
return errors.NewFormattedError(errors.CommandError, fmt.Sprintf("too many arguments for %s", tokens[0]))
}
// too *few* arguments have been supplied
if len(tokens)-1 < args.requiredLen() {
switch args[len(tokens)-1].typ {
case argKeyword:
return errors.NewGopherError(errors.CommandError, fmt.Sprintf("keyword required for %s", tokens[0]))
return errors.NewFormattedError(errors.CommandError, fmt.Sprintf("keyword required for %s", tokens[0]))
case argFile:
return errors.NewGopherError(errors.CommandError, fmt.Sprintf("filename required for %s", tokens[0]))
return errors.NewFormattedError(errors.CommandError, fmt.Sprintf("filename required for %s", tokens[0]))
case argValue:
return errors.NewGopherError(errors.CommandError, fmt.Sprintf("numeric argument required for %s", tokens[0]))
return errors.NewFormattedError(errors.CommandError, fmt.Sprintf("numeric argument required for %s", tokens[0]))
case argString:
return errors.NewGopherError(errors.CommandError, fmt.Sprintf("string argument required for %s", tokens[0]))
return errors.NewFormattedError(errors.CommandError, fmt.Sprintf("string argument required for %s", tokens[0]))
default:
// TODO: argument types can be OR'd together. breakdown these types
// to give more useful information
return errors.NewGopherError(errors.CommandError, fmt.Sprintf("too few arguments for %s", tokens[0]))
return errors.NewFormattedError(errors.CommandError, fmt.Sprintf("too few arguments for %s", tokens[0]))
}
}

View file

@ -70,7 +70,7 @@ func (mem memoryDebug) mapAddress(address interface{}, cpuPerspective bool) (uin
}
if !mapped {
return 0, errors.NewGopherError(errors.UnrecognisedAddress, address)
return 0, errors.NewFormattedError(errors.UnrecognisedAddress, address)
}
}

View file

@ -4,6 +4,7 @@ import (
"fmt"
"gopher2600/debugger/ui"
"gopher2600/errors"
"io/ioutil"
"os"
"strings"
)
@ -13,28 +14,15 @@ func (dbg *Debugger) loadScript(scriptfile string) ([]string, error) {
// open script and defer closing
sf, err := os.Open(scriptfile)
if err != nil {
return nil, errors.NewGopherError(errors.ScriptFileCannotOpen, err)
return nil, errors.NewFormattedError(errors.ScriptFileCannotOpen, err)
}
defer func() {
_ = sf.Close()
}()
// get file info
sfi, err := sf.Stat()
buffer, err := ioutil.ReadAll(sf)
if err != nil {
return nil, err
}
// allocate enough memory for new cartridge
buffer := make([]uint8, sfi.Size())
// read script file
n, err := sf.Read(buffer)
if err != nil {
return nil, err
}
if n != len(buffer) {
return nil, errors.NewGopherError(errors.ScriptFileError, errors.FileTruncated)
return nil, errors.NewFormattedError(errors.ScriptFileError, err)
}
// convert buffer to an array of lines
@ -68,13 +56,13 @@ func (dbg *Debugger) RunScript(scriptfile string, silent bool) error {
}
next, err := dbg.parseInput(lines[i])
if err != nil {
return errors.NewGopherError(errors.ScriptFileError, err)
return errors.NewFormattedError(errors.ScriptFileError, err)
}
if next {
// make sure run state is still sane
dbg.runUntilHalt = false
return errors.NewGopherError(errors.ScriptRunError, strings.ToUpper(lines[i]), scriptfile, i)
return errors.NewFormattedError(errors.ScriptRunError, strings.ToUpper(lines[i]), scriptfile, i)
}
}
}

View file

@ -149,10 +149,10 @@ func parseTarget(dbg *Debugger, tokens *input.Tokens) (target, error) {
},
}
default:
err = errors.NewGopherError(errors.InvalidTarget, fmt.Sprintf("%s/%s", keyword, subkey))
err = errors.NewFormattedError(errors.InvalidTarget, fmt.Sprintf("%s/%s", keyword, subkey))
}
} else {
err = errors.NewGopherError(errors.InvalidTarget, keyword)
err = errors.NewFormattedError(errors.InvalidTarget, keyword)
}
// cartridge
@ -170,14 +170,14 @@ func parseTarget(dbg *Debugger, tokens *input.Tokens) (target, error) {
},
}
default:
err = errors.NewGopherError(errors.InvalidTarget, fmt.Sprintf("%s/%s", keyword, subkey))
err = errors.NewFormattedError(errors.InvalidTarget, fmt.Sprintf("%s/%s", keyword, subkey))
}
} else {
err = errors.NewGopherError(errors.InvalidTarget, keyword)
err = errors.NewFormattedError(errors.InvalidTarget, keyword)
}
default:
err = errors.NewGopherError(errors.InvalidTarget, keyword)
err = errors.NewFormattedError(errors.InvalidTarget, keyword)
}
}

View file

@ -38,7 +38,7 @@ func (tr *traps) clear() {
func (tr *traps) drop(num int) error {
if len(tr.traps)-1 < num {
return errors.NewGopherError(errors.CommandError, fmt.Errorf("trap #%d is not defined", num))
return errors.NewFormattedError(errors.CommandError, fmt.Errorf("trap #%d is not defined", num))
}
h := tr.traps[:num]

View file

@ -72,7 +72,7 @@ func (wtc *watches) clear() {
func (wtc *watches) drop(num int) error {
if len(wtc.watches)-1 < num {
return errors.NewGopherError(errors.CommandError, fmt.Errorf("watch #%d is not defined", num))
return errors.NewFormattedError(errors.CommandError, fmt.Errorf("watch #%d is not defined", num))
}
h := wtc.watches[:num]

View file

@ -17,7 +17,7 @@ func (dsm *Disassembly) parseLoop(mc *cpu.CPU) error {
// filter out some errors
if err != nil {
switch err := err.(type) {
case errors.GopherError:
case errors.FormattedError:
switch err.Errno {
case errors.ProgramCounterCycled:
return nil

View file

@ -47,7 +47,7 @@ const (
// GUI
UnknownGUIRequest
SDLTV
SDL
// Peripherals
NoControllersFound

View file

@ -5,23 +5,24 @@ import "fmt"
// Errno is used specified the specific error
type Errno int
// Values is the type used to specify arguments for a GopherError
// Values is the type used to specify arguments for FormattedErrors
type Values []interface{}
// GopherError is the error type used by Gopher2600
type GopherError struct {
// FormattedError provides a convenient way of providing arguments to a
// predefined error
type FormattedError struct {
Errno Errno
Values Values
}
// NewGopherError is used to create a Gopher2600 specific error
func NewGopherError(errno Errno, values ...interface{}) GopherError {
ge := new(GopherError)
// NewFormattedError is used to create a new instance of a FormattedError
func NewFormattedError(errno Errno, values ...interface{}) FormattedError {
ge := new(FormattedError)
ge.Errno = errno
ge.Values = values
return *ge
}
func (er GopherError) Error() string {
func (er FormattedError) Error() string {
return fmt.Sprintf(messages[er.Errno], er.Values...)
}

View file

@ -46,14 +46,8 @@ var messages = map[Errno]string{
// GUI
UnknownGUIRequest: "GUI does not support %v request",
SDLTV: "SDLTV: %s",
SDL: "SDL: %s",
// Peripherals
NoControllersFound: "no controllers found",
}
// more error strings -- these are strings that are used as arguments to error
// string messages
const (
FileTruncated string = "file truncated"
)

View file

@ -121,7 +121,7 @@ func main() {
dsm, err := disassembly.NewDisassembly(modeFlags.Arg(0))
if err != nil {
switch err.(type) {
case errors.GopherError:
case errors.FormattedError:
// print what disassembly output we do have
if dsm != nil {
dsm.Dump(os.Stdout)

View file

@ -21,7 +21,7 @@ func (tv *GUI) GetMetaState(request gui.MetaStateReq) (interface{}, error) {
case gui.ReqLastMouseScanline:
return tv.crit.lastMouseScanline, nil
default:
return nil, errors.NewGopherError(errors.UnknownGUIRequest, request)
return nil, errors.NewFormattedError(errors.UnknownGUIRequest, request)
}
}
@ -43,7 +43,7 @@ func (tv *GUI) RegisterCallback(request gui.CallbackReq, channel chan func(), ca
tv.onMouseButtonRight.channel = channel
tv.onMouseButtonRight.function = callback
default:
return errors.NewGopherError(errors.UnknownGUIRequest, request)
return errors.NewFormattedError(errors.UnknownGUIRequest, request)
}
return nil
@ -120,7 +120,7 @@ func (tv *GUI) SetFeature(request gui.FeatureReq, args ...interface{}) error {
}
default:
return errors.NewGopherError(errors.UnknownGUIRequest, request)
return errors.NewFormattedError(errors.UnknownGUIRequest, request)
}
return nil

View file

@ -67,7 +67,7 @@ func (overlay *systemStateOverlay) setPixel(attr monitor.SystemState) error {
// label required...
if attr.Label == "" {
errors.NewGopherError(errors.CannotRecordState, "recording of system state requires a label")
errors.NewFormattedError(errors.CannotRecordState, "recording of system state requires a label")
}
// ... however, if a group has been supplied, use that to assign color

View file

@ -104,7 +104,7 @@ func (mc *CPU) IsExecuting() bool {
func (mc *CPU) Reset() error {
// sanity check
if mc.IsExecuting() {
return errors.NewGopherError(errors.InvalidOperationMidInstruction, "reset")
return errors.NewFormattedError(errors.InvalidOperationMidInstruction, "reset")
}
mc.PC.Load(0)
@ -127,7 +127,7 @@ func (mc *CPU) Reset() error {
func (mc *CPU) LoadPCIndirect(indirectAddress uint16) error {
// sanity check
if mc.IsExecuting() {
return errors.NewGopherError(errors.InvalidOperationMidInstruction, "load PC")
return errors.NewFormattedError(errors.InvalidOperationMidInstruction, "load PC")
}
// because we call this LoadPC() outside of the CPU's ExecuteInstruction()
@ -151,7 +151,7 @@ func (mc *CPU) LoadPCIndirect(indirectAddress uint16) error {
func (mc *CPU) LoadPC(directAddress uint16) error {
// sanity check
if mc.IsExecuting() {
return errors.NewGopherError(errors.InvalidOperationMidInstruction, "load PC")
return errors.NewFormattedError(errors.InvalidOperationMidInstruction, "load PC")
}
// because we call this LoadPC() outside of the CPU's ExecuteInstruction()
@ -175,7 +175,7 @@ func (mc *CPU) write8Bit(address uint16, value uint8) error {
if err != nil {
switch err := err.(type) {
case errors.GopherError:
case errors.FormattedError:
// don't worry about unwritable addresses (unless strict addressing
// is on)
if mc.StrictAddressing || err.Errno != errors.UnwritableAddress {
@ -195,7 +195,7 @@ func (mc *CPU) read8Bit(address uint16) (uint8, error) {
if err != nil {
switch err := err.(type) {
case errors.GopherError:
case errors.FormattedError:
// don't worry about unreadable addresses (unless strict addressing
// is on)
if mc.StrictAddressing || err.Errno != errors.UnreadableAddress {
@ -237,7 +237,7 @@ func (mc *CPU) read8BitPC() (uint8, error) {
}
carry, _ := mc.PC.Add(1, false)
if carry {
return 0, errors.NewGopherError(errors.ProgramCounterCycled, nil)
return 0, errors.NewFormattedError(errors.ProgramCounterCycled, nil)
}
return op, nil
}
@ -252,7 +252,7 @@ func (mc *CPU) read16BitPC() (uint16, error) {
// the next instruction but I don't believe this has any side-effects
carry, _ := mc.PC.Add(2, false)
if carry {
return 0, errors.NewGopherError(errors.ProgramCounterCycled, nil)
return 0, errors.NewFormattedError(errors.ProgramCounterCycled, nil)
}
return val, nil
@ -362,10 +362,10 @@ func (mc *CPU) ExecuteInstruction(cycleCallback func(*result.Instruction)) (*res
// has wandered into data memory - most likely to occur during
// disassembly.
if (operator>>4)%2 == 1 {
return nil, errors.NewGopherError(errors.InvalidOpcode, fmt.Sprintf("%02x", operator))
return nil, errors.NewFormattedError(errors.InvalidOpcode, fmt.Sprintf("%02x", operator))
}
return nil, errors.NewGopherError(errors.UnimplementedInstruction, operator, mc.PC.ToUint16()-1)
return nil, errors.NewFormattedError(errors.UnimplementedInstruction, operator, mc.PC.ToUint16()-1)
}
result.Defn = defn

View file

@ -46,14 +46,14 @@ func (mem *mockMem) Clear() {
func (mem mockMem) Read(address uint16) (uint8, error) {
if address&0xff00 == 0xff00 {
return 0, errors.NewGopherError(errors.UnreadableAddress, address)
return 0, errors.NewFormattedError(errors.UnreadableAddress, address)
}
return mem.internal[address], nil
}
func (mem *mockMem) Write(address uint16, data uint8) error {
if address&0xff00 == 0xff00 {
return errors.NewGopherError(errors.UnwritableAddress, address)
return errors.NewFormattedError(errors.UnwritableAddress, address)
}
mem.internal[address] = data
return nil
@ -539,7 +539,7 @@ func testStrictAddressing(t *testing.T, mc *cpu.CPU, mem *mockMem) {
origin = mem.putInstructions(origin, 0x8d, 0x00, 0xff)
_, err := mc.ExecuteInstruction(func(*result.Instruction) {})
if err != nil {
if err.(errors.GopherError).Errno == errors.UnwritableAddress {
if err.(errors.FormattedError).Errno == errors.UnwritableAddress {
t.Fatalf("recieved an UnwritableAddress error when we shouldn't")
}
t.Fatalf("error during CPU step (%v)\n", err)
@ -552,7 +552,7 @@ func testStrictAddressing(t *testing.T, mc *cpu.CPU, mem *mockMem) {
if err == nil {
t.Fatalf("not recieved an UnwritableAddress error when we should")
}
if err.(errors.GopherError).Errno == errors.UnwritableAddress {
if err.(errors.FormattedError).Errno == errors.UnwritableAddress {
// this is okay
} else {
t.Fatalf("error during CPU step (%v)\n", err)
@ -563,7 +563,7 @@ func testStrictAddressing(t *testing.T, mc *cpu.CPU, mem *mockMem) {
origin = mem.putInstructions(origin, 0xad, 0x00, 0xff)
_, err = mc.ExecuteInstruction(func(*result.Instruction) {})
if err != nil {
if err.(errors.GopherError).Errno == errors.UnreadableAddress {
if err.(errors.FormattedError).Errno == errors.UnreadableAddress {
t.Fatalf("recieved an UnreadableAddress we shouldn't")
}
t.Fatalf("error during CPU step (%v)\n", err)
@ -576,7 +576,7 @@ func testStrictAddressing(t *testing.T, mc *cpu.CPU, mem *mockMem) {
if err == nil {
t.Fatalf("not recieved an UnreadableAddress error when we should")
}
if err.(errors.GopherError).Errno == errors.UnreadableAddress {
if err.(errors.FormattedError).Errno == errors.UnreadableAddress {
// this is okay
} else {
t.Fatalf("error during CPU step (%v)\n", err)

View file

@ -86,7 +86,7 @@ func (cart *Cartridge) Clear() {
// Implementation of CPUBus.Read
func (cart Cartridge) Read(address uint16) (uint8, error) {
if len(cart.memory) == 0 {
return 0, errors.NewGopherError(errors.CartridgeMissing)
return 0, errors.NewFormattedError(errors.CartridgeMissing)
}
return cart.readHook(cart.origin | address ^ cart.origin)
}
@ -120,7 +120,7 @@ func (cart *Cartridge) readBanks(file io.ReadSeeker, numBanks int) error {
return err
}
if n != 4096 {
return errors.NewGopherError(errors.CartridgeFileError, errors.FileTruncated)
return errors.NewFormattedError(errors.CartridgeFileError, "not enough bytes in the cartridge file")
}
}
}
@ -132,7 +132,7 @@ func (cart *Cartridge) readBanks(file io.ReadSeeker, numBanks int) error {
func (cart *Cartridge) Attach(filename string) error {
cf, err := os.Open(filename)
if err != nil {
return errors.NewGopherError(errors.CartridgeFileError, err)
return errors.NewFormattedError(errors.CartridgeFileError, err)
}
defer func() {
_ = cf.Close()
@ -148,11 +148,11 @@ func (cart *Cartridge) Attach(filename string) error {
// set default read hooks
cart.readHook = func(addr uint16) (uint8, error) {
return 0, errors.NewGopherError(errors.UnreadableAddress, addr)
return 0, errors.NewFormattedError(errors.UnreadableAddress, addr)
}
cart.writeHook = func(addr uint16, data uint8) error {
return errors.NewGopherError(errors.UnwritableAddress, addr)
return errors.NewFormattedError(errors.UnwritableAddress, addr)
}
// how cartridges are mapped into the 4k space can differs dramatically.
@ -227,7 +227,7 @@ func (cart *Cartridge) Attach(filename string) error {
} else if addr == 0x0ff9 {
cart.Bank = 1
} else {
return errors.NewGopherError(errors.UnwritableAddress, addr)
return errors.NewFormattedError(errors.UnwritableAddress, addr)
}
return nil
}
@ -239,7 +239,7 @@ func (cart *Cartridge) Attach(filename string) error {
// o Montezuma's Revenge
case 12288:
return errors.NewGopherError(errors.CartridgeUnsupported, "12288 bytes not yet supported")
return errors.NewFormattedError(errors.CartridgeUnsupported, "12288 bytes not yet supported")
case 16384:
cart.readBanks(cf, 4)
@ -278,7 +278,7 @@ func (cart *Cartridge) Attach(filename string) error {
} else if addr == 0x0ff9 {
cart.Bank = 3
} else {
return errors.NewGopherError(errors.UnwritableAddress, addr)
return errors.NewFormattedError(errors.UnwritableAddress, addr)
}
return nil
}
@ -336,7 +336,7 @@ func (cart *Cartridge) Attach(filename string) error {
} else if addr == 0x0ffb {
cart.Bank = 7
} else {
return errors.NewGopherError(errors.UnwritableAddress, addr)
return errors.NewFormattedError(errors.UnwritableAddress, addr)
}
return nil
}
@ -344,11 +344,11 @@ func (cart *Cartridge) Attach(filename string) error {
cart.addCartridgeRAM()
case 65536:
return errors.NewGopherError(errors.CartridgeUnsupported, "65536 bytes not yet supported")
return errors.NewFormattedError(errors.CartridgeUnsupported, "65536 bytes not yet supported")
default:
cart.Eject()
return errors.NewGopherError(errors.CartridgeUnsupported, fmt.Sprintf("unrecognised cartridge size (%d bytes)", cfi.Size()))
return errors.NewFormattedError(errors.CartridgeUnsupported, fmt.Sprintf("unrecognised cartridge size (%d bytes)", cfi.Size()))
}
// note name of cartridge
@ -407,7 +407,7 @@ func (cart *Cartridge) addCartridgeRAM() bool {
// BankSwitch changes the current bank number
func (cart *Cartridge) BankSwitch(bank int) error {
if bank > cart.NumBanks {
return errors.NewGopherError(errors.CartridgeNoSuchBank, bank, cart.NumBanks)
return errors.NewFormattedError(errors.CartridgeNoSuchBank, bank, cart.NumBanks)
}
cart.Bank = bank
return nil
@ -429,7 +429,7 @@ func (cart *Cartridge) Eject() {
// Peek is the implementation of Memory.Area.Peek
func (cart Cartridge) Peek(address uint16) (uint8, uint16, string, string, error) {
if len(cart.memory) == 0 {
return 0, 0, "", "", errors.NewGopherError(errors.CartridgeMissing)
return 0, 0, "", "", errors.NewFormattedError(errors.CartridgeMissing)
}
return cart.memory[cart.Bank][cart.origin|address^cart.origin], address, cart.Label(), "", nil
}
@ -438,5 +438,5 @@ func (cart Cartridge) Peek(address uint16) (uint8, uint16, string, string, error
func (cart Cartridge) Poke(address uint16, value uint8) error {
// if we want to poke cartridge memory we need to account for different
// cartridge sizes.
return errors.NewGopherError(errors.UnPokeableAddress, address)
return errors.NewFormattedError(errors.UnPokeableAddress, address)
}

View file

@ -63,12 +63,12 @@ func (area ChipMemory) Memtop() uint16 {
func (area ChipMemory) Peek(address uint16) (uint8, uint16, string, string, error) {
sym := vcssymbols.ReadSymbols[address]
if sym == "" {
return 0, 0, "", "", errors.NewGopherError(errors.UnreadableAddress, address)
return 0, 0, "", "", errors.NewFormattedError(errors.UnreadableAddress, address)
}
return area.memory[address-area.origin], address, area.Label(), sym, nil
}
// Poke is the implementation of Memory.Area.Poke
func (area ChipMemory) Poke(address uint16, value uint8) error {
return errors.NewGopherError(errors.UnPokeableAddress, address)
return errors.NewFormattedError(errors.UnPokeableAddress, address)
}

View file

@ -14,7 +14,7 @@ func (area *ChipMemory) Read(address uint16) (uint8, error) {
sym := vcssymbols.ReadSymbols[address]
if sym == "" {
return 0, errors.NewGopherError(errors.UnreadableAddress, address)
return 0, errors.NewFormattedError(errors.UnreadableAddress, address)
}
return area.memory[area.origin|address^area.origin], nil
@ -26,12 +26,12 @@ func (area *ChipMemory) Write(address uint16, data uint8) error {
// check that the last write to this memory area has been serviced
if area.writeSignal {
return errors.NewGopherError(errors.UnservicedChipWrite, vcssymbols.WriteSymbols[area.lastWriteAddress])
return errors.NewFormattedError(errors.UnservicedChipWrite, vcssymbols.WriteSymbols[area.lastWriteAddress])
}
sym := vcssymbols.WriteSymbols[address]
if sym == "" {
return errors.NewGopherError(errors.UnwritableAddress, address)
return errors.NewFormattedError(errors.UnwritableAddress, address)
}
// note address of write

View file

@ -33,7 +33,7 @@ func NewStick(tia memory.PeriphBus, riot memory.PeriphBus, panel *Panel) *Stick
// system assigned index: typically increments on each new controller added.
stick.device = joysticks.Connect(1)
if stick.device == nil {
stick.err = errors.NewGopherError(errors.NoControllersFound, nil)
stick.err = errors.NewFormattedError(errors.NoControllersFound, nil)
return
}

View file

@ -203,10 +203,10 @@ func addCartridge(cartridgeFile string, tvMode string, numOfFrames int, allowUpd
if allowUpdate == false {
if existEntry, ok := db.entries[entry.key]; ok {
if existEntry.cartridgeFile == entry.cartridgeFile {
return errors.NewGopherError(errors.RegressionEntryExists, entry)
return errors.NewFormattedError(errors.RegressionEntryExists, entry)
}
return errors.NewGopherError(errors.RegressionEntryCollision, entry.cartridgeFile, existEntry.cartridgeFile)
return errors.NewFormattedError(errors.RegressionEntryCollision, entry.cartridgeFile, existEntry.cartridgeFile)
}
}
@ -229,7 +229,7 @@ func RegressDeleteCartridge(cartridgeFile string) error {
}
if _, ok := db.entries[key]; ok == false {
return errors.NewGopherError(errors.RegressionEntryDoesNotExist, cartridgeFile)
return errors.NewFormattedError(errors.RegressionEntryDoesNotExist, cartridgeFile)
}
delete(db.entries, key)
@ -262,7 +262,7 @@ func RegressRunTests(output io.Writer, failOnError bool) (int, int, error) {
if err != nil || entry.digest != digest {
if err == nil {
err = errors.NewGopherError(errors.RegressionEntryFail, entry)
err = errors.NewFormattedError(errors.RegressionEntryFail, entry)
}
numFail++

View file

@ -46,5 +46,5 @@ func (sym *Table) SearchSymbol(symbol string, table TableType) (TableType, strin
}
}
return UnspecifiedSymTable, symbol, 0, errors.NewGopherError(errors.SymbolUnknown, symbol)
return UnspecifiedSymTable, symbol, 0, errors.NewFormattedError(errors.SymbolUnknown, symbol)
}

View file

@ -4,6 +4,7 @@ import (
"fmt"
"gopher2600/errors"
"gopher2600/hardware/memory/vcssymbols"
"io/ioutil"
"os"
"path"
"strconv"
@ -69,26 +70,15 @@ func ReadSymbolsFile(cartridgeFilename string) (*Table, error) {
if cartridgeFilename == "" {
return table, nil
}
return table, errors.NewGopherError(errors.SymbolsFileCannotOpen, cartridgeFilename)
return nil, errors.NewFormattedError(errors.SymbolsFileCannotOpen, cartridgeFilename)
}
defer func() {
_ = sf.Close()
}()
// get file info of symbols file
sfi, err := sf.Stat()
sym, err := ioutil.ReadAll(sf)
if err != nil {
return table, errors.NewGopherError(errors.SymbolsFileError, err)
}
// read symbols file and split into lines
sym := make([]byte, sfi.Size())
n, err := sf.Read(sym)
if err != nil {
return table, errors.NewGopherError(errors.SymbolsFileError, err)
}
if n != len(sym) {
return table, errors.NewGopherError(errors.SymbolsFileError, errors.FileTruncated)
return nil, errors.NewFormattedError(errors.SymbolsFileError, err)
}
lines := strings.Split(string(sym), "\n")

View file

@ -273,7 +273,7 @@ func (tv *HeadlessTV) SystemStateRecord(monitor.SystemState) error {
func (tv *HeadlessTV) GetState(request StateReq) (interface{}, error) {
switch request {
default:
return nil, errors.NewGopherError(errors.UnknownTVRequest, request)
return nil, errors.NewFormattedError(errors.UnknownTVRequest, request)
case ReqFramenum:
return tv.frameNum, nil
case ReqScanline:

View file

@ -84,14 +84,14 @@ func (tv *ImageTV) setPixel(x, y int32, red, green, blue byte, vblank bool) erro
// <group/<label>_<framenum>.png
func (tv *ImageTV) SystemStateRecord(state monitor.SystemState) error {
if state.Label == "" || state.Group == "" {
return errors.NewGopherError(errors.ImageTV, "SystemStateRecord requires a Label and Group")
return errors.NewFormattedError(errors.ImageTV, "SystemStateRecord requires a Label and Group")
}
return tv.save(filepath.Join(state.Group, state.Label))
}
func (tv *ImageTV) save(fileNameBase string) error {
if tv.lastImage == nil {
return errors.NewGopherError(errors.ImageTV, "no data to save")
return errors.NewFormattedError(errors.ImageTV, "no data to save")
}
// prepare filename for image
@ -100,22 +100,22 @@ func (tv *ImageTV) save(fileNameBase string) error {
f, err := os.Open(imageName)
if f != nil {
f.Close()
return errors.NewGopherError(errors.ImageTV, fmt.Errorf("image file (%s) already exists", imageName))
return errors.NewFormattedError(errors.ImageTV, fmt.Errorf("image file (%s) already exists", imageName))
}
if err != nil && !os.IsNotExist(err) {
return errors.NewGopherError(errors.ImageTV, err)
return errors.NewFormattedError(errors.ImageTV, err)
}
f, err = os.Create(imageName)
if err != nil {
return errors.NewGopherError(errors.ImageTV, err)
return errors.NewFormattedError(errors.ImageTV, err)
}
defer f.Close()
err = png.Encode(f, tv.lastImage)
if err != nil {
return errors.NewGopherError(errors.ImageTV, err)
return errors.NewFormattedError(errors.ImageTV, err)
}
return nil