From f92bc2b08ece95e13aebabe5089e5ef7a42c177e Mon Sep 17 00:00:00 2001 From: Ivan Izaguirre Date: Sun, 6 Oct 2019 01:26:00 +0200 Subject: [PATCH] Proper Go error management --- apple2.go | 96 +++++++++++++++++++++++++-------- apple2Setup.go | 56 ++++++++++++++------ apple2main.go | 30 +++++++++-- apple2sdl/sdlKeyboard.go | 8 ++- base64a.go | 22 +++++--- cardBase.go | 8 +-- cardDisk2.go | 112 ++++++++++++++++++++++++++++++--------- cardHardDisk.go | 3 +- cardInOut.go | 2 +- cardLanguage.go | 68 ++++++++++++++++++------ cardSaturn.go | 75 +++++++++++++++++++------- characterGenerator.go | 20 ++++--- core6502/addressing.go | 2 +- core6502/execute.go | 24 +++++++-- core6502/memory.go | 6 ++- diskette16sector.go | 20 ++++--- hardDisk.go | 29 +++++----- ioC0Page.go | 8 +-- memoryManager.go | 27 +++++++--- memoryRange.go | 26 ++++++--- resources.go | 12 ++--- screen.go | 10 ++-- 22 files changed, 486 insertions(+), 178 deletions(-) diff --git a/apple2.go b/apple2.go index 41701c6..7ebab0b 100644 --- a/apple2.go +++ b/apple2.go @@ -109,10 +109,16 @@ func (a *Apple2) executeCommand(command int) { a.isColor = !a.isColor case CommandSaveState: fmt.Println("Saving state") - a.save("apple2.state") + err := a.save("apple2.state") + if err != nil { + fmt.Printf("Error loadind state: %v.", err) + } case CommandLoadState: fmt.Println("Loading state") - a.load("apple2.state") + err := a.load("apple2.state") + if err != nil { + fmt.Printf("Error loadind state: %v.", err) + } case CommandDumpDebugInfo: a.dumpDebugInfo() case CommandNextCharGenPage: @@ -137,55 +143,99 @@ func (a *Apple2) releaseFastMode() { } type persistent interface { - save(io.Writer) - load(io.Reader) + save(io.Writer) error + load(io.Reader) error } -func (a *Apple2) save(filename string) { +func (a *Apple2) save(filename string) error { f, err := os.Create(filename) if err != nil { - panic(err) + return err } defer f.Close() w := bufio.NewWriter(f) defer w.Flush() - a.cpu.Save(w) - a.mmu.save(w) - a.io.save(w) - binary.Write(w, binary.BigEndian, a.isColor) - binary.Write(w, binary.BigEndian, a.fastMode) - binary.Write(w, binary.BigEndian, a.fastRequestsCounter) + err = a.cpu.Save(w) + if err != nil { + return err + } + err = a.mmu.save(w) + if err != nil { + return err + } + err = a.io.save(w) + if err != nil { + return err + } + err = binary.Write(w, binary.BigEndian, a.isColor) + if err != nil { + return err + } + err = binary.Write(w, binary.BigEndian, a.fastMode) + if err != nil { + return err + } + err = binary.Write(w, binary.BigEndian, a.fastRequestsCounter) + if err != nil { + return err + } for _, c := range a.cards { if c != nil { - c.save(w) + err = c.save(w) + if err != nil { + return err + } } } + return nil } -func (a *Apple2) load(filename string) { +func (a *Apple2) load(filename string) error { f, err := os.Open(filename) if err != nil { - // Ignore error if can't load the file - return + return err } defer f.Close() r := bufio.NewReader(f) - a.cpu.Load(r) - a.mmu.load(r) - a.io.load(r) - binary.Read(r, binary.BigEndian, &a.isColor) - binary.Read(r, binary.BigEndian, &a.fastMode) - binary.Read(r, binary.BigEndian, &a.fastRequestsCounter) + err = a.cpu.Load(r) + if err != nil { + return err + } + err = a.mmu.load(r) + if err != nil { + return err + } + err = a.io.load(r) + if err != nil { + return err + } + err = binary.Read(r, binary.BigEndian, &a.isColor) + if err != nil { + return err + } + err = binary.Read(r, binary.BigEndian, &a.fastMode) + if err != nil { + return err + } + err = binary.Read(r, binary.BigEndian, &a.fastRequestsCounter) + if err != nil { + return err + } for _, c := range a.cards { if c != nil { - c.load(r) + err = c.load(r) + if err != nil { + return err + } } } + + return nil } func (a *Apple2) dumpDebugInfo() { diff --git a/apple2Setup.go b/apple2Setup.go index cd80757..607706a 100644 --- a/apple2Setup.go +++ b/apple2Setup.go @@ -1,18 +1,18 @@ package apple2 -import "github.com/ivanizag/apple2/core6502" +import ( + "errors" + + "github.com/ivanizag/apple2/core6502" +) // NewApple2 instantiates an apple2 -func NewApple2(charRomFile string, clockMhz float64, - isColor bool, fastMode bool) *Apple2 { +func NewApple2(clockMhz float64, isColor bool, fastMode bool) *Apple2 { var a Apple2 a.Name = "Apple ][+" a.mmu = newMemoryManager(&a) a.cpu = core6502.NewNMOS6502(a.mmu) - if charRomFile != "" { - a.cg = NewCharacterGenerator(charRomFile) - } a.commandChannel = make(chan int, 100) a.isColor = isColor a.fastMode = fastMode @@ -42,11 +42,15 @@ const ( ) // LoadRom loads a standard Apple2+ or 2e ROM -func (a *Apple2) LoadRom(filename string) { - data := loadResource(filename) +func (a *Apple2) LoadRom(filename string) error { + data, err := loadResource(filename) + if err != nil { + return err + } + size := len(data) if size != apple2RomSize && size != apple2eRomSize { - panic("Rom size not supported") + return errors.New("Rom size not supported") } romStart := 0 @@ -62,29 +66,42 @@ func (a *Apple2) LoadRom(filename string) { mmu.physicalROM = newMemoryRange(0xd000, data[romStart:]) mmu.resetRomPaging() + return nil } // AddDisk2 inserts a DiskII controller -func (a *Apple2) AddDisk2(slot int, diskRomFile string, diskImage string) { +func (a *Apple2) AddDisk2(slot int, diskRomFile string, diskImage string) error { var c cardDisk2 - c.loadRom(loadResource(diskRomFile)) + data, err := loadResource(diskRomFile) + if err != nil { + return err + } + c.loadRom(data) a.insertCard(&c, slot) if diskImage != "" { - diskette := loadDisquette(diskImage) - //diskette.saveNib(diskImage + "bak") + diskette, err := loadDisquette(diskImage) + if err != nil { + return err + } c.drive[0].insertDiskette(diskette) } + + return nil } // AddHardDisk adds a ProDos hard dirve with a 2MG image -func (a *Apple2) AddHardDisk(slot int, hdImage string) { +func (a *Apple2) AddHardDisk(slot int, hdImage string) error { var c cardHardDisk c.loadRom(buildHardDiskRom(slot)) a.insertCard(&c, slot) - hd := openHardDisk2mg(hdImage) + hd, err := openHardDisk2mg(hdImage) + if err != nil { + return err + } c.addDisk(hd) + return nil } // AddLanguageCard inserts a 16Kb card @@ -98,10 +115,15 @@ func (a *Apple2) AddSaturnCard(slot int) { } // AddThunderClockPlusCard inserts a ThunderClock Plus clock card -func (a *Apple2) AddThunderClockPlusCard(slot int, romFile string) { +func (a *Apple2) AddThunderClockPlusCard(slot int, romFile string) error { var c cardThunderClockPlus - c.loadRom(loadResource(romFile)) + data, err := loadResource(romFile) + if err != nil { + return err + } + c.loadRom(data) a.insertCard(&c, slot) + return nil } // AddCardLogger inserts a fake card that logs accesses diff --git a/apple2main.go b/apple2main.go index 2f5631f..c070ba2 100644 --- a/apple2main.go +++ b/apple2main.go @@ -88,16 +88,27 @@ func MainApple() *Apple2 { ) flag.Parse() - a := NewApple2(*charRomFile, *cpuClock, !*mono, *fastDisk) + a := NewApple2(*cpuClock, !*mono, *fastDisk) a.cpu.SetTrace(*traceCPU) a.io.setTrace(*traceSS) a.io.setPanicNotImplemented(*panicSS) + if *charRomFile != "" { + cg, err := NewCharacterGenerator(*charRomFile) + if err != nil { + panic(err) + } + a.cg = cg + } + if *base64a { NewBase64a(a) } else { - a.LoadRom(*romFile) + err := a.LoadRom(*romFile) + if err != nil { + panic(err) + } } if *languageCardSlot >= 0 { a.AddLanguageCard(*languageCardSlot) @@ -106,17 +117,26 @@ func MainApple() *Apple2 { a.AddSaturnCard(*saturnCardSlot) } if *thunderClockCardSlot > 0 { - a.AddThunderClockPlusCard(*thunderClockCardSlot, "/ThunderclockPlusROM.bin") + err := a.AddThunderClockPlusCard(*thunderClockCardSlot, "/ThunderclockPlusROM.bin") + if err != nil { + panic(err) + } } if *disk2Slot > 0 { - a.AddDisk2(*disk2Slot, *disk2RomFile, *diskImage) + err := a.AddDisk2(*disk2Slot, *disk2RomFile, *diskImage) + if err != nil { + panic(err) + } } if *hardDiskImage != "" { if *hardDiskSlot <= 0 { // If there is a hard disk image, but no slot assigned, use slot 7. *hardDiskSlot = 7 } - a.AddHardDisk(*hardDiskSlot, *hardDiskImage) + err := a.AddHardDisk(*hardDiskSlot, *hardDiskImage) + if err != nil { + panic(err) + } } //a.AddCardInOut(2) diff --git a/apple2sdl/sdlKeyboard.go b/apple2sdl/sdlKeyboard.go index 3ea6c87..8102870 100644 --- a/apple2sdl/sdlKeyboard.go +++ b/apple2sdl/sdlKeyboard.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "unicode/utf8" "github.com/ivanizag/apple2" @@ -106,7 +107,12 @@ func (k *sdlKeyboard) putKey(keyEvent *sdl.KeyboardEvent) { case sdl.K_F11: k.a.SendCommand(apple2.CommandToggleCPUTrace) case sdl.K_F12: - apple2.SaveSnapshot(k.a, "snapshot.png") + err := apple2.SaveSnapshot(k.a, "snapshot.png") + if err != nil { + fmt.Printf("Error saving snapshoot: %v.\n.", err) + } else { + fmt.Println("Saving snapshot") + } } // Missing values 91 to 95. Usually control for [\]^_ diff --git a/base64a.go b/base64a.go index 33400d6..4f05985 100644 --- a/base64a.go +++ b/base64a.go @@ -14,20 +14,26 @@ type Base64a struct { } // NewBase64a instantiates an apple2 -func NewBase64a(a *Apple2) *Base64a { +func NewBase64a(a *Apple2) (*Base64a, error) { var b Base64a b.a = a a.Name = "Base 64A" - b.loadRom() + err := b.loadRom() + if err != nil { + return nil, err + } // Configure the character generator if !a.cg.customRom { - a.cg.load("/BASE64A_ROM7_CharGen.BIN") + err := a.cg.load("/BASE64A_ROM7_CharGen.BIN") + if err != nil { + return nil, err + } } a.cg.setColumnMap(base64aCharGenColumnsMap) a.cg.setPage(1) - return &b + return &b, nil } func base64aCharGenColumnsMap(column int) int { @@ -50,7 +56,7 @@ const ( base64aRomChipCount = 6 ) -func (b *Base64a) loadRom() { +func (b *Base64a) loadRom() error { // Load the 6 PROM dumps romBanksBytes := make([][]uint8, base64aRomBankCount) for j := range romBanksBytes { @@ -59,7 +65,10 @@ func (b *Base64a) loadRom() { for i := 0; i < base64aRomChipCount; i++ { filename := fmt.Sprintf("/BASE64A_%X.BIN", 0xd0+i*0x08) - data := loadResource(filename) + data, err := loadResource(filename) + if err != nil { + return err + } for j := range romBanksBytes { start := (j * base64aRomWindowSize) % len(data) romBanksBytes[j] = append(romBanksBytes[j], data[start:start+base64aRomWindowSize]...) @@ -101,6 +110,7 @@ func (b *Base64a) loadRom() { speakerSoftSwitch(io) }) + return nil } func (b *Base64a) changeRomBank(bank uint8) { diff --git a/cardBase.go b/cardBase.go index 8de87c0..85dec00 100644 --- a/cardBase.go +++ b/cardBase.go @@ -21,7 +21,7 @@ type cardBase struct { func (c *cardBase) loadRom(data []uint8) { if c.a != nil { - panic("Rom must be loaded before inserting the card in the slot") + panic("Assert failed. Rom must be loaded before inserting the card in the slot") } if len(data) >= 0x100 { c.rom = newMemoryRange(0, data) @@ -50,10 +50,12 @@ func (c *cardBase) assign(a *Apple2, slot int) { } } -func (c *cardBase) save(w io.Writer) { +func (c *cardBase) save(w io.Writer) error { // Empty + return nil } -func (c *cardBase) load(r io.Reader) { +func (c *cardBase) load(r io.Reader) error { // Empty + return nil } diff --git a/cardDisk2.go b/cardDisk2.go index 5043c30..ffe25ec 100644 --- a/cardDisk2.go +++ b/cardDisk2.go @@ -169,34 +169,98 @@ func (d *cardDisk2Drive) insertDiskette(dt *diskette16sector) { d.diskette = dt } -func (c *cardDisk2) save(w io.Writer) { - binary.Write(w, binary.BigEndian, c.selected) - binary.Write(w, binary.BigEndian, c.dataLatch) - binary.Write(w, binary.BigEndian, c.q6) - binary.Write(w, binary.BigEndian, c.q7) - c.drive[0].save(w) - c.drive[1].save(w) +func (c *cardDisk2) save(w io.Writer) error { + err := binary.Write(w, binary.BigEndian, c.selected) + if err != nil { + return err + } + err = binary.Write(w, binary.BigEndian, c.dataLatch) + if err != nil { + return err + } + err = binary.Write(w, binary.BigEndian, c.q6) + if err != nil { + return err + } + err = binary.Write(w, binary.BigEndian, c.q7) + if err != nil { + return err + } + err = c.drive[0].save(w) + if err != nil { + return err + } + err = c.drive[1].save(w) + if err != nil { + return err + } + return c.cardBase.save(w) } -func (c *cardDisk2) load(r io.Reader) { - binary.Read(r, binary.BigEndian, &c.selected) - binary.Read(r, binary.BigEndian, &c.dataLatch) - binary.Read(r, binary.BigEndian, &c.q6) - binary.Read(r, binary.BigEndian, &c.q7) - c.drive[0].load(r) - c.drive[1].load(r) +func (c *cardDisk2) load(r io.Reader) error { + err := binary.Read(r, binary.BigEndian, &c.selected) + if err != nil { + return err + } + err = binary.Read(r, binary.BigEndian, &c.dataLatch) + if err != nil { + return err + } + err = binary.Read(r, binary.BigEndian, &c.q6) + if err != nil { + return err + } + err = binary.Read(r, binary.BigEndian, &c.q7) + if err != nil { + return err + } + err = c.drive[0].load(r) + if err != nil { + return err + } + err = c.drive[1].load(r) + if err != nil { + return err + } + return c.cardBase.load(r) } -func (d *cardDisk2Drive) save(w io.Writer) { - binary.Write(w, binary.BigEndian, d.currentPhase) - binary.Write(w, binary.BigEndian, d.power) - binary.Write(w, binary.BigEndian, d.halfTrack) - binary.Write(w, binary.BigEndian, d.position) +func (d *cardDisk2Drive) save(w io.Writer) error { + err := binary.Write(w, binary.BigEndian, d.currentPhase) + if err != nil { + return err + } + err = binary.Write(w, binary.BigEndian, d.power) + if err != nil { + return err + } + err = binary.Write(w, binary.BigEndian, d.halfTrack) + if err != nil { + return err + } + err = binary.Write(w, binary.BigEndian, d.position) + if err != nil { + return err + } + return nil } -func (d *cardDisk2Drive) load(r io.Reader) { - binary.Read(r, binary.BigEndian, &d.currentPhase) - binary.Read(r, binary.BigEndian, &d.power) - binary.Read(r, binary.BigEndian, &d.halfTrack) - binary.Read(r, binary.BigEndian, &d.position) +func (d *cardDisk2Drive) load(r io.Reader) error { + err := binary.Read(r, binary.BigEndian, &d.currentPhase) + if err != nil { + return err + } + err = binary.Read(r, binary.BigEndian, &d.power) + if err != nil { + return err + } + err = binary.Read(r, binary.BigEndian, &d.halfTrack) + if err != nil { + return err + } + err = binary.Read(r, binary.BigEndian, &d.position) + if err != nil { + return err + } + return nil } diff --git a/cardHardDisk.go b/cardHardDisk.go index 4ac02bc..a947f8e 100644 --- a/cardHardDisk.go +++ b/cardHardDisk.go @@ -96,7 +96,8 @@ func (c *cardHardDisk) assign(a *Apple2, slot int) { case proDosDeviceCommandWrite: return c.writeBlock(block, address) default: - panic("Prodos device command not supported.") + // Prodos device command not supported + return proDosDeviceErrorIO } } c.ssr[1] = func(*ioC0Page) uint8 { diff --git a/cardInOut.go b/cardInOut.go index e9170c3..5ba15b4 100644 --- a/cardInOut.go +++ b/cardInOut.go @@ -75,7 +75,7 @@ func (c *cardInOut) assign(a *Apple2, slot int) { if slot != 2 { // To make ifwork on other slots, patch C2, A0 and A1 - panic("Only slot 2 supported for the InOut card") + panic("Assert failed. Only slot 2 supported for the InOut card") } c.cardBase.assign(a, slot) } diff --git a/cardLanguage.go b/cardLanguage.go index 6e5d656..15b708d 100644 --- a/cardLanguage.go +++ b/cardLanguage.go @@ -128,25 +128,61 @@ func (c *cardLanguage) applyState() { } -func (c *cardLanguage) save(w io.Writer) { - binary.Write(w, binary.BigEndian, c.readState) - binary.Write(w, binary.BigEndian, c.writeState) - binary.Write(w, binary.BigEndian, c.activeBank) - c.ramBankA.save(w) - c.ramBankB.save(w) - c.ramUpper.save(w) +func (c *cardLanguage) save(w io.Writer) error { + err := binary.Write(w, binary.BigEndian, c.readState) + if err != nil { + return err + } + err = binary.Write(w, binary.BigEndian, c.writeState) + if err != nil { + return err + } + err = binary.Write(w, binary.BigEndian, c.activeBank) + if err != nil { + return err + } + err = c.ramBankA.save(w) + if err != nil { + return err + } + err = c.ramBankB.save(w) + if err != nil { + return err + } + err = c.ramUpper.save(w) + if err != nil { + return err + } - c.cardBase.save(w) + return c.cardBase.save(w) } -func (c *cardLanguage) load(r io.Reader) { - binary.Read(r, binary.BigEndian, &c.readState) - binary.Read(r, binary.BigEndian, &c.writeState) - binary.Read(r, binary.BigEndian, &c.activeBank) - c.ramBankA.load(r) - c.ramBankB.load(r) - c.ramUpper.load(r) +func (c *cardLanguage) load(r io.Reader) error { + err := binary.Read(r, binary.BigEndian, &c.readState) + if err != nil { + return err + } + err = binary.Read(r, binary.BigEndian, &c.writeState) + if err != nil { + return err + } + err = binary.Read(r, binary.BigEndian, &c.activeBank) + if err != nil { + return err + } + err = c.ramBankA.load(r) + if err != nil { + return err + } + err = c.ramBankB.load(r) + if err != nil { + return err + } + err = c.ramUpper.load(r) + if err != nil { + return err + } c.applyState() - c.cardBase.load(r) + return c.cardBase.load(r) } diff --git a/cardSaturn.go b/cardSaturn.go index f19303e..4d8f491 100644 --- a/cardSaturn.go +++ b/cardSaturn.go @@ -153,30 +153,69 @@ func (c *cardSaturn) applyState() { } } -func (c *cardSaturn) save(w io.Writer) { +func (c *cardSaturn) save(w io.Writer) error { for i := 0; i < saturnBlocks; i++ { - binary.Write(w, binary.BigEndian, c.readState) - binary.Write(w, binary.BigEndian, c.writeState) - binary.Write(w, binary.BigEndian, c.activeBank) - binary.Write(w, binary.BigEndian, c.activeBlock) - c.ramBankA[i].save(w) - c.ramBankB[i].save(w) - c.ramUpper[i].save(w) + err := binary.Write(w, binary.BigEndian, c.readState) + if err != nil { + return err + } + err = binary.Write(w, binary.BigEndian, c.writeState) + if err != nil { + return err + } + err = binary.Write(w, binary.BigEndian, c.activeBank) + if err != nil { + return err + } + err = binary.Write(w, binary.BigEndian, c.activeBlock) + if err != nil { + return err + } + err = c.ramBankA[i].save(w) + if err != nil { + return err + } + err = c.ramBankB[i].save(w) + if err != nil { + return err + } + err = c.ramUpper[i].save(w) + if err != nil { + return err + } } - c.cardBase.save(w) + return c.cardBase.save(w) } -func (c *cardSaturn) load(r io.Reader) { +func (c *cardSaturn) load(r io.Reader) error { for i := 0; i < saturnBlocks; i++ { - binary.Read(r, binary.BigEndian, &c.readState) - binary.Read(r, binary.BigEndian, &c.writeState) - binary.Read(r, binary.BigEndian, &c.activeBank) - binary.Read(r, binary.BigEndian, &c.activeBlock) - c.ramBankA[i].load(r) - c.ramBankB[i].load(r) - c.ramUpper[i].load(r) + err := binary.Read(r, binary.BigEndian, &c.readState) + if err != nil { + return err + } + err = binary.Read(r, binary.BigEndian, &c.writeState) + if err != nil { + return err + } + err = binary.Read(r, binary.BigEndian, &c.activeBank) + if err != nil { + return err + } + err = binary.Read(r, binary.BigEndian, &c.activeBlock) + if err != nil { + return err + } + err = c.ramBankA[i].load(r) + if err != nil { + return err + } + err = c.ramBankB[i].load(r) + if err != nil { + return err + } + err = c.ramUpper[i].load(r) c.applyState() } - c.cardBase.load(r) + return c.cardBase.load(r) } diff --git a/characterGenerator.go b/characterGenerator.go index 2adb3b3..dfdbceb 100644 --- a/characterGenerator.go +++ b/characterGenerator.go @@ -1,6 +1,7 @@ package apple2 import ( + "errors" "fmt" ) @@ -25,20 +26,27 @@ const ( ) // NewCharacterGenerator instantiates a new Character Generator with the rom on the file given -func NewCharacterGenerator(filename string) *CharacterGenerator { +func NewCharacterGenerator(filename string) (*CharacterGenerator, error) { var cg CharacterGenerator - cg.load(filename) - return &cg + err := cg.load(filename) + if err != nil { + return nil, err + } + return &cg, nil } -func (cg *CharacterGenerator) load(filename string) { +func (cg *CharacterGenerator) load(filename string) error { cg.customRom = !isInternalResource(filename) - bytes := loadResource(filename) + bytes, err := loadResource(filename) + if err != nil { + return err + } size := len(bytes) if size < rev7CharGenSize { - panic("Character ROM size not supported") + return errors.New("Character ROM size not supported") } cg.data = bytes + return nil } func (cg *CharacterGenerator) setColumnMap(columnMap charColumnMap) { diff --git a/core6502/addressing.go b/core6502/addressing.go index b35edb6..48f6735 100644 --- a/core6502/addressing.go +++ b/core6502/addressing.go @@ -96,7 +96,7 @@ func resolve(s *State, line []uint8, opcode opcode) (getValue func() uint8, setV } else if register != regNone { s.reg.setRegister(register, value) } else { - panic("Should never happen") + panic("Assert failed. Should never happen") } } return diff --git a/core6502/execute.go b/core6502/execute.go index 7722af6..9684371 100644 --- a/core6502/execute.go +++ b/core6502/execute.go @@ -85,15 +85,29 @@ func (s *State) GetCycles() uint64 { } // Save saves the CPU state (registers and cycle counter) -func (s *State) Save(w io.Writer) { - binary.Write(w, binary.BigEndian, s.cycles) +func (s *State) Save(w io.Writer) error { + err := binary.Write(w, binary.BigEndian, s.cycles) + if err != nil { + return err + } binary.Write(w, binary.BigEndian, s.reg.data) + if err != nil { + return err + } + return nil } // Load loads the CPU state (registers and cycle counter) -func (s *State) Load(r io.Reader) { - binary.Read(r, binary.BigEndian, &s.cycles) - binary.Read(r, binary.BigEndian, &s.reg.data) +func (s *State) Load(r io.Reader) error { + err := binary.Read(r, binary.BigEndian, &s.cycles) + if err != nil { + return err + } + err = binary.Read(r, binary.BigEndian, &s.reg.data) + if err != nil { + return err + } + return nil } func lineString(line []uint8, opcode opcode) string { diff --git a/core6502/memory.go b/core6502/memory.go index 4248562..6e15b27 100644 --- a/core6502/memory.go +++ b/core6502/memory.go @@ -31,13 +31,15 @@ func (m *FlatMemory) Poke(address uint16, value uint8) { m.data[address] = value } -func (m *FlatMemory) loadBinary(filename string) { +func (m *FlatMemory) loadBinary(filename string) error { bytes, err := ioutil.ReadFile(filename) if err != nil { - panic(err) + return err } for i, v := range bytes { m.Poke(uint16(i), uint8(v)) } + + return nil } diff --git a/diskette16sector.go b/diskette16sector.go index 840480c..ff4494f 100644 --- a/diskette16sector.go +++ b/diskette16sector.go @@ -1,6 +1,7 @@ package apple2 import ( + "errors" "os" ) @@ -36,10 +37,13 @@ func (d *diskette16sector) write(track int, position int, value uint8) int { return (position + 1) % nibBytesPerTrack } -func loadDisquette(filename string) *diskette16sector { +func loadDisquette(filename string) (*diskette16sector, error) { var d diskette16sector - data := loadResource(filename) + data, err := loadResource(filename) + if err != nil { + return nil, err + } size := len(data) if size == nibImageSize { @@ -54,25 +58,27 @@ func loadDisquette(filename string) *diskette16sector { d.track[i] = nibEncodeTrack(trackData, defaultVolumeTag, byte(i)) } } else { - panic("Invalid disk size") + return nil, errors.New("Invalid disk size") } - return &d + return &d, nil } -func (d *diskette16sector) saveNib(filename string) { +func (d *diskette16sector) saveNib(filename string) error { f, err := os.Create(filename) if err != nil { - panic(err) + return err } defer f.Close() for _, v := range d.track { _, err := f.Write(v) if err != nil { - panic(err) + return err } } + + return nil } var dos33SectorsLogicOrder = [16]int{ diff --git a/hardDisk.go b/hardDisk.go index 3dbe111..2f4b9d2 100644 --- a/hardDisk.go +++ b/hardDisk.go @@ -76,7 +76,7 @@ func (hd *hardDisk) write(block uint32, data []uint8) error { return nil } -func openHardDisk2mg(filename string) *hardDisk { +func openHardDisk2mg(filename string) (*hardDisk, error) { var hd hardDisk hd.readOnly = false @@ -87,44 +87,49 @@ func openHardDisk2mg(filename string) *hardDisk { file, err = os.OpenFile(filename, os.O_RDONLY, 0) } if err != nil { - panic(err) + return nil, err } hd.file = file fileInfo, err := hd.file.Stat() if err != nil { - panic(err) + return nil, err } minHeaderSize := binary.Size(&hd.header) if fileInfo.Size() < int64(minHeaderSize) { - panic("Invalid 2MG file") + return nil, errors.New("Invalid 2MG file") } - readHeader(hd.file, &hd.header) + err = readHeader(hd.file, &hd.header) + if err != nil { + return nil, err + } if fileInfo.Size() < int64(hd.header.OffsetData+hd.header.Blocks*proDosBlockSize) { - panic("Thr 2MG file is too small") + return nil, errors.New("Thr 2MG file is too small") } - return &hd + return &hd, nil } -func readHeader(buf io.Reader, header *hardDisk2mgHeader) { +func readHeader(buf io.Reader, header *hardDisk2mgHeader) error { err := binary.Read(buf, binary.LittleEndian, header) if err != nil { - panic(err) + return err } if header.Preamble != hardDisk2mgPreamble { - panic("2mg file must start with '2IMG'") + return errors.New("2mg file must start with '2IMG'") } if header.Format != hardDisk2mgFormatProdos { - panic("Only prodos hard disks are supported") + return errors.New("Only prodos hard disks are supported") } if header.Version != hardDisk2mgVersion { - panic("Version of 2MG image not supported") + return errors.New("Version of 2MG image not supported") } + + return nil } diff --git a/ioC0Page.go b/ioC0Page.go index 4168aa3..d80dbed 100644 --- a/ioC0Page.go +++ b/ioC0Page.go @@ -67,12 +67,12 @@ func (p *ioC0Page) setPanicNotImplemented(value bool) { p.panicNotImplemented = value } -func (p *ioC0Page) save(w io.Writer) { - binary.Write(w, binary.BigEndian, p.softSwitchesData) +func (p *ioC0Page) save(w io.Writer) error { + return binary.Write(w, binary.BigEndian, p.softSwitchesData) } -func (p *ioC0Page) load(r io.Reader) { - binary.Read(r, binary.BigEndian, &p.softSwitchesData) +func (p *ioC0Page) load(r io.Reader) error { + return binary.Read(r, binary.BigEndian, &p.softSwitchesData) } func (p *ioC0Page) addSoftSwitchRW(address uint8, ss softSwitchR) { diff --git a/memoryManager.go b/memoryManager.go index cc15c57..56360f3 100644 --- a/memoryManager.go +++ b/memoryManager.go @@ -141,16 +141,29 @@ func newMemoryManager(a *Apple2) *memoryManager { return &mmu } -func (mmu *memoryManager) save(w io.Writer) { - mmu.physicalMainRAM.save(w) - binary.Write(w, binary.BigEndian, mmu.activeSlot) - +func (mmu *memoryManager) save(w io.Writer) error { + err := mmu.physicalMainRAM.save(w) + if err != nil { + return err + } + err = binary.Write(w, binary.BigEndian, mmu.activeSlot) + if err != nil { + return err + } + return nil } -func (mmu *memoryManager) load(r io.Reader) { - mmu.physicalMainRAM.load(r) - binary.Read(r, binary.BigEndian, &mmu.activeSlot) +func (mmu *memoryManager) load(r io.Reader) error { + err := mmu.physicalMainRAM.load(r) + if err != nil { + return err + } + err = binary.Read(r, binary.BigEndian, &mmu.activeSlot) + if err != nil { + return err + } mmu.activateCardRomExtra(mmu.activeSlot) mmu.resetBaseRamPaging() + return nil } diff --git a/memoryRange.go b/memoryRange.go index c8f24eb..c41ea63 100644 --- a/memoryRange.go +++ b/memoryRange.go @@ -29,12 +29,26 @@ func (m *memoryRange) subRange(a, b uint16) []uint8 { return m.data[a-m.base : b-m.base] } -func (m *memoryRange) save(w io.Writer) { - binary.Write(w, binary.BigEndian, m.base) - binary.Write(w, binary.BigEndian, m.data) +func (m *memoryRange) save(w io.Writer) error { + err := binary.Write(w, binary.BigEndian, m.base) + if err != nil { + return err + } + err = binary.Write(w, binary.BigEndian, m.data) + if err != nil { + return err + } + return nil } -func (m *memoryRange) load(r io.Reader) { - binary.Read(r, binary.BigEndian, &m.base) - binary.Read(r, binary.BigEndian, &m.data) +func (m *memoryRange) load(r io.Reader) error { + err := binary.Read(r, binary.BigEndian, &m.base) + if err != nil { + return err + } + err = binary.Read(r, binary.BigEndian, &m.data) + if err != nil { + return err + } + return nil } diff --git a/resources.go b/resources.go index 5d70838..c107ee9 100644 --- a/resources.go +++ b/resources.go @@ -25,14 +25,14 @@ func isHTTPResource(filename string) bool { strings.HasPrefix(filename, httpsPrefix) } -func loadResource(filename string) []uint8 { +func loadResource(filename string) ([]uint8, error) { var file io.Reader if isInternalResource(filename) { // load from embedded resource resource := strings.TrimPrefix(filename, internalPrefix) resourceFile, err := romdumps.Assets.Open(resource) if err != nil { - panic(err) + return nil, err } defer resourceFile.Close() file = resourceFile @@ -40,7 +40,7 @@ func loadResource(filename string) []uint8 { } else if isHTTPResource(filename) { response, err := http.Get(filename) if err != nil { - panic(err) + return nil, err } defer response.Body.Close() file = response.Body @@ -48,7 +48,7 @@ func loadResource(filename string) []uint8 { } else { diskFile, err := os.Open(filename) if err != nil { - panic(err) + return nil, err } defer diskFile.Close() file = diskFile @@ -56,7 +56,7 @@ func loadResource(filename string) []uint8 { data, err := ioutil.ReadAll(file) if err != nil { - panic(err) + return nil, err } - return data + return data, nil } diff --git a/screen.go b/screen.go index 2707082..8dc3738 100644 --- a/screen.go +++ b/screen.go @@ -96,22 +96,18 @@ func mixSnapshots(top, bottom *image.RGBA) *image.RGBA { } // SaveSnapshot saves a snapshot of the screen to a png file -func SaveSnapshot(a *Apple2, filename string) { +func SaveSnapshot(a *Apple2, filename string) error { img := Snapshot(a) - if img == nil { - return - } img = squarishPixelsFilter(img) f, err := os.Create(filename) if err != nil { - panic(err) + return err } defer f.Close() - fmt.Println("Saving snapshot") - png.Encode(f, img) + return nil } func squarishPixelsFilter(in *image.RGBA) *image.RGBA {