mirror of
https://github.com/ivanizag/izapple2.git
synced 2025-02-22 05:28:58 +00:00
Rework of the memory manager. No longer based on pages, but on bigger go byte ranges
This commit is contained in:
parent
51c7a8cb57
commit
c4f7a7e709
@ -21,27 +21,17 @@ type ansiConsoleFrontend struct {
|
||||
apple2 *Apple2
|
||||
keyChannel chan uint8
|
||||
extraLineFeeds chan int
|
||||
textUpdated bool
|
||||
stdinKeyboard bool
|
||||
lastContent string
|
||||
}
|
||||
|
||||
func newAnsiConsoleFrontend(a *Apple2, stdinKeyboard bool) *ansiConsoleFrontend {
|
||||
var fe ansiConsoleFrontend
|
||||
fe.apple2 = a
|
||||
fe.stdinKeyboard = stdinKeyboard
|
||||
fe.subscribeToTextPages()
|
||||
return &fe
|
||||
}
|
||||
|
||||
func (fe *ansiConsoleFrontend) subscribeToTextPages() {
|
||||
observer := func(_ uint8, _ bool) {
|
||||
fe.textUpdated = true
|
||||
}
|
||||
for i := 0x04; i < 0x08; i++ {
|
||||
fe.apple2.mmu.physicalMainRAM[i].observer = observer
|
||||
}
|
||||
}
|
||||
|
||||
const refreshDelayMs = 100
|
||||
|
||||
func (fe *ansiConsoleFrontend) GetKey(strobed bool) (key uint8, ok bool) {
|
||||
@ -85,101 +75,53 @@ func (fe *ansiConsoleFrontend) GetKey(strobed bool) (key uint8, ok bool) {
|
||||
return
|
||||
}
|
||||
|
||||
func ansiCursorUp(steps int) {
|
||||
fmt.Printf("\033[%vA", steps)
|
||||
}
|
||||
|
||||
func (fe *ansiConsoleFrontend) textModeGoRoutineFast() {
|
||||
fe.extraLineFeeds = make(chan int, 100)
|
||||
|
||||
fmt.Printf(strings.Repeat("\n", 26))
|
||||
for {
|
||||
if fe.textUpdated {
|
||||
fe.textUpdated = false
|
||||
// Go up
|
||||
ansiCursorUp(26)
|
||||
done := false
|
||||
for !done {
|
||||
select {
|
||||
case lineFeeds := <-fe.extraLineFeeds:
|
||||
ansiCursorUp(lineFeeds)
|
||||
default:
|
||||
done = true
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println(strings.Repeat("#", 44))
|
||||
|
||||
// See "Understand the Apple II", page 5-10
|
||||
// http://www.applelogic.org/files/UNDERSTANDINGTHEAII.pdf
|
||||
isAltText := fe.apple2.isApple2e && fe.apple2.io.isSoftSwitchActive(ioFlagAltChar)
|
||||
var i, j, h, c uint8
|
||||
// Top, middle and botton screen
|
||||
for i = 0; i < 120; i = i + 40 {
|
||||
// Memory pages
|
||||
for j = 0x04; j < 0x08; j++ {
|
||||
p := fe.apple2.mmu.physicalMainRAM[j]
|
||||
// The two half pages
|
||||
for _, h = range []uint8{0, 128} {
|
||||
line := ""
|
||||
for c = i + h; c < i+h+40; c++ {
|
||||
line += textMemoryByteToString(p.internalPeek(c), isAltText)
|
||||
}
|
||||
fmt.Printf("# %v #\n", line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println(strings.Repeat("#", 44))
|
||||
if fe.stdinKeyboard {
|
||||
fmt.Print("\033[KLine: ")
|
||||
}
|
||||
}
|
||||
time.Sleep(refreshDelayMs * time.Millisecond)
|
||||
}
|
||||
func ansiCursorUp(steps int) string {
|
||||
return fmt.Sprintf("\033[%vA", steps)
|
||||
}
|
||||
|
||||
func (fe *ansiConsoleFrontend) textModeGoRoutine() {
|
||||
fe.extraLineFeeds = make(chan int, 100)
|
||||
|
||||
fmt.Printf(strings.Repeat("\n", 26))
|
||||
fmt.Printf(strings.Repeat("\n", textLines+3))
|
||||
for {
|
||||
if fe.textUpdated {
|
||||
fe.textUpdated = false
|
||||
// Go up
|
||||
ansiCursorUp(26)
|
||||
content := ansiCursorUp(textLines + 3)
|
||||
done := false
|
||||
for !done {
|
||||
select {
|
||||
case lineFeeds := <-fe.extraLineFeeds:
|
||||
ansiCursorUp(lineFeeds)
|
||||
content += ansiCursorUp(lineFeeds)
|
||||
default:
|
||||
done = true
|
||||
}
|
||||
}
|
||||
|
||||
content += "\n"
|
||||
content += fmt.Sprintln(strings.Repeat("#", textColumns+4))
|
||||
|
||||
pageIndex := 0
|
||||
if fe.apple2.io.isSoftSwitchActive(ioFlagSecondPage) {
|
||||
pageIndex = 1
|
||||
}
|
||||
isAltText := fe.apple2.isApple2e && fe.apple2.io.isSoftSwitchActive(ioFlagAltChar)
|
||||
|
||||
fmt.Println(strings.Repeat("#", 44))
|
||||
for line := 0; line < 24; line++ {
|
||||
text := ""
|
||||
for col := 0; col < 40; col++ {
|
||||
value := getTextChar(fe.apple2, col, line, pageIndex)
|
||||
text += textMemoryByteToString(value, isAltText)
|
||||
for l := 0; l < textLines; l++ {
|
||||
line := ""
|
||||
for c := 0; c < textColumns; c++ {
|
||||
char := getTextChar(fe.apple2, c, l, pageIndex)
|
||||
line += textMemoryByteToString(char, isAltText)
|
||||
}
|
||||
fmt.Printf("# %v #\n", text)
|
||||
content += fmt.Sprintf("# %v #\n", line)
|
||||
}
|
||||
|
||||
fmt.Println(strings.Repeat("#", 44))
|
||||
content += fmt.Sprintln(strings.Repeat("#", textColumns+4))
|
||||
if fe.stdinKeyboard {
|
||||
fmt.Print("\033[KLine: ")
|
||||
content += "\033[KLine: "
|
||||
}
|
||||
|
||||
//saveSnapshot(fe.apple2)
|
||||
if content != fe.lastContent {
|
||||
fmt.Print(content)
|
||||
fe.lastContent = content
|
||||
}
|
||||
time.Sleep(refreshDelayMs * time.Millisecond)
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package apple2
|
||||
import (
|
||||
"fmt"
|
||||
"go6502/core6502"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -36,11 +35,10 @@ func NewApple2(romFile string, charRomFile string, clockMhz float64,
|
||||
var a Apple2
|
||||
a.mmu = newMemoryManager(&a)
|
||||
a.cpu = core6502.NewNMOS6502(a.mmu)
|
||||
a.loadRom(romFile)
|
||||
a.mmu.loadRom(romFile)
|
||||
if charRomFile != "" {
|
||||
a.cg = NewCharacterGenerator(charRomFile)
|
||||
}
|
||||
a.mmu.resetRomPaging()
|
||||
a.commandChannel = make(chan int, 100)
|
||||
a.isColor = isColor
|
||||
a.fastMode = fastMode
|
||||
@ -182,32 +180,3 @@ func (a *Apple2) releaseFastMode() {
|
||||
a.fastRequestsCounter--
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Apple2) loadRom(filename string) {
|
||||
bytes, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
size := len(bytes)
|
||||
if size != apple2RomSize && size != apple2eRomSize {
|
||||
panic("Rom size not supported")
|
||||
}
|
||||
|
||||
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])
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ package apple2
|
||||
|
||||
type cardBase struct {
|
||||
a *Apple2
|
||||
rom []memoryPage
|
||||
rom *memoryRange
|
||||
slot int
|
||||
ssr [16]softSwitchR
|
||||
ssw [16]softSwitchW
|
||||
@ -11,8 +11,9 @@ type cardBase struct {
|
||||
func (c *cardBase) insert(a *Apple2, slot int) {
|
||||
c.a = a
|
||||
c.slot = slot
|
||||
if slot != 0 && c.rom[0] != nil {
|
||||
a.mmu.setPage(uint8(0xC0+slot), c.rom[0])
|
||||
if slot != 0 && c.rom != nil {
|
||||
c.rom.base = uint16(0xC000 + slot*0x100)
|
||||
a.mmu.setPage(uint8(0xC0+slot), c.rom)
|
||||
}
|
||||
|
||||
for i := 0; i < 0x10; i++ {
|
||||
|
@ -30,7 +30,7 @@ type cardDisk2Drive struct {
|
||||
|
||||
func newCardDisk2(filename string) *cardDisk2 {
|
||||
var c cardDisk2
|
||||
c.rom = loadCardRom(filename)
|
||||
c.rom = newMemoryRange(0, loadCardRom(filename))
|
||||
|
||||
// Phase control soft switches
|
||||
// Lazy emulation. It only checks for phases on and move the head
|
||||
@ -137,29 +137,12 @@ func newCardDisk2(filename string) *cardDisk2 {
|
||||
return &c
|
||||
}
|
||||
|
||||
func loadCardRom(filename string) []memoryPage {
|
||||
bytes, err := ioutil.ReadFile(filename)
|
||||
func loadCardRom(filename string) []uint8 {
|
||||
data, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
size := len(bytes)
|
||||
pages := size / 256
|
||||
if (size % 256) > 0 {
|
||||
pages++
|
||||
}
|
||||
|
||||
rom := make([]romPage, pages)
|
||||
for i := 0; i < size; i++ {
|
||||
rom[i>>8].burn(uint8(i), bytes[i])
|
||||
}
|
||||
|
||||
memPages := make([]memoryPage, pages)
|
||||
for i := range rom {
|
||||
memPages[i] = &rom[i]
|
||||
}
|
||||
|
||||
return memPages
|
||||
return data
|
||||
}
|
||||
|
||||
func (d *cardDisk2Drive) insertDiskette(dt *diskette16sector) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package apple2
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
@ -33,41 +34,25 @@ func (d *diskette16sector) read(track int, position int) (value uint8, newPositi
|
||||
func loadDisquette(filename string) *diskette16sector {
|
||||
var d diskette16sector
|
||||
|
||||
f, err := os.Open(filename)
|
||||
data, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer f.Close()
|
||||
size := len(data)
|
||||
|
||||
stats, statsErr := f.Stat()
|
||||
if statsErr != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
size := stats.Size()
|
||||
if size == nibImageSize {
|
||||
// Load file already in nib format
|
||||
for i := 0; i < numberOfTracks; i++ {
|
||||
d.track[i] = make([]byte, nibBytesPerTrack)
|
||||
n, err := f.Read(d.track[i])
|
||||
if err != nil || n != nibBytesPerTrack {
|
||||
panic("Error loading file")
|
||||
}
|
||||
d.track[i] = data[nibBytesPerTrack*i : nibBytesPerTrack*(i+1)]
|
||||
}
|
||||
} else if size == dskImageSize {
|
||||
// Load file in dsk format
|
||||
data := make([]byte, dskImageSize)
|
||||
n, err := f.Read(data)
|
||||
if err != nil || n != dskImageSize {
|
||||
panic("Error loading file")
|
||||
}
|
||||
// Convert to nib
|
||||
for i := 0; i < numberOfTracks; i++ {
|
||||
trackData := data[i*bytesPerTrack : (i+1)*bytesPerTrack]
|
||||
d.track[i] = nibEncodeTrack(trackData, defaultVolumeTag, byte(i))
|
||||
}
|
||||
} else {
|
||||
panic("Disk size with nib format has to be 232960 bytes")
|
||||
panic("Invalid disk size")
|
||||
}
|
||||
|
||||
return &d
|
||||
|
@ -80,32 +80,26 @@ func (p *ioC0Page) setSpeakerProvider(s SpeakerProvider) {
|
||||
p.speaker = s
|
||||
}
|
||||
|
||||
func (p *ioC0Page) Peek(address uint8) uint8 {
|
||||
func (p *ioC0Page) peek(address uint16) uint8 {
|
||||
//fmt.Printf("Peek on $C0%02x ", address)
|
||||
ss := p.softSwitchesR[address]
|
||||
pageAddress := uint8(address)
|
||||
ss := p.softSwitchesR[pageAddress]
|
||||
if ss == nil {
|
||||
if p.apple2.panicSS {
|
||||
panic(fmt.Sprintf("Unknown softswitch on read to 0xC0%02x", address))
|
||||
panic(fmt.Sprintf("Unknown softswitch on read to 0xC0%02x", pageAddress))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
return ss(p)
|
||||
}
|
||||
|
||||
func (p *ioC0Page) internalPeek(address uint8) uint8 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (p *ioC0Page) all() []uint8 {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *ioC0Page) Poke(address uint8, value uint8) {
|
||||
func (p *ioC0Page) poke(address uint16, value uint8) {
|
||||
//fmt.Printf("Poke on $C0%02x with %02x ", address, value)
|
||||
ss := p.softSwitchesW[address]
|
||||
pageAddress := uint8(address)
|
||||
ss := p.softSwitchesW[pageAddress]
|
||||
if ss == nil {
|
||||
if p.apple2.panicSS {
|
||||
panic(fmt.Sprintf("Unknown softswitch on write to 0xC0%02x", address))
|
||||
panic(fmt.Sprintf("Unknown softswitch on write to 0xC0%02x", pageAddress))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -1,26 +1,25 @@
|
||||
package apple2
|
||||
|
||||
import "io/ioutil"
|
||||
|
||||
// See https://fabiensanglard.net/fd_proxy/prince_of_persia/Inside%20the%20Apple%20IIe.pdf
|
||||
// See https://i.stack.imgur.com/yn21s.gif
|
||||
|
||||
type memoryManager struct {
|
||||
apple2 *Apple2
|
||||
// Map of assigned pages
|
||||
activeMemory [256]memoryPage
|
||||
activeMemoryRead [256]memoryHandler
|
||||
activeMemoryWrite [256]memoryHandler
|
||||
|
||||
// Pages prepared to be paged in and out
|
||||
physicalMainRAM []ramPage // 0x0000 to 0xbfff, Up to 48 Kb
|
||||
physicalROM []romPage // 0xd000 to 0xffff, 12 Kb
|
||||
physicalROMe []romPage // 0xc000 to 0xcfff, Zero or 4bk in the Apple2e
|
||||
unassignedExpansionROM []unassignedPage // 0xc000 to 0xcfff
|
||||
physicalMainRAM *memoryRange // 0x0000 to 0xbfff, Up to 48 Kb
|
||||
physicalROM *memoryRange // 0xd000 to 0xffff, 12 Kb
|
||||
physicalROMe *memoryRange // 0xc000 to 0xcfff, Zero or 4bk in the Apple2e
|
||||
}
|
||||
|
||||
// memoryPage is a data page of 256 bytes
|
||||
type memoryPage interface {
|
||||
Peek(uint8) uint8
|
||||
Poke(uint8, uint8)
|
||||
internalPeek(uint8) uint8
|
||||
all() []uint8
|
||||
type memoryHandler interface {
|
||||
peek(uint16) uint8
|
||||
poke(uint16, uint8)
|
||||
}
|
||||
|
||||
const (
|
||||
@ -34,18 +33,11 @@ func (mmu *memoryManager) Peek(address uint16) uint8 {
|
||||
}
|
||||
|
||||
hi := uint8(address >> 8)
|
||||
lo := uint8(address)
|
||||
return mmu.activeMemory[hi].Peek(lo)
|
||||
}
|
||||
|
||||
func (mmu *memoryManager) internalPeek(address uint16) uint8 {
|
||||
hi := uint8(address >> 8)
|
||||
lo := uint8(address)
|
||||
return mmu.activeMemory[hi].internalPeek(lo)
|
||||
}
|
||||
|
||||
func (mmu *memoryManager) internalPage(hi uint8) []uint8 {
|
||||
return mmu.activeMemory[hi].all()
|
||||
mh := mmu.activeMemoryRead[hi]
|
||||
if mh == nil {
|
||||
return 0xf4 // Or some random number
|
||||
}
|
||||
return mh.peek(address)
|
||||
}
|
||||
|
||||
// Poke sets the data at the given address
|
||||
@ -54,15 +46,24 @@ func (mmu *memoryManager) Poke(address uint16, value uint8) {
|
||||
mmu.resetSlotExpansionRoms()
|
||||
}
|
||||
hi := uint8(address >> 8)
|
||||
lo := uint8(address)
|
||||
mmu.activeMemory[hi].Poke(lo, value)
|
||||
mh := mmu.activeMemoryWrite[hi]
|
||||
if mh == nil {
|
||||
return
|
||||
}
|
||||
mh.poke(address, value)
|
||||
}
|
||||
|
||||
// SetPage assigns a MemoryPage implementation on the page given
|
||||
func (mmu *memoryManager) setPage(index uint8, page memoryPage) {
|
||||
//fmt.Printf("Assigning page 0x%02x type %s\n", index, reflect.TypeOf(page))
|
||||
mmu.activeMemory[index] = page
|
||||
func (mmu *memoryManager) setPage(index uint8, mh memoryHandler) {
|
||||
mmu.setPageRead(index, mh)
|
||||
mmu.setPageWrite(index, mh)
|
||||
}
|
||||
|
||||
func (mmu *memoryManager) setPageRead(index uint8, mh memoryHandler) {
|
||||
mmu.activeMemoryRead[index] = mh
|
||||
}
|
||||
|
||||
func (mmu *memoryManager) setPageWrite(index uint8, mh memoryHandler) {
|
||||
mmu.activeMemoryWrite[index] = mh
|
||||
}
|
||||
|
||||
// When 0xcfff is accessed the card expansion rom is unassigned
|
||||
@ -71,9 +72,8 @@ func (mmu *memoryManager) resetSlotExpansionRoms() {
|
||||
// Ignore if the Apple2 shadow ROM is active
|
||||
return
|
||||
}
|
||||
for i := 8; i < 16; i++ {
|
||||
p := mmu.unassignedExpansionROM[i]
|
||||
mmu.setPage(uint8(i+0xc0), &p)
|
||||
for i := uint8(0xc8); i < 0xd0; i++ {
|
||||
mmu.setPage(i, nil)
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,25 +82,43 @@ func newMemoryManager(a *Apple2) *memoryManager {
|
||||
mmu.apple2 = a
|
||||
|
||||
// Assign RAM from 0x0000 to 0xbfff, 48kb
|
||||
mmu.physicalMainRAM = make([]ramPage, 0xc0)
|
||||
for i := 0; i <= 0xbf; i++ {
|
||||
mmu.setPage(uint8(i), &(mmu.physicalMainRAM[i]))
|
||||
ram := make([]uint8, 0xc000)
|
||||
mmu.physicalMainRAM = newMemoryRange(0, ram)
|
||||
for i := 0; i < 0xc000; i = i + 0x100 {
|
||||
mmu.setPage(uint8(i>>8), mmu.physicalMainRAM)
|
||||
}
|
||||
|
||||
// Set the 0xc100 to 0xcfff as unasigned, 4kb. It wil be taken by slot cards.
|
||||
mmu.unassignedExpansionROM = make([]unassignedPage, 0x10)
|
||||
for i := 1; i < 0x10; i++ {
|
||||
page := uint8(i + 0xc0)
|
||||
p := &mmu.unassignedExpansionROM[i]
|
||||
p.page = page
|
||||
mmu.setPage(page, p)
|
||||
}
|
||||
return &mmu
|
||||
}
|
||||
|
||||
func (mmu *memoryManager) loadRom(filename string) {
|
||||
data, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
size := len(data)
|
||||
if size != apple2RomSize && size != apple2eRomSize {
|
||||
panic("Rom size not supported")
|
||||
}
|
||||
|
||||
a := mmu.apple2
|
||||
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 = newMemoryRange(0xc000, data[0:extraRomSize])
|
||||
romStart = extraRomSize
|
||||
}
|
||||
|
||||
a.mmu.physicalROM = newMemoryRange(0xd000, data[romStart:])
|
||||
mmu.resetRomPaging()
|
||||
}
|
||||
|
||||
func (mmu *memoryManager) resetRomPaging() {
|
||||
// Assign the first 12kb of ROM from 0xd000 to 0xfff
|
||||
for i := 0xd0; i <= 0xff; i++ {
|
||||
mmu.setPage(uint8(i), &(mmu.physicalROM[i-0xd0]))
|
||||
for i := 0x0000; i < 0x3000; i = i + 0x100 {
|
||||
mmu.setPageRead(uint8(0xd0+(i>>8)), mmu.physicalROM)
|
||||
}
|
||||
}
|
||||
|
25
apple2/memoryRange.go
Normal file
25
apple2/memoryRange.go
Normal file
@ -0,0 +1,25 @@
|
||||
package apple2
|
||||
|
||||
type memoryRange struct {
|
||||
base uint16
|
||||
data []uint8
|
||||
}
|
||||
|
||||
func newMemoryRange(base uint16, data []uint8) *memoryRange {
|
||||
var m memoryRange
|
||||
m.base = base
|
||||
m.data = data
|
||||
return &m
|
||||
}
|
||||
|
||||
func (m *memoryRange) peek(address uint16) uint8 {
|
||||
return m.data[address-m.base]
|
||||
}
|
||||
|
||||
func (m *memoryRange) poke(address uint16, value uint8) {
|
||||
m.data[address-m.base] = value
|
||||
}
|
||||
|
||||
func (m *memoryRange) subRange(a, b uint16) []uint8 {
|
||||
return m.data[a-m.base : b-m.base]
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
package apple2
|
||||
|
||||
type rxmPage struct {
|
||||
data [256]uint8
|
||||
observer func(address uint8, isWrite bool)
|
||||
}
|
||||
|
||||
type ramPage struct {
|
||||
rxmPage
|
||||
}
|
||||
|
||||
type romPage struct {
|
||||
rxmPage
|
||||
}
|
||||
|
||||
func (p *rxmPage) Peek(address uint8) uint8 {
|
||||
p.touch(address, false)
|
||||
return p.data[address]
|
||||
}
|
||||
|
||||
func (p *rxmPage) internalPeek(address uint8) uint8 {
|
||||
return p.data[address]
|
||||
}
|
||||
|
||||
func (p *rxmPage) all() []uint8 {
|
||||
return p.data[:]
|
||||
}
|
||||
|
||||
func (p *rxmPage) Poke(address uint8, value uint8) {
|
||||
p.touch(address, true)
|
||||
p.data[address] = value
|
||||
}
|
||||
|
||||
func (p *rxmPage) touch(address uint8, isWrite bool) {
|
||||
if p.observer != nil {
|
||||
p.observer(address, isWrite)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *romPage) Poke(address uint8, value uint8) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
func (p *romPage) burn(address uint8, value uint8) {
|
||||
p.data[address] = value
|
||||
}
|
@ -30,11 +30,7 @@ func getHiResLine(a *Apple2, line int, page int) []uint8 {
|
||||
}
|
||||
|
||||
address += getHiResLineOffset(line)
|
||||
hi := uint8(address >> 8)
|
||||
lo := uint8(address)
|
||||
|
||||
memPage := a.mmu.internalPage(hi)
|
||||
return memPage[lo : lo+40]
|
||||
return a.mmu.physicalMainRAM.subRange(address, address+40)
|
||||
}
|
||||
|
||||
func snapshotHiResModeMonoShift(a *Apple2, page int, mixedMode bool, light color.Color) *image.RGBA {
|
||||
|
@ -31,7 +31,7 @@ func getTextChar(a *Apple2, col int, line int, page int) uint8 {
|
||||
address = textPage2Address
|
||||
}
|
||||
address += getTextCharOffset(col, line)
|
||||
return a.mmu.internalPeek(address)
|
||||
return a.mmu.physicalMainRAM.subRange(address, address+1)[0]
|
||||
}
|
||||
|
||||
func snapshotTextMode(a *Apple2, page int, mixMode bool, light color.Color) *image.RGBA {
|
||||
|
@ -46,8 +46,8 @@ func getSoftSwitchExt(ioFlag uint8, dstValue uint8, action softSwitchExtAction)
|
||||
|
||||
func softSwitchIntCxRomOn(io *ioC0Page) {
|
||||
mmu := io.apple2.mmu
|
||||
for i := uint8(1); i < 16; i++ {
|
||||
mmu.setPage(uint8(0xc0+i), &mmu.physicalROMe[i])
|
||||
for i := 0x100; i < 0x1000; i = i + 0x100 {
|
||||
mmu.setPage(uint8(i>>8), mmu.physicalROMe)
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ func softSwitchIntCxRomOff(io *ioC0Page) {
|
||||
// TODO restore all the ROM from the slot for 0xc1 to 0xc7
|
||||
mmu := io.apple2.mmu
|
||||
for i := 1; i < 16; i++ {
|
||||
mmu.setPage(uint8(0xc0+i), &mmu.unassignedExpansionROM[i])
|
||||
mmu.setPage(uint8(0xc0+i), nil)
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,13 +65,13 @@ func softSwitchSlotC3RomOn(io *ioC0Page) {
|
||||
}
|
||||
// TODO restore the slot 3 ROM
|
||||
mmu := io.apple2.mmu
|
||||
mmu.setPage(0xC3, &mmu.unassignedExpansionROM[3])
|
||||
mmu.setPage(0xC3, nil)
|
||||
}
|
||||
|
||||
func softSwitchSlotC3RomOff(io *ioC0Page) {
|
||||
if io.isSoftSwitchActive(ioFlagIntCxRom) {
|
||||
return // Ignore if allt the Apple2 shadow ROM is active
|
||||
return // Ignore if alt the Apple2 shadow ROM is active
|
||||
}
|
||||
mmu := io.apple2.mmu
|
||||
mmu.setPage(0xC3, &mmu.physicalROMe[3])
|
||||
mmu.setPageRead(0xC3, mmu.physicalROMe)
|
||||
}
|
||||
|
@ -1,24 +0,0 @@
|
||||
package apple2
|
||||
|
||||
type unassignedPage struct {
|
||||
page uint8
|
||||
}
|
||||
|
||||
func (p *unassignedPage) Peek(address uint8) uint8 {
|
||||
//fmt.Printf("Read on address 0x%02x%02x\n", p.page, address)
|
||||
//panic(address)
|
||||
return 0xdd
|
||||
}
|
||||
|
||||
func (p *unassignedPage) internalPeek(address uint8) uint8 {
|
||||
return 0xdd
|
||||
}
|
||||
|
||||
func (p *unassignedPage) all() []uint8 {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *unassignedPage) Poke(address uint8, value uint8) {
|
||||
//fmt.Printf("Write on address 0x%02x%02x\n", p.page, address)
|
||||
//panic(address)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user