izapple2/apple2/apple2.go

89 lines
1.8 KiB
Go
Raw Normal View History

package apple2
import (
"bufio"
"go6502/core6502"
"os"
)
type Apple2 struct {
cpu *core6502.State
mmu *memoryManager
isApple2e bool
ioPage *ioC0Page // 0xc000 to 0xc080
activeSlot int // Slot that has the addressing 0xc800 to 0ccfff
}
// NewApple2 instantiates an apple2
func NewApple2(romFile string) *Apple2 {
var a Apple2
a.mmu = newMemoryManager(&a)
a.cpu = core6502.NewNMOS6502(a.mmu)
a.loadRom(romFile)
a.mmu.resetPaging()
// Set the io in 0xc000
a.ioPage = newIoC0Page(&a)
a.mmu.setPage(0xc0, a.ioPage)
return &a
}
func (a *Apple2) Run(log bool) {
// Init frontend
fe := newAnsiConsoleFrontend(a)
a.ioPage.setKeyboardProvider(fe)
go fe.textModeGoRoutine()
// Start the processor
a.cpu.Reset()
for {
a.cpu.ExecuteInstruction(log)
}
}
// LoadRom loads a binary file to the top of the memory.
const (
apple2RomSize = 12 * 1024
apple2eRomSize = 16 * 1024
)
func (a *Apple2) loadRom(filename string) {
f, err := os.Open(filename)
if err != nil {
panic(err)
}
defer f.Close()
stats, statsErr := f.Stat()
if statsErr != nil {
panic(err)
}
size := stats.Size()
if size != apple2RomSize && size != apple2eRomSize {
panic("Rom size not supported")
}
bytes := make([]byte, size)
buf := bufio.NewReader(f)
buf.Read(bytes)
romStart := 0
if size == apple2eRomSize {
// The extra 4kb ROM is first in the rom file.
// It starts with 256 unused bytes not mapped to 0xc000.
a.isApple2e = true
extraRomSize := apple2eRomSize - apple2RomSize
a.mmu.physicalROMe = make([]romPage, extraRomSize>>8)
for i := 0; i < extraRomSize; i++ {
a.mmu.physicalROMe[i>>8].burn(uint8(i), bytes[i])
}
romStart = extraRomSize
}
a.mmu.physicalROM = make([]romPage, apple2RomSize>>8)
for i := 0; i < apple2RomSize; i++ {
a.mmu.physicalROM[i>>8].burn(uint8(i), bytes[i+romStart])
}
}