From 6d597c50355957c66c304781f3af9f6a0e86e2f9 Mon Sep 17 00:00:00 2001 From: steve Date: Tue, 12 Mar 2019 14:38:09 +0000 Subject: [PATCH] o errors - renamed GopherError to FormattedError - reading files now handled by ioutil.ReadAll(), rather than os.Read() --- debugger/breakpoints.go | 8 ++++---- debugger/commands.go | 4 ++-- debugger/debugger.go | 2 +- debugger/input/validation.go | 16 ++++++++-------- debugger/memory.go | 2 +- debugger/script.go | 24 ++++++------------------ debugger/targets.go | 10 +++++----- debugger/traps.go | 2 +- debugger/watches.go | 2 +- disassembly/parse.go | 2 +- errors/categories.go | 2 +- errors/errors.go | 15 ++++++++------- errors/messages.go | 8 +------- gopher2600.go | 2 +- gui/sdl/requests.go | 6 +++--- gui/sdl/staterecorder.go | 2 +- hardware/cpu/cpu.go | 18 +++++++++--------- hardware/cpu/cpu_test.go | 12 ++++++------ hardware/memory/cartridge.go | 28 ++++++++++++++-------------- hardware/memory/chip.go | 4 ++-- hardware/memory/cpubus.go | 6 +++--- hardware/peripherals/stick.go | 2 +- regression/regression.go | 8 ++++---- symbols/search.go | 2 +- symbols/symbols.go | 18 ++++-------------- television/headless.go | 2 +- television/imagetv/imagetv.go | 12 ++++++------ 27 files changed, 96 insertions(+), 123 deletions(-) diff --git a/debugger/breakpoints.go b/debugger/breakpoints.go index 9a21f440..99822904 100644 --- a/debugger/breakpoints.go +++ b/debugger/breakpoints.go @@ -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) diff --git a/debugger/commands.go b/debugger/commands.go index 6a7a3e8b..14afa966 100644 --- a/debugger/commands.go +++ b/debugger/commands.go @@ -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 diff --git a/debugger/debugger.go b/debugger/debugger.go index a420092a..7d7a852c 100644 --- a/debugger/debugger.go +++ b/debugger/debugger.go @@ -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 diff --git a/debugger/input/validation.go b/debugger/input/validation.go index 583ceb5f..51cf4b92 100644 --- a/debugger/input/validation.go +++ b/debugger/input/validation.go @@ -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])) } } diff --git a/debugger/memory.go b/debugger/memory.go index be71019f..cd047520 100644 --- a/debugger/memory.go +++ b/debugger/memory.go @@ -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) } } diff --git a/debugger/script.go b/debugger/script.go index 15b55ca5..e620841b 100644 --- a/debugger/script.go +++ b/debugger/script.go @@ -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) } } } diff --git a/debugger/targets.go b/debugger/targets.go index 5dfb3668..5fd0cc2a 100644 --- a/debugger/targets.go +++ b/debugger/targets.go @@ -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) } } diff --git a/debugger/traps.go b/debugger/traps.go index 4fbadc69..5eb885c8 100644 --- a/debugger/traps.go +++ b/debugger/traps.go @@ -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] diff --git a/debugger/watches.go b/debugger/watches.go index 1704b365..0497ee2b 100644 --- a/debugger/watches.go +++ b/debugger/watches.go @@ -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] diff --git a/disassembly/parse.go b/disassembly/parse.go index bb2ad183..ee29e897 100644 --- a/disassembly/parse.go +++ b/disassembly/parse.go @@ -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 diff --git a/errors/categories.go b/errors/categories.go index 971a11b0..512d260e 100644 --- a/errors/categories.go +++ b/errors/categories.go @@ -47,7 +47,7 @@ const ( // GUI UnknownGUIRequest - SDLTV + SDL // Peripherals NoControllersFound diff --git a/errors/errors.go b/errors/errors.go index 40fbe01a..ab47021c 100644 --- a/errors/errors.go +++ b/errors/errors.go @@ -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...) } diff --git a/errors/messages.go b/errors/messages.go index 57bd24fb..87d7f534 100644 --- a/errors/messages.go +++ b/errors/messages.go @@ -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" -) diff --git a/gopher2600.go b/gopher2600.go index 904de275..aae1c8a8 100644 --- a/gopher2600.go +++ b/gopher2600.go @@ -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) diff --git a/gui/sdl/requests.go b/gui/sdl/requests.go index e8b11d79..d6865fcc 100644 --- a/gui/sdl/requests.go +++ b/gui/sdl/requests.go @@ -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 diff --git a/gui/sdl/staterecorder.go b/gui/sdl/staterecorder.go index 939169ee..876aaa44 100644 --- a/gui/sdl/staterecorder.go +++ b/gui/sdl/staterecorder.go @@ -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 diff --git a/hardware/cpu/cpu.go b/hardware/cpu/cpu.go index 6031e7e2..34c8e852 100644 --- a/hardware/cpu/cpu.go +++ b/hardware/cpu/cpu.go @@ -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 diff --git a/hardware/cpu/cpu_test.go b/hardware/cpu/cpu_test.go index a83f736a..18d8b721 100644 --- a/hardware/cpu/cpu_test.go +++ b/hardware/cpu/cpu_test.go @@ -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) diff --git a/hardware/memory/cartridge.go b/hardware/memory/cartridge.go index 801ad3a5..db113666 100644 --- a/hardware/memory/cartridge.go +++ b/hardware/memory/cartridge.go @@ -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) } diff --git a/hardware/memory/chip.go b/hardware/memory/chip.go index 228f17fc..52988afa 100644 --- a/hardware/memory/chip.go +++ b/hardware/memory/chip.go @@ -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) } diff --git a/hardware/memory/cpubus.go b/hardware/memory/cpubus.go index 5cdba48b..3ec6d1fb 100644 --- a/hardware/memory/cpubus.go +++ b/hardware/memory/cpubus.go @@ -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 diff --git a/hardware/peripherals/stick.go b/hardware/peripherals/stick.go index 5b21a270..d152be5b 100644 --- a/hardware/peripherals/stick.go +++ b/hardware/peripherals/stick.go @@ -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 } diff --git a/regression/regression.go b/regression/regression.go index c4ed04ce..e50abd6a 100644 --- a/regression/regression.go +++ b/regression/regression.go @@ -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++ diff --git a/symbols/search.go b/symbols/search.go index b6735c9d..9722cec3 100644 --- a/symbols/search.go +++ b/symbols/search.go @@ -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) } diff --git a/symbols/symbols.go b/symbols/symbols.go index 04a66ff0..4600ff2a 100644 --- a/symbols/symbols.go +++ b/symbols/symbols.go @@ -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") diff --git a/television/headless.go b/television/headless.go index 93772738..f0e395b3 100644 --- a/television/headless.go +++ b/television/headless.go @@ -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: diff --git a/television/imagetv/imagetv.go b/television/imagetv/imagetv.go index 0c0ae89e..2b819e52 100644 --- a/television/imagetv/imagetv.go +++ b/television/imagetv/imagetv.go @@ -84,14 +84,14 @@ func (tv *ImageTV) setPixel(x, y int32, red, green, blue byte, vblank bool) erro // _.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