mirror of
https://github.com/ivanizag/izapple2.git
synced 2024-12-23 00:30:21 +00:00
ROM can be paged, refactor the Base64A ROM
This commit is contained in:
parent
63c982d976
commit
9c27175f86
40
base64a.go
40
base64a.go
@ -1,8 +1,6 @@
|
|||||||
package izapple2
|
package izapple2
|
||||||
|
|
||||||
import (
|
import "fmt"
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copam BASE64A adaptation.
|
Copam BASE64A adaptation.
|
||||||
@ -36,14 +34,16 @@ func loadBase64aRom(a *Apple2) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create banks
|
// Create paged ROM
|
||||||
for j := range romBanksBytes {
|
romData := make([]uint8, 0, base64aRomBankSize*base64aRomBankCount)
|
||||||
a.mmu.physicalROM[j] = newMemoryRange(0xd000, romBanksBytes[j], fmt.Sprintf("Base64 ROM page %v", j))
|
for _, bank := range romBanksBytes {
|
||||||
|
romData = append(romData, bank...)
|
||||||
}
|
}
|
||||||
|
rom := newMemoryRangePagedROM(0xd000, romData, "Base64 ROM", base64aRomBankCount)
|
||||||
|
|
||||||
// Start with first bank active
|
// Start with first bank active
|
||||||
a.mmu.setActiveROMPage(0)
|
rom.setPage(0)
|
||||||
|
a.mmu.physicalROM = rom
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,23 +55,31 @@ func addBase64aSoftSwitches(io *ioC0Page) {
|
|||||||
// ROM pagination softswitches. They use the annunciator 0 and 1
|
// ROM pagination softswitches. They use the annunciator 0 and 1
|
||||||
mmu := io.apple2.mmu
|
mmu := io.apple2.mmu
|
||||||
io.addSoftSwitchRW(0x58, func() uint8 {
|
io.addSoftSwitchRW(0x58, func() uint8 {
|
||||||
p := mmu.getActiveROMPage()
|
if rom, ok := mmu.physicalROM.(*memoryRangeROM); ok {
|
||||||
mmu.setActiveROMPage(p & 2)
|
p := rom.getPage()
|
||||||
|
rom.setPage(p & 2)
|
||||||
|
}
|
||||||
return 0
|
return 0
|
||||||
}, "ANN0OFF-ROM")
|
}, "ANN0OFF-ROM")
|
||||||
io.addSoftSwitchRW(0x59, func() uint8 {
|
io.addSoftSwitchRW(0x59, func() uint8 {
|
||||||
p := mmu.getActiveROMPage()
|
if rom, ok := mmu.physicalROM.(*memoryRangeROM); ok {
|
||||||
mmu.setActiveROMPage(p | 1)
|
p := rom.getPage()
|
||||||
|
rom.setPage(p | 1)
|
||||||
|
}
|
||||||
return 0
|
return 0
|
||||||
}, "ANN0ON-ROM")
|
}, "ANN0ON-ROM")
|
||||||
io.addSoftSwitchRW(0x5A, func() uint8 {
|
io.addSoftSwitchRW(0x5A, func() uint8 {
|
||||||
p := mmu.getActiveROMPage()
|
if rom, ok := mmu.physicalROM.(*memoryRangeROM); ok {
|
||||||
mmu.setActiveROMPage(p & 1)
|
p := rom.getPage()
|
||||||
|
rom.setPage(p & 1)
|
||||||
|
}
|
||||||
return 0
|
return 0
|
||||||
}, "ANN1OFF-ROM")
|
}, "ANN1OFF-ROM")
|
||||||
io.addSoftSwitchRW(0x5B, func() uint8 {
|
io.addSoftSwitchRW(0x5B, func() uint8 {
|
||||||
p := mmu.getActiveROMPage()
|
if rom, ok := mmu.physicalROM.(*memoryRangeROM); ok {
|
||||||
mmu.setActiveROMPage(p | 2)
|
p := rom.getPage()
|
||||||
|
rom.setPage(p | 2)
|
||||||
|
}
|
||||||
return 0
|
return 0
|
||||||
}, "ANN1ON-ROM")
|
}, "ANN1ON-ROM")
|
||||||
|
|
||||||
|
@ -31,9 +31,7 @@ func newCardThunderClockPlusBuilder() *cardBuilder {
|
|||||||
return &cardBuilder{
|
return &cardBuilder{
|
||||||
name: "ThunderClock+ Card",
|
name: "ThunderClock+ Card",
|
||||||
description: "Clock card",
|
description: "Clock card",
|
||||||
defaultParams: &[]paramSpec{
|
defaultParams: &[]paramSpec{},
|
||||||
{"rom", "ROM file to load", "<internal>/ThunderclockPlusROM.bin"},
|
|
||||||
},
|
|
||||||
buildFunc: func(params map[string]string) (Card, error) {
|
buildFunc: func(params map[string]string) (Card, error) {
|
||||||
var c CardThunderClockPlus
|
var c CardThunderClockPlus
|
||||||
err := c.loadRomFromResource("<internal>/ThunderclockPlusROM.bin")
|
err := c.loadRomFromResource("<internal>/ThunderclockPlusROM.bin")
|
||||||
|
@ -16,7 +16,7 @@ type memoryManager struct {
|
|||||||
cardsROMExtra [8]memoryHandler // 0xc800 to 0xcfff. 2048 bytes for each card
|
cardsROMExtra [8]memoryHandler // 0xc800 to 0xcfff. 2048 bytes for each card
|
||||||
|
|
||||||
// Upper area ROM: 0xc000 to 0xffff (or 0xd000 to 0xffff on the II+)
|
// Upper area ROM: 0xc000 to 0xffff (or 0xd000 to 0xffff on the II+)
|
||||||
physicalROM [4]memoryHandler // 0xc000 (or 0xd000) to 0xffff, 16 (or 12) Kb. Up to four banks
|
physicalROM memoryHandler // 0xc000 (or 0xd000) to 0xffff, 16 (or 12) Kb. Up to four banks
|
||||||
|
|
||||||
// Language card upper area RAM: 0xd000 to 0xffff. One bank for regular LC cards, up to 8 with Saturn
|
// Language card upper area RAM: 0xd000 to 0xffff. One bank for regular LC cards, up to 8 with Saturn
|
||||||
physicalLangRAM []*memoryRange // 0xd000 to 0xffff, 12KB. Up to 8 banks.
|
physicalLangRAM []*memoryRange // 0xd000 to 0xffff, 12KB. Up to 8 banks.
|
||||||
@ -44,9 +44,6 @@ type memoryManager struct {
|
|||||||
extendedRAMBlock uint8 // Block used for entended memory for RAMWorks cards
|
extendedRAMBlock uint8 // Block used for entended memory for RAMWorks cards
|
||||||
mainROMinhibited memoryHandler // Alternative ROM from 0xd000 to 0xffff provided by a card with the INH signal.
|
mainROMinhibited memoryHandler // Alternative ROM from 0xd000 to 0xffff provided by a card with the INH signal.
|
||||||
|
|
||||||
// Configuration switches, Base64A
|
|
||||||
romPage uint8 // Active ROM page
|
|
||||||
|
|
||||||
// Resolution cache
|
// Resolution cache
|
||||||
lastAddressPage uint16 // The first byte is the page. The second is zero when the cached is valid.
|
lastAddressPage uint16 // The first byte is the page. The second is zero when the cached is valid.
|
||||||
lastAddressHandler memoryHandler
|
lastAddressHandler memoryHandler
|
||||||
@ -90,12 +87,12 @@ func (mmu *memoryManager) accessCArea(address uint16) memoryHandler {
|
|||||||
// Internal IIe slot 3
|
// Internal IIe slot 3
|
||||||
if (address <= addressLimitSlots) && !mmu.slotC3ROMActive && (slot == 3) {
|
if (address <= addressLimitSlots) && !mmu.slotC3ROMActive && (slot == 3) {
|
||||||
mmu.intC8ROMActive = true
|
mmu.intC8ROMActive = true
|
||||||
return mmu.physicalROM[mmu.romPage]
|
return mmu.physicalROM
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal IIe CxROM
|
// Internal IIe CxROM
|
||||||
if mmu.intCxROMActive {
|
if mmu.intCxROMActive {
|
||||||
return mmu.physicalROM[mmu.romPage]
|
return mmu.physicalROM
|
||||||
}
|
}
|
||||||
|
|
||||||
// First slot area
|
// First slot area
|
||||||
@ -114,7 +111,7 @@ func (mmu *memoryManager) accessCArea(address uint16) memoryHandler {
|
|||||||
|
|
||||||
// Extra slot area
|
// Extra slot area
|
||||||
if mmu.intC8ROMActive {
|
if mmu.intC8ROMActive {
|
||||||
return mmu.physicalROM[mmu.romPage]
|
return mmu.physicalROM
|
||||||
}
|
}
|
||||||
return mmu.cardsROMExtra[mmu.activeSlot]
|
return mmu.cardsROMExtra[mmu.activeSlot]
|
||||||
}
|
}
|
||||||
@ -188,7 +185,7 @@ func (mmu *memoryManager) accessRead(address uint16) memoryHandler {
|
|||||||
if mmu.lcActiveRead {
|
if mmu.lcActiveRead {
|
||||||
return mmu.accessUpperRAMArea(address)
|
return mmu.accessUpperRAMArea(address)
|
||||||
}
|
}
|
||||||
return mmu.physicalROM[mmu.romPage]
|
return mmu.physicalROM
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mmu *memoryManager) accessWrite(address uint16) memoryHandler {
|
func (mmu *memoryManager) accessWrite(address uint16) memoryHandler {
|
||||||
@ -221,7 +218,7 @@ func (mmu *memoryManager) accessWrite(address uint16) memoryHandler {
|
|||||||
if mmu.lcActiveWrite {
|
if mmu.lcActiveWrite {
|
||||||
return mmu.accessUpperRAMArea(address)
|
return mmu.accessUpperRAMArea(address)
|
||||||
}
|
}
|
||||||
return mmu.physicalROM[mmu.romPage]
|
return mmu.physicalROM
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mmu *memoryManager) peekWord(address uint16) uint16 {
|
func (mmu *memoryManager) peekWord(address uint16) uint16 {
|
||||||
@ -318,14 +315,6 @@ func (mmu *memoryManager) initExtendedRAM(groups int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Memory configuration
|
// 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) {
|
func (mmu *memoryManager) setLanguageRAM(readActive bool, writeActive bool, altBank bool) {
|
||||||
mmu.lcActiveRead = readActive
|
mmu.lcActiveRead = readActive
|
||||||
mmu.lcActiveWrite = writeActive
|
mmu.lcActiveWrite = writeActive
|
||||||
|
@ -12,6 +12,8 @@ type memoryRange struct {
|
|||||||
|
|
||||||
type memoryRangeROM struct {
|
type memoryRangeROM struct {
|
||||||
memoryRange
|
memoryRange
|
||||||
|
pageOffset uint16
|
||||||
|
pages uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMemoryRange(base uint16, data []uint8, name string) *memoryRange {
|
func newMemoryRange(base uint16, data []uint8, name string) *memoryRange {
|
||||||
@ -25,10 +27,15 @@ func newMemoryRange(base uint16, data []uint8, name string) *memoryRange {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newMemoryRangeROM(base uint16, data []uint8, name string) *memoryRangeROM {
|
func newMemoryRangeROM(base uint16, data []uint8, name string) *memoryRangeROM {
|
||||||
|
return newMemoryRangePagedROM(base, data, name, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newMemoryRangePagedROM(base uint16, data []uint8, name string, pages uint8) *memoryRangeROM {
|
||||||
var m memoryRangeROM
|
var m memoryRangeROM
|
||||||
m.base = base
|
m.base = base
|
||||||
m.data = data
|
m.data = data
|
||||||
m.name = name
|
m.name = name
|
||||||
|
m.pages = pages
|
||||||
return &m
|
return &m
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,10 +55,27 @@ func (m *memoryRange) subRange(a, b uint16) []uint8 {
|
|||||||
return m.data[a-m.base : b-m.base]
|
return m.data[a-m.base : b-m.base]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *memoryRangeROM) setPage(page uint8) {
|
||||||
|
pageSize := len(m.data) / int(m.pages)
|
||||||
|
m.pageOffset = uint16(int(page%m.pages) * pageSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *memoryRangeROM) getPage() uint8 {
|
||||||
|
pageSize := len(m.data) / int(m.pages)
|
||||||
|
return uint8(m.pageOffset / uint16(pageSize))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *memoryRangeROM) peek(address uint16) uint8 {
|
||||||
|
return m.data[address-m.base+m.pageOffset]
|
||||||
|
}
|
||||||
func (m *memoryRangeROM) poke(address uint16, value uint8) {
|
func (m *memoryRangeROM) poke(address uint16, value uint8) {
|
||||||
// Ignore
|
// Ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *memoryRangeROM) subRange(a, b uint16) []uint8 {
|
||||||
|
return m.data[a-m.base+m.pageOffset : b-m.base+m.pageOffset]
|
||||||
|
}
|
||||||
|
|
||||||
//lint:ignore U1000 this is used to write debug code
|
//lint:ignore U1000 this is used to write debug code
|
||||||
func identifyMemory(m memoryHandler) string {
|
func identifyMemory(m memoryHandler) string {
|
||||||
ram, ok := m.(*memoryRange)
|
ram, ok := m.(*memoryRange)
|
||||||
|
@ -204,8 +204,8 @@ func (nsc *noSlotClockDS1216) loadTime() {
|
|||||||
|
|
||||||
func setupNoSlotClock(a *Apple2, arg string) error {
|
func setupNoSlotClock(a *Apple2, arg string) error {
|
||||||
if arg == "main" {
|
if arg == "main" {
|
||||||
nsc := newNoSlotClockDS1216(a, a.mmu.physicalROM[0])
|
nsc := newNoSlotClockDS1216(a, a.mmu.physicalROM)
|
||||||
a.mmu.physicalROM[0] = nsc
|
a.mmu.physicalROM = nsc
|
||||||
} else {
|
} else {
|
||||||
slot, err := strconv.ParseUint(arg, 10, 8)
|
slot, err := strconv.ParseUint(arg, 10, 8)
|
||||||
if err != nil || slot < 1 || slot > 7 {
|
if err != nil || slot < 1 || slot > 7 {
|
||||||
|
2
setup.go
2
setup.go
@ -150,7 +150,7 @@ func (a *Apple2) loadRom(filename string) error {
|
|||||||
size := len(data)
|
size := len(data)
|
||||||
|
|
||||||
romBase := 0x10000 - size
|
romBase := 0x10000 - size
|
||||||
a.mmu.physicalROM[0] = newMemoryRangeROM(uint16(romBase), data, "Main ROM")
|
a.mmu.physicalROM = newMemoryRangeROM(uint16(romBase), data, "Main ROM")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user