Improve the expansion card abstraction

This commit is contained in:
Ivan Izaguirre 2019-05-18 16:43:51 +02:00
parent cb21a1fefc
commit 684c8f7172
7 changed files with 115 additions and 104 deletions

View File

@ -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)
}
}
}

View File

@ -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

View File

@ -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
}

View File

@ -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) {

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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)
}
}