mirror of
https://github.com/ivanizag/izapple2.git
synced 2024-09-10 03:54:30 +00:00
Experimental RomX
This commit is contained in:
parent
17edb28d38
commit
3e5e10b8dd
@ -50,7 +50,14 @@ func (a *Apple2) Run() {
|
||||
// Run a 6502 step
|
||||
if !a.paused {
|
||||
for i := 0; i < cpuSpinLoops; i++ {
|
||||
// Conditional tracing
|
||||
//pc, _ := a.cpu.GetPCAndSP()
|
||||
//a.cpu.SetTrace(pc >= 0x300 && pc <= 0x400)
|
||||
|
||||
// Execution
|
||||
a.cpu.ExecuteInstruction()
|
||||
|
||||
// Special tracing
|
||||
a.executionTrace()
|
||||
}
|
||||
} else {
|
||||
|
@ -171,6 +171,12 @@ func (a *Apple2) AddNoSlotClock() {
|
||||
a.mmu.physicalROM[0] = nsc
|
||||
}
|
||||
|
||||
// AddRomX inserts a RomX. It intercepts all memory accesses
|
||||
func (a *Apple2) AddRomX() {
|
||||
rx := newRomX(a, a.mmu)
|
||||
a.cpu.SetMemory(rx)
|
||||
}
|
||||
|
||||
// AddNoSlotClockInCard inserts a DS1215 no slot clock under a card ROM
|
||||
func (a *Apple2) AddNoSlotClockInCard(slot int) error {
|
||||
cardRom := a.mmu.cardsROM[slot]
|
||||
|
@ -288,6 +288,7 @@ func MainApple() *Apple2 {
|
||||
|
||||
}
|
||||
|
||||
// a.AddRomX()
|
||||
// a.AddCardInOut(2)
|
||||
// a.AddCardLogger(4)
|
||||
|
||||
|
@ -103,6 +103,11 @@ func (s *State) GetTrace() bool {
|
||||
return s.trace
|
||||
}
|
||||
|
||||
// SetMemory changes the memory provider
|
||||
func (s *State) SetMemory(mem Memory) {
|
||||
s.mem = mem
|
||||
}
|
||||
|
||||
// GetPCAndSP returns the current program counter and stack pointer. Used to trace MLI calls
|
||||
func (s *State) GetPCAndSP() (uint16, uint8) {
|
||||
return s.reg.getPC(), s.reg.getSP()
|
||||
|
@ -55,7 +55,7 @@ func fyneRun(s *state) {
|
||||
toolbar := buildToolbar(s)
|
||||
display := canvas.NewImageFromImage(nil)
|
||||
display.ScaleMode = canvas.ImageScalePixels // Looks worst but loads less.
|
||||
display.SetMinSize(fyne.NewSize(280*2, 192*2))
|
||||
display.SetMinSize(fyne.NewSize(280*2*2, 192*2*2))
|
||||
|
||||
container := fyne.NewContainerWithLayout(
|
||||
layout.NewBorderLayout(nil, toolbar, nil, s.devices.w),
|
||||
|
@ -135,7 +135,6 @@ func (nsc *noSlotClockDS1216) peek(address uint16) uint8 {
|
||||
}
|
||||
|
||||
func (nsc *noSlotClockDS1216) poke(address uint16, value uint8) {
|
||||
// This should not happen as we are dealing with ROM
|
||||
nsc.memory.poke(address, value)
|
||||
}
|
||||
|
||||
|
127
romX.go
Normal file
127
romX.go
Normal file
@ -0,0 +1,127 @@
|
||||
package izapple2
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ivanizag/izapple2/core6502"
|
||||
)
|
||||
|
||||
/*
|
||||
RomX from https://theromexchange.com/
|
||||
This complement uses the RomX API spec to switch main ROM and character generator ROM
|
||||
|
||||
See:
|
||||
https://theromexchange.com/documentation/ROM%20X%20API%20Reference.pdf
|
||||
https://theromexchange.com/downloads/ROM%20X%2020-10-22.zip
|
||||
|
||||
It is not enough to intercept the ROM accesses. RomX intercept the 74LS138 in
|
||||
position F12, that has access to the full 0xc000-0xf000 on the Apple II+
|
||||
*/
|
||||
|
||||
type romX struct {
|
||||
a *Apple2
|
||||
memory core6502.Memory
|
||||
activationStep int
|
||||
systemBank uint8
|
||||
textBank uint8
|
||||
}
|
||||
|
||||
var romXActivationSequence = []uint16{0xcaca, 0xcaca, 0xcafe}
|
||||
|
||||
const (
|
||||
setupBank = uint8(0)
|
||||
romXSetSystemBankBaseAddress = uint16(0xcef0)
|
||||
romXSetTextBankBaseAddress = uint16(0xcfd0)
|
||||
romXDefaultSystemBankAddress = uint16(0xd034)
|
||||
romXDefaultTextBankAddress = uint16(0xd02e)
|
||||
|
||||
// Unknown
|
||||
romXFirmwareMark0Address = uint16(0xdffe)
|
||||
romXFirmwareMark0Value = uint8(0x4a)
|
||||
romXFirmwareMark1Address = uint16(0xdfff)
|
||||
romXFirmwareMark1Value = uint8(0xcd)
|
||||
)
|
||||
|
||||
func newRomX(a *Apple2, memory core6502.Memory) *romX {
|
||||
var rx romX
|
||||
rx.a = a
|
||||
rx.memory = memory
|
||||
rx.systemBank = 0
|
||||
rx.textBank = 0
|
||||
return &rx
|
||||
}
|
||||
|
||||
func (rx *romX) Peek(address uint16) uint8 {
|
||||
intercepted, value := rx.interceptAccess(address)
|
||||
if intercepted {
|
||||
return value
|
||||
}
|
||||
return rx.memory.Peek(address)
|
||||
}
|
||||
|
||||
func (rx *romX) PeekCode(address uint16) uint8 {
|
||||
//intercepted, value := rx.interceptAccess(address)
|
||||
//if intercepted {
|
||||
// return value
|
||||
//}
|
||||
return rx.memory.PeekCode(address)
|
||||
}
|
||||
|
||||
func (rx *romX) Poke(address uint16, value uint8) {
|
||||
rx.interceptAccess(address)
|
||||
rx.memory.Poke(address, value)
|
||||
}
|
||||
|
||||
func (rx *romX) interceptAccess(address uint16) (bool, uint8) {
|
||||
// Intercept only $C080 to $FFFF as seen by the F12 chip
|
||||
if address < 0xc080 {
|
||||
return false, 0
|
||||
}
|
||||
|
||||
// Setup mode when the setup bank is active
|
||||
if rx.systemBank == setupBank {
|
||||
switch address {
|
||||
case romXDefaultSystemBankAddress:
|
||||
fmt.Printf("[romX]Peek in $%04x, current system bank %v\n", address, rx.systemBank)
|
||||
return true, 0xe0 + rx.systemBank
|
||||
case romXDefaultTextBankAddress:
|
||||
fmt.Printf("[romX]PeeK in $%04x, current text bank %v\n", address, rx.textBank)
|
||||
return true, 0xd0 + rx.textBank
|
||||
case romXFirmwareMark0Address:
|
||||
fmt.Printf("[romX]Peek in $%04x, ???\n", address)
|
||||
return true, romXFirmwareMark0Value
|
||||
case romXFirmwareMark1Address:
|
||||
fmt.Printf("[romX]Peek in $%04x, ???\n", address)
|
||||
return true, romXFirmwareMark1Value
|
||||
}
|
||||
|
||||
if address&0xfff0 == romXSetSystemBankBaseAddress {
|
||||
rx.systemBank = uint8(address & 0xf)
|
||||
fmt.Printf("[romX]System bank set to %v\n", rx.systemBank)
|
||||
} else if address&0xfff0 == romXSetTextBankBaseAddress {
|
||||
rx.textBank = uint8(address & 0xf)
|
||||
fmt.Printf("[romX]Text bank set to %v\n", rx.textBank)
|
||||
} else if address < 0xe000 {
|
||||
fmt.Printf("[romX]Peek in $%04x\n", address)
|
||||
}
|
||||
|
||||
return false, 0
|
||||
}
|
||||
|
||||
// Activation sequence detection
|
||||
if address == romXActivationSequence[rx.activationStep] {
|
||||
rx.activationStep++
|
||||
//fmt.Printf("[romX]Activation step %v\n", rx.activationStep)
|
||||
if rx.activationStep == len(romXActivationSequence) {
|
||||
// Activation sequence completed
|
||||
rx.systemBank = setupBank
|
||||
rx.activationStep = 0
|
||||
// rx.a.cpu.SetTrace(true)
|
||||
fmt.Printf("[romX]System bank set to 0, %v\n", rx.systemBank)
|
||||
}
|
||||
} else {
|
||||
rx.activationStep = 0
|
||||
}
|
||||
|
||||
return false, 0
|
||||
}
|
Loading…
Reference in New Issue
Block a user