Experiments with prodos device drivers

This commit is contained in:
Ivan Izaguirre 2020-11-20 16:19:06 +01:00
parent c9bb9f2208
commit bce5c4b92e
2 changed files with 214 additions and 127 deletions

View File

@ -229,4 +229,8 @@ func (a *Apple2) dumpDebugInfo() {
d := a.mmu.physicalMainRAM.data[k]
fmt.Printf(" %v(0x%x): 0x%02x\n", pageZeroSymbols[k], k, d)
}
if a.traceMLI != nil {
a.traceMLI.dumpDevices()
}
}

View File

@ -8,21 +8,28 @@ type traceProDOS struct {
functionCode uint8
paramsAdddress uint16
returnAddress uint16
deviceDrivers []uint16
}
const (
mliAddress uint16 = 0xbf00
biAddress uint16 = 0xbe03
deviceCountAddress uint16 = 0xbf31 // DEVCNT
deviceListAddress uint16 = 0xbf32
deviceDriverVectors uint16 = 0xbf10 // DEVADR01
deviceDateTimeVector uint16 = 0xbf07 // DATETIME+1
)
func newTraceProDOS(a *Apple2) *traceProDOS {
var t traceProDOS
t.a = a
t.deviceDrivers = make([]uint16, 0)
return &t
}
func (t *traceProDOS) inspect() {
pc, ps := t.a.cpu.GetPCAndSP()
pc, _ := t.a.cpu.GetPCAndSP()
if pc == mliAddress {
/*
MLI has been called (provided we are running proDOS and the proper page)
@ -39,6 +46,24 @@ func (t *traceProDOS) inspect() {
fmt.Print("<there was a call pending>\n")
}
}
t.dumpMLICall()
t.refreshDeviceDrives()
t.callPending = true
//t.a.cpu.SetTrace(true)
} else if t.callPending && pc == t.returnAddress {
t.dumpMLIReturn()
t.callPending = false
//t.a.cpu.SetTrace(false)
} else if pc == biAddress {
t.dumpBIExec()
} else if /*t.callPending &&*/ t.isDriverAddress(pc) {
fmt.Printf(" <<< Calling a driver in $%04x >>> ", pc)
}
}
func (t *traceProDOS) dumpMLICall() {
_, ps := t.a.cpu.GetPCAndSP()
caller := uint16(t.a.mmu.Peek(0x100+uint16(ps+1))) +
uint16(t.a.mmu.Peek(0x100+uint16(ps+2)))<<8 - 2
t.functionCode = t.a.mmu.Peek(caller + 3)
@ -98,9 +123,9 @@ func (t *traceProDOS) inspect() {
fmt.Printf(" GET_BUF(ref=%v)", t.paramByte(1))
}
fmt.Printf(" => ")
}
t.callPending = true
} else if t.callPending && pc == t.returnAddress {
func (t *traceProDOS) dumpMLIReturn() {
error, acc := t.a.cpu.GetCarryAndAcc()
if error {
fmt.Printf("error $%02x: %v\n", acc, getMliErrorText(acc))
@ -158,8 +183,9 @@ func (t *traceProDOS) inspect() {
fmt.Printf("Ok\n")
}
}
t.callPending = false
} else if pc == biAddress {
}
func (t *traceProDOS) dumpBIExec() {
s := ""
for i := uint16(1); i < 256; i++ {
ch := t.a.mmu.Peek(0x200 + i)
@ -170,6 +196,63 @@ func (t *traceProDOS) inspect() {
}
fmt.Printf("Prodos BI exec: \"%s\".\n", s)
}
func (t *traceProDOS) dumpDevices() {
// Active disk devices
// See https://prodos8.com/docs/techref/writing-a-prodos-system-program/#page94
// See https://prodos8.com/docs/technote/21/
mem := t.a.mmu.getPhysicalMainRAM(false)
count := mem.peek(deviceCountAddress) + 1
fmt.Printf("Prodos disk devices: \n")
for i := uint8(0); i < count; i++ {
value := mem.peek(deviceListAddress + uint16(i))
id := "unknown"
switch value & 0xf {
case 0x0:
id = "DiskII"
case 0x4:
id = "ProFile" // Used also be the Memory Expansion Ram disk
case 0xf:
id = "RAM"
}
fmt.Printf((" S%vD%v %s($%02x)\n"), (value>>4)&7, (value>>7)+1, id, value)
}
// Device drivers
fmt.Printf("ProDOS device drivers:\n")
for slot := uint16(0); slot <= 7; slot++ {
for drive := uint16(0); drive < 2; drive++ {
address := deviceDriverVectors + (slot+drive*8)*2
value := uint16(mem.peek(address)) + 0x100*uint16(mem.peek(address+1))
fmt.Printf(" S%vD%v: $%04x\n", slot, drive+1, value)
}
}
}
func (t *traceProDOS) refreshDeviceDrives() {
mem := t.a.mmu.getPhysicalMainRAM(false)
drivers := make([]uint16, 0, 14)
for i := uint16(0); i < 16; i++ {
address := deviceDriverVectors + i*2
value := uint16(mem.peek(address)) + 0x100*uint16(mem.peek(address+1))
drivers = append(drivers, value)
}
// Datetime
value := uint16(mem.peek(deviceDateTimeVector)) + 0x100*uint16(mem.peek(deviceDateTimeVector+1))
drivers = append(drivers, value)
t.deviceDrivers = drivers
}
func (t *traceProDOS) isDriverAddress(pc uint16) bool {
for _, vector := range t.deviceDrivers {
if vector == pc {
return true
}
}
return false
}
func (t *traceProDOS) paramByte(pos uint16) uint8 {