izapple2/apple2/addressSpace.go

111 lines
2.2 KiB
Go

package apple2
import (
"bufio"
"os"
)
// See https://i.stack.imgur.com/yn21s.gif
type addressSpace struct {
activeMemory *pagedMemory
physicalRAM [256]ramPage // up to 64 Kb
physicalROM [48]romPage // up to 12 Kb
ioPage ioC0Page
textPages1 *textPages
activeSlow int // Slot that has the addressing 0xc800 to 0ccfff
}
const (
ioAreaMask uint16 = 0xFF80
ioAreaValue uint16 = 0xC000
ioC8Off uint16 = 0xCFFF
)
// Peek returns the data on the given address
func (a *addressSpace) Peek(address uint16) uint8 {
if address == ioC8Off {
a.resetSlotRoms()
}
if (address & ioAreaMask) == ioAreaValue {
return a.ioPage.Peek(uint8(address))
}
return a.activeMemory.Peek(address)
}
// Poke sets the data at the given address
func (a *addressSpace) Poke(address uint16, value uint8) {
if address == ioC8Off {
a.resetSlotRoms()
}
if (address & ioAreaMask) == ioAreaValue {
a.ioPage.Poke(uint8(address), value)
}
a.activeMemory.Poke(address, value)
}
func (a *addressSpace) resetSlotRoms() {
// TODO
}
func newAddressSpace() *addressSpace {
var a addressSpace
var m pagedMemory
a.activeMemory = &m
// Assign RAM from 0x0000 to 0xbfff, 48kb
for i := 0; i <= 0xbf; i++ {
m.SetPage(uint8(i), &(a.physicalRAM[i]))
}
// Assign ROM from 0xd000 to 0xfff, 12 kb. The ROM is empty
for i := 0xd0; i <= 0xff; i++ {
m.SetPage(uint8(i), &(a.physicalROM[i-0xd0]))
}
// Set the 0xc000 to 0xcfff as unasigned, 4kb. It wil be taken by slot cards.
for i := uint8(0xc0); i <= 0xcf; i++ {
var p unassignedPage
p.page = i
m.SetPage(i, &p)
}
// Replace RAM in the TEXT1 area.
// TODO: treat as normal ram. Add is dirty in all RAM pages
var t textPages
a.textPages1 = &t
for i := 0; i < 4; i++ {
m.SetPage(uint8(4+i), &(t.pages[i]))
}
return &a
}
// LoadRom loads a binary file to the top of the memory.
func (a *addressSpace) 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 != 12288 {
panic("Rom size not supported")
}
bytes := make([]byte, size)
buf := bufio.NewReader(f)
buf.Read(bytes)
for i, v := range bytes {
a.physicalROM[i>>8].burn(uint8(i), uint8(v))
}
}