Trace calls to the BBC MOS when using Applecorn
This commit is contained in:
parent
c1a8bf7ee4
commit
620d496807
|
@ -60,6 +60,7 @@ Portable emulator of an Apple II+ or //e. Written in Go.
|
||||||
- ProDOS MLI calls
|
- ProDOS MLI calls
|
||||||
- Apple Pascal BIOS calls
|
- Apple Pascal BIOS calls
|
||||||
- Smartport commands
|
- Smartport commands
|
||||||
|
- BBC MOS calls when using [Applecorn](https://github.com/bobbimanners/)
|
||||||
- Other features:
|
- Other features:
|
||||||
- Sound
|
- Sound
|
||||||
- Joystick support. Up to two joysticks or four paddles
|
- Joystick support. Up to two joysticks or four paddles
|
||||||
|
@ -227,6 +228,10 @@ Only valid on SDL mode
|
||||||
use the sequencer based Disk II card
|
use the sequencer based Disk II card
|
||||||
-thunderClockCardSlot int
|
-thunderClockCardSlot int
|
||||||
slot for the ThunderClock Plus card. -1 for none (default 4)
|
slot for the ThunderClock Plus card. -1 for none (default 4)
|
||||||
|
-traceBBC
|
||||||
|
trace BBC MOS API calls used with Applecorn, skip console I/O calls
|
||||||
|
-traceBBCFull
|
||||||
|
trace BBC MOS API calls used with Applecorn
|
||||||
-traceCpu
|
-traceCpu
|
||||||
dump to the console the CPU execution. Use F11 to toggle.
|
dump to the console the CPU execution. Use F11 to toggle.
|
||||||
-traceHD
|
-traceHD
|
||||||
|
|
|
@ -142,6 +142,14 @@ func MainApple() *Apple2 {
|
||||||
"sequencer",
|
"sequencer",
|
||||||
false,
|
false,
|
||||||
"use the sequencer based Disk II card")
|
"use the sequencer based Disk II card")
|
||||||
|
traceBBC := flag.Bool(
|
||||||
|
"traceBBC",
|
||||||
|
false,
|
||||||
|
"trace BBC MOS API calls used with Applecorn, skip console I/O calls")
|
||||||
|
traceBBCFull := flag.Bool(
|
||||||
|
"traceBBCFull",
|
||||||
|
false,
|
||||||
|
"trace BBC MOS API calls used with Applecorn")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
@ -170,6 +178,12 @@ func MainApple() *Apple2 {
|
||||||
if *tracePascal {
|
if *tracePascal {
|
||||||
a.addTracer(newTracePascal(a))
|
a.addTracer(newTracePascal(a))
|
||||||
}
|
}
|
||||||
|
if *traceBBC {
|
||||||
|
a.addTracer(newTraceApplecorn(a, false))
|
||||||
|
}
|
||||||
|
if *traceBBCFull {
|
||||||
|
a.addTracer(newTraceApplecorn(a, true))
|
||||||
|
}
|
||||||
|
|
||||||
var charGenMap charColumnMap
|
var charGenMap charColumnMap
|
||||||
initialCharGenPage := 0
|
initialCharGenPage := 0
|
||||||
|
|
|
@ -127,11 +127,16 @@ func (s *State) GetPCAndSP() (uint16, uint8) {
|
||||||
return s.reg.getPC(), s.reg.getSP()
|
return s.reg.getPC(), s.reg.getSP()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCarryAndAcc returns the value of te carry flag and the accumulator. Used to trace MLI calls
|
// GetCarryAndAcc returns the value of the carry flag and the accumulator. Used to trace MLI calls
|
||||||
func (s *State) GetCarryAndAcc() (bool, uint8) {
|
func (s *State) GetCarryAndAcc() (bool, uint8) {
|
||||||
return s.reg.getFlag(flagC), s.reg.getA()
|
return s.reg.getFlag(flagC), s.reg.getA()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAXY returns the value of the A, X and Y registers
|
||||||
|
func (s *State) GetAXY() (uint8, uint8, uint8) {
|
||||||
|
return s.reg.getA(), s.reg.getX(), s.reg.getY()
|
||||||
|
}
|
||||||
|
|
||||||
// Save saves the CPU state (registers and cycle counter)
|
// Save saves the CPU state (registers and cycle counter)
|
||||||
func (s *State) Save(w io.Writer) error {
|
func (s *State) Save(w io.Writer) error {
|
||||||
err := binary.Write(w, binary.BigEndian, s.cycles)
|
err := binary.Write(w, binary.BigEndian, s.cycles)
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
package izapple2
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
/*
|
||||||
|
See:
|
||||||
|
https://github.com/bobbimanners/Applecorn
|
||||||
|
http://beebwiki.mdfs.net/Category:MOS_API
|
||||||
|
http://beebwiki.mdfs.net/OSBYTEs
|
||||||
|
http://mdfs.net/Docs/Comp/BBC/Osbyte00
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
type traceApplecorn struct {
|
||||||
|
a *Apple2
|
||||||
|
skipConsole bool
|
||||||
|
osbyteNames [256]string
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
applecornMosVec uint16 = 0xffb9 // Start of the MOS entry points
|
||||||
|
)
|
||||||
|
|
||||||
|
func newTraceApplecorn(a *Apple2, skipConsole bool) *traceApplecorn {
|
||||||
|
var t traceApplecorn
|
||||||
|
t.a = a
|
||||||
|
t.skipConsole = skipConsole
|
||||||
|
t.osbyteNames[0x7c] = "clear escape condition"
|
||||||
|
t.osbyteNames[0x7d] = "set escape condition"
|
||||||
|
t.osbyteNames[0x7e] = "ack detection of ESC"
|
||||||
|
t.osbyteNames[0x81] = "Read key with time lim"
|
||||||
|
t.osbyteNames[0x82] = "read high order address"
|
||||||
|
t.osbyteNames[0x83] = "read bottom of user mem"
|
||||||
|
t.osbyteNames[0x84] = "read top of user mem"
|
||||||
|
t.osbyteNames[0x85] = "top user mem for mode"
|
||||||
|
t.osbyteNames[0x86] = "read cursor pos"
|
||||||
|
t.osbyteNames[0xDA] = "clear VDU queue"
|
||||||
|
|
||||||
|
return &t
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *traceApplecorn) inspect() {
|
||||||
|
pc, _ := t.a.cpu.GetPCAndSP()
|
||||||
|
if pc >= applecornMosVec {
|
||||||
|
regA, regX, regY := t.a.cpu.GetAXY()
|
||||||
|
s := ""
|
||||||
|
|
||||||
|
if !t.skipConsole {
|
||||||
|
switch pc {
|
||||||
|
case 0xffe0:
|
||||||
|
s = fmt.Sprintf("OSNEWL()")
|
||||||
|
case 0xffc8:
|
||||||
|
ch := ""
|
||||||
|
if regA >= 0x20 && regA < 0x7f {
|
||||||
|
ch = string(regA)
|
||||||
|
}
|
||||||
|
s = fmt.Sprintf("OSNWRCH(A=%02x, '%v')", regA, ch)
|
||||||
|
case 0xffcb:
|
||||||
|
s = fmt.Sprintf("OSNRDCH()")
|
||||||
|
case 0xffe7:
|
||||||
|
s = fmt.Sprintf("OSRDCH()")
|
||||||
|
case 0xffee:
|
||||||
|
ch := ""
|
||||||
|
if regA >= 0x20 && regA < 0x7f {
|
||||||
|
ch = string(regA)
|
||||||
|
}
|
||||||
|
s = fmt.Sprintf("OSWRCH(A=%02x, '%v')", regA, ch)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
switch pc {
|
||||||
|
case 0xffb9:
|
||||||
|
s = "OSDRM(?)"
|
||||||
|
case 0xffbf:
|
||||||
|
s = "OSEVEN(?)"
|
||||||
|
case 0xffc2:
|
||||||
|
s = "OSINIT(?)"
|
||||||
|
case 0xffc5:
|
||||||
|
s = "OSREAD(?)"
|
||||||
|
case 0xffce:
|
||||||
|
s = "OSFIND(?)"
|
||||||
|
case 0xffd1:
|
||||||
|
s = "OSGBPB(?)"
|
||||||
|
case 0xffd4:
|
||||||
|
s = "OSBPUT(?)"
|
||||||
|
case 0xffd7:
|
||||||
|
s = "OSBGET(?)"
|
||||||
|
case 0xffda:
|
||||||
|
s = "OSARGS(?)"
|
||||||
|
case 0xffdd:
|
||||||
|
s = "OSFILE(?)"
|
||||||
|
case 0xffe3:
|
||||||
|
s = "OSASCI(?)"
|
||||||
|
case 0xfff1:
|
||||||
|
s = fmt.Sprintf("OSWORD(A=%02x,XY=%04x)", regA, uint16(regX)<<8+uint16(regY))
|
||||||
|
case 0xfff4:
|
||||||
|
s = fmt.Sprintf("OSBYTE('%s';A=%02x,X=%02x,Y=%02x)", t.osbyteNames[regA], regA, regX, regY)
|
||||||
|
case 0xfff7:
|
||||||
|
s = "OSCLI(?)"
|
||||||
|
}
|
||||||
|
|
||||||
|
if s != "" {
|
||||||
|
fmt.Printf("BBC MOS call to $%04x %s\n", pc, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue