From 3660e0ae98553ed50fac7aeed220737ae8f47d10 Mon Sep 17 00:00:00 2001 From: Ivan Izaguirre Date: Sun, 3 Nov 2019 18:22:10 +0100 Subject: [PATCH] Memory manager rewritten. Logic calculated on every access. --- apple2Setup.go | 12 +- base64a.go | 3 - base64aRom.go | 30 ++--- cardBase.go | 4 +- cardLanguage.go | 69 ++--------- cardLogger.go | 15 --- cardSaturn.go | 88 +++---------- ioC0Page.go | 6 + memoryManager.go | 309 +++++++++++++++++++++++++++++----------------- softSwitches2e.go | 8 +- 10 files changed, 242 insertions(+), 302 deletions(-) diff --git a/apple2Setup.go b/apple2Setup.go index 8a87c6a..6ed892e 100644 --- a/apple2Setup.go +++ b/apple2Setup.go @@ -13,10 +13,7 @@ func newApple2plus() *Apple2 { a.Name = "Apple ][+" a.mmu = newMemoryManager(&a) a.cpu = core6502.NewNMOS6502(a.mmu) - - // Set the io in 0xc000 a.io = newIoC0Page(&a) - a.mmu.setPages(0xc0, 0xc0, a.io) addApple2SoftSwitches(a.io) return &a @@ -28,10 +25,7 @@ func newApple2e() *Apple2 { a.Name = "Apple IIe" a.mmu = newMemoryManager(&a) a.cpu = core6502.NewCMOS65c02(a.mmu) - - // Set the io in 0xc000 a.io = newIoC0Page(&a) - a.mmu.setPages(0xc0, 0xc0, a.io) addApple2SoftSwitches(a.io) addApple2ESoftSwitches(a.io) @@ -44,10 +38,7 @@ func newApple2eEnhanced() *Apple2 { a.Name = "Apple //e" a.mmu = newMemoryManager(&a) a.cpu = core6502.NewCMOS65c02(a.mmu) - - // Set the io in 0xc000 a.io = newIoC0Page(&a) - a.mmu.setPages(0xc0, 0xc0, a.io) addApple2SoftSwitches(a.io) addApple2ESoftSwitches(a.io) @@ -100,8 +91,7 @@ func (a *Apple2) LoadRom(filename string) error { romStart = extraRomSize } - mmu.physicalROM = newMemoryRange(0xd000, data[romStart:]) - mmu.resetRomPaging() + mmu.physicalROM[0] = newMemoryRange(0xd000, data[romStart:]) return nil } diff --git a/base64a.go b/base64a.go index 4646584..fc66c0f 100644 --- a/base64a.go +++ b/base64a.go @@ -15,10 +15,7 @@ func newBase64a() *Apple2 { a.Name = "Base 64A" a.mmu = newMemoryManager(&a) a.cpu = core6502.NewNMOS6502(a.mmu) - - // Set the io in 0xc000 a.io = newIoC0Page(&a) - a.mmu.setPages(0xc0, 0xc0, a.io) addApple2SoftSwitches(a.io) addBase64aSoftSwitches(a.io) diff --git a/base64aRom.go b/base64aRom.go index b79f5f1..c9fe131 100644 --- a/base64aRom.go +++ b/base64aRom.go @@ -8,12 +8,6 @@ import ( Copam BASE64A uses paginated ROM */ -// Base64aROM Models the paginated ROM on a BASE64A clone -type base64aROM struct { - romBanks [4]*memoryRange - romBank uint8 -} - const ( // There are 6 ROM chips. Each can have 4Kb or 8Kb. They can fill // 2 or 4 banks with 2kb windows. @@ -43,38 +37,34 @@ func loadBase64aRom(a *Apple2) error { } // Create banks - var r base64aROM for j := range romBanksBytes { - r.romBanks[j] = newMemoryRange(0xd000, romBanksBytes[j]) + a.mmu.physicalROM[j] = newMemoryRange(0xd000, romBanksBytes[j]) } // Start with first bank active - r.changeBank(a.mmu, 0) + a.mmu.setActiveROMPage(0) // Add rom soft switches. They use the annunciator 0 and 1 a.io.addSoftSwitchRW(0x58, func(*ioC0Page) uint8 { - r.changeBank(a.mmu, r.romBank&2) + p := a.mmu.getActiveROMPage() + a.mmu.setActiveROMPage(p & 2) return 0 }, "ANN0OFF-ROM") a.io.addSoftSwitchRW(0x59, func(*ioC0Page) uint8 { - r.changeBank(a.mmu, r.romBank|1) + p := a.mmu.getActiveROMPage() + a.mmu.setActiveROMPage(p | 1) return 0 }, "ANN0ON-ROM") a.io.addSoftSwitchRW(0x5A, func(*ioC0Page) uint8 { - r.changeBank(a.mmu, r.romBank&1) + p := a.mmu.getActiveROMPage() + a.mmu.setActiveROMPage(p & 1) return 0 }, "ANN1OFF-ROM") a.io.addSoftSwitchRW(0x5B, func(*ioC0Page) uint8 { - r.changeBank(a.mmu, r.romBank|2) + p := a.mmu.getActiveROMPage() + a.mmu.setActiveROMPage(p | 2) return 0 }, "ANN1ON-ROM") return nil } - -func (r *base64aROM) changeBank(mmu *memoryManager, bank uint8) { - r.romBank = bank - //fmt.Printf("Change to ROM bank #%v\n", r.romBank) - mmu.physicalROM = r.romBanks[r.romBank] - mmu.resetRomPaging() // If rom was not active. This is going too far? -} diff --git a/cardBase.go b/cardBase.go index 332065c..f2c1cc9 100644 --- a/cardBase.go +++ b/cardBase.go @@ -38,12 +38,12 @@ func (c *cardBase) assign(a *Apple2, slot int) { c.slot = slot if slot != 0 && c.rom != nil { c.rom.base = uint16(0xc000 + slot*0x100) - a.mmu.setPagesRead(uint8(0xc0+slot), uint8(0xc0+slot), c.rom) + a.mmu.setCardROM(slot, c.rom) } if slot != 0 && c.romExtra != nil { c.romExtra.base = uint16(0xc800) - a.mmu.prepareCardExtraRom(slot, c.romExtra) + a.mmu.setCardROMExtra(slot, c.romExtra) } for i := 0; i < 0x10; i++ { diff --git a/cardLanguage.go b/cardLanguage.go index fd6d0a8..59be0bc 100644 --- a/cardLanguage.go +++ b/cardLanguage.go @@ -32,14 +32,11 @@ type cardLanguage struct { cardBase readState bool writeState uint8 - activeBank uint8 - ramBankA *memoryRange // First 4kb to map in 0xD000-0xDFFF - ramBankB *memoryRange // Second 4kb to map in 0xD000-0xDFFF - ramUpper *memoryRange // Upper 8kb to map in 0xE000-0xFFFF + altBank bool } const ( - // Write enabling requires two sofstwitch accesses + // Write enabling requires two softswitch accesses lcWriteDisabled = 0 lcWriteHalfEnabled = 1 lcWriteEnabled = 2 @@ -48,11 +45,9 @@ const ( func (c *cardLanguage) assign(a *Apple2, slot int) { c.readState = false c.writeState = lcWriteEnabled - c.activeBank = 1 + c.altBank = true - c.ramBankA = newMemoryRange(0xd000, make([]uint8, 0x1000)) - c.ramBankB = newMemoryRange(0xd000, make([]uint8, 0x1000)) - c.ramUpper = newMemoryRange(0xe000, make([]uint8, 0x2000)) + a.mmu.initLanguageRAM(1) for i := uint8(0x0); i <= 0xf; i++ { iCopy := i @@ -70,7 +65,7 @@ func (c *cardLanguage) assign(a *Apple2, slot int) { } func (c *cardLanguage) ssAction(ss uint8, write bool) { - c.activeBank = (ss >> 3) & 1 + c.altBank = ((ss >> 3) & 1) == 1 action := ss & 0x3 switch action { case 0: @@ -103,30 +98,8 @@ func (c *cardLanguage) ssAction(ss uint8, write bool) { c.applyState() } -func (c *cardLanguage) getActiveBank() *memoryRange { - if c.activeBank == 0 { - return c.ramBankA - } - return c.ramBankB -} - func (c *cardLanguage) applyState() { - mmu := c.a.mmu - - if c.readState { - mmu.setPagesRead(0xd0, 0xdf, c.getActiveBank()) - mmu.setPagesRead(0xe0, 0xff, c.ramUpper) - } else { - mmu.setPagesRead(0xd0, 0xff, mmu.physicalROM) - } - - if c.writeState == lcWriteEnabled { - mmu.setPagesWrite(0xd0, 0xdf, c.getActiveBank()) - mmu.setPagesWrite(0xe0, 0xff, c.ramUpper) - } else { - mmu.setPagesWrite(0xd0, 0xff, nil) - } - + c.a.mmu.setLanguageRAM(c.readState, c.writeState == lcWriteEnabled, c.altBank) } func (c *cardLanguage) save(w io.Writer) error { @@ -138,23 +111,10 @@ func (c *cardLanguage) save(w io.Writer) error { if err != nil { return err } - err = binary.Write(w, binary.BigEndian, c.activeBank) + err = binary.Write(w, binary.BigEndian, c.altBank) if err != nil { return err } - err = c.ramBankA.save(w) - if err != nil { - return err - } - err = c.ramBankB.save(w) - if err != nil { - return err - } - err = c.ramUpper.save(w) - if err != nil { - return err - } - return c.cardBase.save(w) } @@ -167,23 +127,10 @@ func (c *cardLanguage) load(r io.Reader) error { if err != nil { return err } - err = binary.Read(r, binary.BigEndian, &c.activeBank) + err = binary.Read(r, binary.BigEndian, &c.altBank) if err != nil { return err } - err = c.ramBankA.load(r) - if err != nil { - return err - } - err = c.ramBankB.load(r) - if err != nil { - return err - } - err = c.ramUpper.load(r) - if err != nil { - return err - } - c.applyState() return c.cardBase.load(r) } diff --git a/cardLogger.go b/cardLogger.go index a9b665d..84a7399 100644 --- a/cardLogger.go +++ b/cardLogger.go @@ -24,20 +24,5 @@ func (c *cardLogger) assign(a *Apple2, slot int) { }, "LOGGERW") } - if slot != 0 { - a.mmu.setPagesRead(uint8(0xc0+slot), uint8(0xc0+slot), c) - } c.cardBase.assign(a, slot) } - -// MemoryHandler implementation -func (c *cardLogger) peek(address uint16) uint8 { - fmt.Printf("[cardLogger] Read in %x.\n", address) - c.a.dumpDebugInfo() - - return 0xf3 -} - -func (*cardLogger) poke(address uint16, value uint8) { - fmt.Printf("[cardLogger] Write %x in %x.\n", value, address) -} diff --git a/cardSaturn.go b/cardSaturn.go index 5b93978..d68f91a 100644 --- a/cardSaturn.go +++ b/cardSaturn.go @@ -17,20 +17,10 @@ type cardSaturn struct { cardBase readState bool writeState uint8 - activeBank uint8 + altBank bool activeBlock uint8 - ramBankA [saturnBlocks]*memoryRange // First 4kb to map in 0xD000-0xDFFF - ramBankB [saturnBlocks]*memoryRange // Second 4kb to map in 0xD000-0xDFFF - ramUpper [saturnBlocks]*memoryRange // Upper 8kb to map in 0xE000-0xFFFF } -const ( - // Write enabling requires two sofstwitch accesses - saturnWriteDisabled = 0 - saturnWriteHalfEnabled = 1 - saturnWriteEnabled = 2 -) - const ( saturnBlocks = 8 ) @@ -38,13 +28,10 @@ const ( func (c *cardSaturn) assign(a *Apple2, slot int) { c.readState = false c.writeState = lcWriteEnabled - c.activeBank = 1 + c.altBank = true + c.activeBlock = 0 + a.mmu.initLanguageRAM(saturnBlocks) - for i := 0; i < saturnBlocks; i++ { - c.ramBankA[i] = newMemoryRange(0xd000, make([]uint8, 0x1000)) - c.ramBankB[i] = newMemoryRange(0xd000, make([]uint8, 0x1000)) - c.ramUpper[i] = newMemoryRange(0xe000, make([]uint8, 0x2000)) - } for i := uint8(0x0); i <= 0xf; i++ { iCopy := i c.addCardSoftSwitchR(iCopy, func(*ioC0Page) uint8 { @@ -63,22 +50,22 @@ func (c *cardSaturn) ssAction(ss uint8, write bool) { switch ss { case 0: // RAM read, no writes - c.activeBank = 0 + c.altBank = false c.readState = true c.writeState = lcWriteDisabled case 1: // ROM read, RAM write - c.activeBank = 0 + c.altBank = false c.readState = false c.writeState++ case 2: // ROM read, no writes - c.activeBank = 0 + c.altBank = false c.readState = false c.writeState = lcWriteDisabled case 3: //RAM read, RAM write - c.activeBank = 0 + c.altBank = false c.readState = true c.writeState++ case 4: @@ -91,22 +78,22 @@ func (c *cardSaturn) ssAction(ss uint8, write bool) { c.activeBlock = 3 case 8: // RAM read, no writes - c.activeBank = 1 + c.altBank = true c.readState = true c.writeState = lcWriteDisabled case 9: // ROM read, RAM write - c.activeBank = 1 + c.altBank = true c.readState = false c.writeState++ case 10: // ROM read, no writes - c.activeBank = 1 + c.altBank = true c.readState = false c.writeState = lcWriteDisabled case 11: //RAM read, RAM write - c.activeBank = 1 + c.altBank = true c.readState = true c.writeState++ case 12: @@ -131,30 +118,9 @@ func (c *cardSaturn) ssAction(ss uint8, write bool) { c.applyState() } -func (c *cardSaturn) getActiveBank() [8]*memoryRange { - if c.activeBank == 0 { - return c.ramBankA - } - return c.ramBankB -} - func (c *cardSaturn) applyState() { - mmu := c.a.mmu - block := c.activeBlock - - if c.readState { - mmu.setPagesRead(0xd0, 0xdf, c.getActiveBank()[block]) - mmu.setPagesRead(0xe0, 0xff, c.ramUpper[block]) - } else { - mmu.setPagesRead(0xd0, 0xff, mmu.physicalROM) - } - - if c.writeState == lcWriteEnabled { - mmu.setPagesWrite(0xd0, 0xdf, c.getActiveBank()[block]) - mmu.setPagesWrite(0xe0, 0xff, c.ramUpper[block]) - } else { - mmu.setPagesWrite(0xd0, 0xff, nil) - } + c.a.mmu.setLanguageRAMBlock(c.activeBlock) + c.a.mmu.setLanguageRAM(c.readState, c.writeState == lcWriteEnabled, c.altBank) } func (c *cardSaturn) save(w io.Writer) error { @@ -167,7 +133,7 @@ func (c *cardSaturn) save(w io.Writer) error { if err != nil { return err } - err = binary.Write(w, binary.BigEndian, c.activeBank) + err = binary.Write(w, binary.BigEndian, c.altBank) if err != nil { return err } @@ -175,18 +141,6 @@ func (c *cardSaturn) save(w io.Writer) error { if err != nil { return err } - err = c.ramBankA[i].save(w) - if err != nil { - return err - } - err = c.ramBankB[i].save(w) - if err != nil { - return err - } - err = c.ramUpper[i].save(w) - if err != nil { - return err - } } return c.cardBase.save(w) } @@ -201,7 +155,7 @@ func (c *cardSaturn) load(r io.Reader) error { if err != nil { return err } - err = binary.Read(r, binary.BigEndian, &c.activeBank) + err = binary.Read(r, binary.BigEndian, &c.altBank) if err != nil { return err } @@ -209,16 +163,6 @@ func (c *cardSaturn) load(r io.Reader) error { if err != nil { return err } - err = c.ramBankA[i].load(r) - if err != nil { - return err - } - err = c.ramBankB[i].load(r) - if err != nil { - return err - } - err = c.ramUpper[i].load(r) - c.applyState() } return c.cardBase.load(r) diff --git a/ioC0Page.go b/ioC0Page.go index 4c02bd8..ff16ddf 100644 --- a/ioC0Page.go +++ b/ioC0Page.go @@ -114,6 +114,9 @@ func (p *ioC0Page) peek(address uint16) uint8 { pageAddress := uint8(address) ss := p.softSwitchesR[pageAddress] if ss == nil { + if p.trace { + fmt.Printf("Unknown softswitch on read to $%04x\n", address) + } if p.panicNotImplemented { panic(fmt.Sprintf("Unknown softswitch on read to $%04x", address)) } @@ -131,6 +134,9 @@ func (p *ioC0Page) poke(address uint16, value uint8) { pageAddress := uint8(address) ss := p.softSwitchesW[pageAddress] if ss == nil { + if p.trace { + fmt.Printf("Unknown softswitch on write to $%04x\n", address) + } if p.panicNotImplemented { panic(fmt.Sprintf("Unknown softswitch on write to $%04x", address)) } diff --git a/memoryManager.go b/memoryManager.go index 32f02bd..70f8fbc 100644 --- a/memoryManager.go +++ b/memoryManager.go @@ -2,6 +2,7 @@ package apple2 import ( "encoding/binary" + "fmt" "io" ) @@ -10,137 +11,218 @@ import ( type memoryManager struct { apple2 *Apple2 - // Map of assigned pages - activeMemoryRead [256]memoryHandler - activeMemoryWrite [256]memoryHandler - // Pages prepared to be paged in and out - physicalMainRAM *memoryRange // 0x0000 to 0xbfff, Up to 48 Kb - physicalROM memoryHandler // 0xd000 to 0xffff, 12 Kb - physicalROMe memoryHandler // 0xc000 to 0xcfff, Zero or 4bk in the Apple2e + // Main RAM area: 0x0000 to 0xbfff + physicalMainRAM *memoryRange // 0x0000 to 0xbfff, Up to 48 Kb + physicalMainRAMAlt *memoryRange // 0x0000 to 0xbfff, Up to 48 Kb. Additional - // Pages prapared for optional card ROM banks - activeSlot uint8 - cardsROMExtra [8]memoryHandler // 0xc800 to 0xcfff. for each card + // Slots area: 0xc000 to 0xcfff + cardsROM [8]memoryHandler //0xcs00 to 0xcsff. 256 bytes for each card + cardsROMExtra [8]memoryHandler // 0xc800 to 0xcfff. 2048 bytes for each card + physicalROMe memoryHandler // 0xc100 to 0xcfff, Zero or 4kb in the Apple2e + + // Upper area: 0xd000 to 0xffff + physicalROM [4]memoryHandler // 0xd000 to 0xffff, 12 Kb. Up to four banks + physicalDRAM []memoryHandler // 0xd000 to 0xdfff, 4KB. Up to 8 banks. + physicalDAltRAM []memoryHandler // 0xd000 to 0xdfff, 4KB. Up to 8 banks. + physicalEFRAM []memoryHandler // 0xe000 to 0xffff, 8KB. Up to 8 banks. + + // Pages prapared for optional card ROM banks in 0xc800 to 0xcfff + altMainRAMActiveRead bool // Use extra RAM on the 128KB Apple2e for read + altMainRAMActiveWrite bool // Use extra RAM on the 128KB Apple2e for write + + c3ROMActive bool // Apple2e slot 3 ROM shadow + cxROMActive bool // Apple2e slots ROM shadow + activeSlot uint8 // Active slot owner of 0xc800 to 0xcfff + + lcSelectedBlock uint8 // Language card block selected. Usually, allways 0. But Saturn has 8 + lcActiveRead bool // Upper RAM active for read + lcActiveWrite bool // Upper RAM active for read + lcAltBank bool // Alternate + romPage uint8 // Active ROM page } +const ( + ioC8Off uint16 = 0xcfff + addressLimitMainRAM uint16 = 0xbfff + addressLimitIO uint16 = 0xc0ff + addressLimitSlots uint16 = 0xc7ff + addressLimitSlotsExtra uint16 = 0xcfff + addressLimitDArea uint16 = 0xdfff +) + type memoryHandler interface { peek(uint16) uint8 poke(uint16, uint8) } -const ( - ioC8Off uint16 = 0xCFFF -) - -func (mmu *memoryManager) access(address uint16, activeMemory *[256]memoryHandler) memoryHandler { - if address == ioC8Off { - mmu.resetSlotExpansionRoms() - } - - hi := uint8(address >> 8) - if hi >= 0xC1 && hi <= 0xC7 { - slot := hi - 0xC0 - if slot != mmu.activeSlot { - mmu.activateCardRomExtra(slot) - } - } - mh := activeMemory[hi] - if mh == nil { - return nil - } - return mh -} - -// Peek returns the data on the given address -func (mmu *memoryManager) Peek(address uint16) uint8 { - mh := mmu.access(address, &mmu.activeMemoryRead) - if mh == nil { - return 0xf4 // Or some random number - } - return mh.peek(address) -} - -// Poke sets the data at the given address -func (mmu *memoryManager) Poke(address uint16, value uint8) { - mh := mmu.access(address, &mmu.activeMemoryWrite) - if mh == nil { - return - } - mh.poke(address, value) -} - -func (mmu *memoryManager) setPages(begin uint8, end uint8, mh memoryHandler) { - mmu.setPagesRead(begin, end, mh) - mmu.setPagesWrite(begin, end, mh) -} - -func (mmu *memoryManager) setPagesRead(begin uint8, end uint8, mh memoryHandler) { - i := begin - for { - mmu.activeMemoryRead[i] = mh - if i == end { - break - } - i++ - } -} - -func (mmu *memoryManager) setPagesWrite(begin uint8, end uint8, mh memoryHandler) { - i := begin - for { - mmu.activeMemoryWrite[i] = mh - if i == end { - break - } - i++ - } -} - -func (mmu *memoryManager) prepareCardExtraRom(slot int, mh memoryHandler) { - mmu.cardsROMExtra[slot] = mh -} - -// When 0xcfff is accessed the card expansion rom is unassigned -func (mmu *memoryManager) resetSlotExpansionRoms() { - if mmu.apple2.io.isSoftSwitchActive(ioFlagIntCxRom) { - // Ignore if the Apple2 shadow ROM is active - return - } - mmu.activeSlot = 0 - mmu.setPagesRead(0xc8, 0xcf, nil) -} - -// When a card base ROM is accesed the extra rom is assigned if available -func (mmu *memoryManager) activateCardRomExtra(slot uint8) { - //fmt.Printf("Activate slot %v\n", slot) - if mmu.cardsROMExtra[slot] != nil { - mmu.setPagesRead(0xC8, 0xCF, mmu.cardsROMExtra[slot]) - } - mmu.activeSlot = slot -} - -func (mmu *memoryManager) resetRomPaging() { - // Assign the first 12kb of ROM from 0xd000 to 0xffff - mmu.setPagesRead(0xd0, 0xff, mmu.physicalROM) -} - -func (mmu *memoryManager) resetBaseRamPaging() { - // Assign the base RAM from 0x0000 to 0xbfff - mmu.setPages(0x00, 0xbf, mmu.physicalMainRAM) -} - func newMemoryManager(a *Apple2) *memoryManager { var mmu memoryManager mmu.apple2 = a ram := make([]uint8, 0xc000) // Reserve 48kb mmu.physicalMainRAM = newMemoryRange(0, ram) - mmu.resetBaseRamPaging() return &mmu } +func (mmu *memoryManager) accessRead(address uint16) memoryHandler { + // Main RAM area + if address <= addressLimitMainRAM { + if mmu.altMainRAMActiveRead { + return mmu.physicalMainRAMAlt + } + return mmu.physicalMainRAM + } + + // IO section + if address <= addressLimitIO { + return mmu.apple2.io + } + + // Slots sections + if address <= addressLimitSlotsExtra { + slot := uint8((address >> 8) & 0x07) + if mmu.cxROMActive { + return mmu.physicalROMe + } + // First slot area + if address <= addressLimitSlots { + if mmu.c3ROMActive && (slot == 3) { + return mmu.physicalROMe + } + mmu.activeSlot = slot + return mmu.cardsROM[slot] + } + // Extra slot area + if address == ioC8Off { + // Reset extra slot area owner + mmu.activeSlot = 0 + } + return mmu.cardsROMExtra[slot] + } + + // Upper address area + if mmu.lcActiveRead { + if address <= addressLimitDArea { + if mmu.lcAltBank { + return mmu.physicalDAltRAM[mmu.lcSelectedBlock] + } + return mmu.physicalDRAM[mmu.lcSelectedBlock] + } + return mmu.physicalEFRAM[mmu.lcSelectedBlock] + } + + // Use ROM + return mmu.physicalROM[mmu.romPage] +} + +func (mmu *memoryManager) accessWrite(address uint16) memoryHandler { + // Main RAM area + if address <= addressLimitMainRAM { + if mmu.altMainRAMActiveWrite { + return mmu.physicalMainRAMAlt + } + return mmu.physicalMainRAM + } + + // IO section + if address <= addressLimitIO { + return mmu.apple2.io + } + + // Slots sections + if address <= addressLimitSlotsExtra { + slot := uint8((address >> 8) & 0x07) + // First slot area + if address <= addressLimitSlots { + mmu.activeSlot = slot + return mmu.cardsROM[slot] + } + // Extra slot area + if address == ioC8Off { + // Reset extra slot area owner + mmu.activeSlot = 0 + } + return mmu.cardsROMExtra[slot] + } + + // Upper address area + if mmu.lcActiveWrite { + if address <= addressLimitDArea { + if mmu.lcAltBank { + return mmu.physicalDAltRAM[mmu.lcSelectedBlock] + } + return mmu.physicalDRAM[mmu.lcSelectedBlock] + } + return mmu.physicalEFRAM[mmu.lcSelectedBlock] + } + + // Use ROM + return mmu.physicalROM[mmu.romPage] +} + +// Peek returns the data on the given address +func (mmu *memoryManager) Peek(address uint16) uint8 { + mh := mmu.accessRead(address) + if mh == nil { + fmt.Printf("Reading void addressing 0x%x\n", address) + return 0xf4 // Or some random number + } + return mh.peek(address) +} + +// Poke sets the data at the given address +func (mmu *memoryManager) Poke(address uint16, value uint8) { + mh := mmu.accessWrite(address) + if mh == nil { + fmt.Printf("Writing to void addressing 0x%x\n", address) + return + } + mh.poke(address, value) +} + +// Memory initialization +func (mmu *memoryManager) setCardROM(slot int, mh memoryHandler) { + mmu.cardsROM[slot] = mh +} + +func (mmu *memoryManager) setCardROMExtra(slot int, mh memoryHandler) { + mmu.cardsROMExtra[slot] = mh +} + +func (mmu *memoryManager) initLanguageRAM(groups int) { + mmu.physicalDRAM = make([]memoryHandler, groups) + mmu.physicalDAltRAM = make([]memoryHandler, groups) + mmu.physicalEFRAM = make([]memoryHandler, groups) + for i := 0; i < groups; i++ { + mmu.physicalDRAM[i] = newMemoryRange(0xd000, make([]uint8, 0x1000)) + mmu.physicalDAltRAM[i] = newMemoryRange(0xd000, make([]uint8, 0x1000)) + mmu.physicalEFRAM[i] = newMemoryRange(0xe000, make([]uint8, 0x2000)) + } +} + +// Memory configuration +func (mmu *memoryManager) setActiveROMPage(page uint8) { + mmu.romPage = page +} + +func (mmu *memoryManager) getActiveROMPage() uint8 { + return mmu.romPage +} + +func (mmu *memoryManager) setLanguageRAM(readActive bool, writeActive bool, altBank bool) { + mmu.lcActiveRead = readActive + mmu.lcActiveWrite = writeActive + mmu.lcAltBank = altBank +} + +func (mmu *memoryManager) setLanguageRAMBlock(block uint8) { + block = block % uint8(len(mmu.physicalDRAM)) + mmu.lcSelectedBlock = block +} + +// TODO: complete save and load func (mmu *memoryManager) save(w io.Writer) error { err := mmu.physicalMainRAM.save(w) if err != nil { @@ -162,8 +244,7 @@ func (mmu *memoryManager) load(r io.Reader) error { if err != nil { return err } - mmu.activateCardRomExtra(mmu.activeSlot) + // mmu.activateCardRomExtra(mmu.activeSlot) - mmu.resetBaseRamPaging() return nil } diff --git a/softSwitches2e.go b/softSwitches2e.go index d7234f9..58e4722 100644 --- a/softSwitches2e.go +++ b/softSwitches2e.go @@ -82,21 +82,21 @@ func getSoftSwitchExt(ioFlag uint8, dstValue uint8, action softSwitchExtAction) } func softSwitchIntCxRomOn(io *ioC0Page) { - io.apple2.mmu.setPagesRead(0xc1, 0xcf, io.apple2.mmu.physicalROMe) + //io.apple2.mmu.setPagesRead(0xc1, 0xcf, io.apple2.mmu.physicalROMe) } func softSwitchIntCxRomOff(io *ioC0Page) { // TODO restore all the ROM from the slots for 0xc1 to 0xc7 - io.apple2.mmu.setPages(0xc1, 0xc7, nil) + //io.apple2.mmu.setPages(0xc1, 0xc7, nil) } func softSwitchSlotC3RomOn(io *ioC0Page) { // TODO restore the slot 3 ROM - io.apple2.mmu.setPages(0xc3, 0xc3, nil) + //io.apple2.mmu.setPages(0xc3, 0xc3, nil) } func softSwitchSlotC3RomOff(io *ioC0Page) { - io.apple2.mmu.setPagesRead(0xc3, 0xc3, io.apple2.mmu.physicalROMe) + //io.apple2.mmu.setPagesRead(0xc3, 0xc3, io.apple2.mmu.physicalROMe) } // TODO: apply state after persistance load