diff --git a/apple2/apple2.go b/apple2/apple2.go index fd1f367..bd8f791 100644 --- a/apple2/apple2.go +++ b/apple2/apple2.go @@ -1,8 +1,12 @@ package apple2 import ( + "bufio" + "encoding/binary" "fmt" "go6502/core6502" + "io" + "os" "time" ) @@ -12,6 +16,7 @@ type Apple2 struct { mmu *memoryManager io *ioC0Page cg *CharacterGenerator + cards [8]card isApple2e bool panicSS bool commandChannel chan int @@ -19,7 +24,6 @@ type Apple2 struct { isColor bool fastMode bool fastRequestsCounter int - persistance *persistance } const ( @@ -97,10 +101,10 @@ func (a *Apple2) executeCommand(command int) { a.isColor = !a.isColor case CommandSaveState: fmt.Println("Saving state") - a.persistance.save("apple2.state") + a.save("apple2.state") case CommandLoadState: fmt.Println("Loading state") - a.persistance.load("apple2.state") + a.load("apple2.state") } } @@ -116,3 +120,55 @@ func (a *Apple2) releaseFastMode() { a.fastRequestsCounter-- } } + +type persistent interface { + save(io.Writer) + load(io.Reader) +} + +func (a *Apple2) save(filename string) { + f, err := os.Create(filename) + if err != nil { + panic(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) + + for _, c := range a.cards { + if c != nil { + c.save(w) + } + } +} + +func (a *Apple2) load(filename string) { + f, err := os.Open(filename) + if err != nil { + // Ignore error if can't load the file + return + } + 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) + + for _, c := range a.cards { + if c != nil { + c.load(r) + + } + } +} diff --git a/apple2/apple2Setup.go b/apple2/apple2Setup.go index b477cb3..0ff4ec5 100644 --- a/apple2/apple2Setup.go +++ b/apple2/apple2Setup.go @@ -8,9 +8,7 @@ import ( func NewApple2(romFile string, charRomFile string, clockMhz float64, isColor bool, fastMode bool, panicSS bool) *Apple2 { var a Apple2 - a.persistance = newPersistance(&a) a.mmu = newMemoryManager(&a, romFile) - a.persistance.register(a.mmu) a.cpu = core6502.NewNMOS6502(a.mmu) if charRomFile != "" { a.cg = NewCharacterGenerator(charRomFile) @@ -29,39 +27,37 @@ func NewApple2(romFile string, charRomFile string, clockMhz float64, // Set the io in 0xc000 a.io = newIoC0Page(&a) - a.persistance.register(a.io) a.mmu.setPages(0xc0, 0xc0, a.io) return &a } +func (a *Apple2) insertCard(c card, slot int) { + c.assign(a, slot) + a.cards[slot] = c +} + // AddDisk2 insterts a DiskII controller func (a *Apple2) AddDisk2(slot int, diskRomFile string, diskImage string) { - d := newCardDisk2(diskRomFile) - d.cardBase.insert(a, slot) - a.persistance.register(d) + var c cardDisk2 + c.loadRom(diskRomFile) + a.insertCard(&c, slot) if diskImage != "" { diskette := loadDisquette(diskImage) //diskette.saveNib(diskImage + "bak") - d.drive[0].insertDiskette(diskette) + c.drive[0].insertDiskette(diskette) } } // AddLanguageCard inserts a 16Kb card func (a *Apple2) AddLanguageCard(slot int) { - d := newCardLanguage() - d.cardBase.insert(a, slot) - d.applyState() - a.persistance.register(d) + a.insertCard(&cardLanguage{}, slot) } // AddSaturnCard inserts a 128Kb card func (a *Apple2) AddSaturnCard(slot int) { - d := newCardSaturn() - d.cardBase.insert(a, slot) - d.applyState() - a.persistance.register(d) + a.insertCard(&cardSaturn{}, slot) } // ConfigureStdConsole uses stdin and stdout to interface with the Apple2 diff --git a/apple2/cardBase.go b/apple2/cardBase.go index 21c3767..f72fe21 100644 --- a/apple2/cardBase.go +++ b/apple2/cardBase.go @@ -1,5 +1,16 @@ package apple2 +import ( + "io" + "io/ioutil" +) + +type card interface { + loadRom(filename string) + assign(a *Apple2, slot int) + persistent +} + type cardBase struct { a *Apple2 rom *memoryRange @@ -8,7 +19,18 @@ type cardBase struct { ssw [16]softSwitchW } -func (c *cardBase) insert(a *Apple2, slot int) { +func (c *cardBase) loadRom(filename string) { + if c.a != nil { + panic("Rom must be loaded before inserting the card in the slot") + } + data, err := ioutil.ReadFile(filename) + if err != nil { + panic(err) + } + c.rom = newMemoryRange(0, data) +} + +func (c *cardBase) assign(a *Apple2, slot int) { c.a = a c.slot = slot if slot != 0 && c.rom != nil { @@ -21,3 +43,11 @@ func (c *cardBase) insert(a *Apple2, slot int) { a.io.addSoftSwitchW(uint8(0xC80+slot*0x10+i), c.ssw[i]) } } + +func (c *cardBase) save(w io.Writer) { + // Empty +} + +func (c *cardBase) load(r io.Reader) { + // Empty +} diff --git a/apple2/cardDisk2.go b/apple2/cardDisk2.go index 4f404be..97b079f 100644 --- a/apple2/cardDisk2.go +++ b/apple2/cardDisk2.go @@ -3,7 +3,6 @@ package apple2 import ( "encoding/binary" "io" - "io/ioutil" ) /* @@ -32,10 +31,7 @@ type cardDisk2Drive struct { position int } -func newCardDisk2(filename string) *cardDisk2 { - var c cardDisk2 - c.rom = newMemoryRange(0, loadCardRom(filename)) - +func (c *cardDisk2) assign(a *Apple2, slot int) { // Phase control soft switches // Lazy emulation. It only checks for phases on and move the head // up or down depending on the previous phase. @@ -138,15 +134,8 @@ func newCardDisk2(filename string) *cardDisk2 { //fmt.Printf("DISKII: Set write mode\n") return 0 } - return &c -} -func loadCardRom(filename string) []uint8 { - data, err := ioutil.ReadFile(filename) - if err != nil { - panic(err) - } - return data + c.cardBase.assign(a, slot) } func (d *cardDisk2Drive) insertDiskette(dt *diskette16sector) { diff --git a/apple2/cardLanguage.go b/apple2/cardLanguage.go index 02e011a..97d237a 100644 --- a/apple2/cardLanguage.go +++ b/apple2/cardLanguage.go @@ -45,8 +45,7 @@ const ( lcWriteEnabled = 2 ) -func newCardLanguage() *cardLanguage { - var c cardLanguage +func (c *cardLanguage) assign(a *Apple2, slot int) { c.readState = false c.writeState = lcWriteEnabled c.activeBank = 1 @@ -66,7 +65,9 @@ func newCardLanguage() *cardLanguage { c.writeState = lcWriteDisabled } } - return &c + + c.cardBase.assign(a, slot) + c.applyState() } func (c *cardLanguage) ssAction(ss int) { @@ -131,6 +132,8 @@ func (c *cardLanguage) save(w io.Writer) { c.ramBankA.save(w) c.ramBankB.save(w) c.ramUpper.save(w) + + c.cardBase.save(w) } func (c *cardLanguage) load(r io.Reader) { @@ -142,4 +145,5 @@ func (c *cardLanguage) load(r io.Reader) { c.ramUpper.load(r) c.applyState() + c.cardBase.load(r) } diff --git a/apple2/cardSaturn.go b/apple2/cardSaturn.go index 03f08f3..c2a1d06 100644 --- a/apple2/cardSaturn.go +++ b/apple2/cardSaturn.go @@ -35,8 +35,7 @@ const ( saturnBlocks = 8 ) -func newCardSaturn() *cardSaturn { - var c cardSaturn +func (c *cardSaturn) assign(a *Apple2, slot int) { c.readState = false c.writeState = lcWriteEnabled c.activeBank = 1 @@ -57,7 +56,8 @@ func newCardSaturn() *cardSaturn { c.writeState = lcWriteDisabled } } - return &c + c.cardBase.assign(a, slot) + c.applyState() } func (c *cardSaturn) ssAction(ss int) { @@ -163,6 +163,7 @@ func (c *cardSaturn) save(w io.Writer) { c.ramBankB[i].save(w) c.ramUpper[i].save(w) } + c.cardBase.save(w) } func (c *cardSaturn) load(r io.Reader) { @@ -177,4 +178,5 @@ func (c *cardSaturn) load(r io.Reader) { c.applyState() } + c.cardBase.load(r) } diff --git a/apple2/persistance.go b/apple2/persistance.go deleted file mode 100644 index c2d5596..0000000 --- a/apple2/persistance.go +++ /dev/null @@ -1,66 +0,0 @@ -package apple2 - -import ( - "bufio" - "encoding/binary" - "io" - "os" -) - -type persistent interface { - save(w io.Writer) - load(r io.Reader) -} - -type persistance struct { - a *Apple2 - items []persistent -} - -func newPersistance(a *Apple2) *persistance { - var p persistance - p.a = a - return &p -} - -func (p *persistance) register(i persistent) { - p.items = append(p.items, i) -} - -func (p *persistance) save(filename string) { - f, err := os.Create(filename) - if err != nil { - panic(err) - } - defer f.Close() - w := bufio.NewWriter(f) - defer w.Flush() - - binary.Write(w, binary.BigEndian, p.a.isColor) - binary.Write(w, binary.BigEndian, p.a.fastMode) - binary.Write(w, binary.BigEndian, p.a.fastRequestsCounter) - p.a.cpu.Save(w) - - for _, v := range p.items { - v.save(w) - } -} - -func (p *persistance) load(filename string) { - f, err := os.Open(filename) - if err != nil { - // Ignore error if can't load the file - return - } - defer f.Close() - r := bufio.NewReader(f) - - binary.Read(r, binary.BigEndian, &p.a.isColor) - binary.Read(r, binary.BigEndian, &p.a.fastMode) - binary.Read(r, binary.BigEndian, &p.a.fastRequestsCounter) - p.a.cpu.Load(r) - - for _, v := range p.items { - v.load(r) - } -}