Added the -traceCpu and -traceSS command line switches.

This commit is contained in:
Ivan Izaguirre 2019-09-24 23:32:03 +02:00
parent 43a5980fd3
commit 68b949d871
9 changed files with 84 additions and 38 deletions

View File

@ -99,29 +99,34 @@ Only valid on SDL mode
-base64a -base64a
setup a Base64A clone setup a Base64A clone
-charRom string -charRom string
rom file for the character generator (default "<internal>/Apple2rev7CharGen.rom") rom file for the character generator (default "<internal>/Apple2rev7CharGen.rom")
-disk string -disk string
file to load on the first disk drive (default "<internal>/dos33.dsk") file to load on the first disk drive (default "<internal>/dos33.dsk")
-disk2Slot int -disk2Slot int
slot for the disk driver. -1 for none. (default 6) slot for the disk driver. -1 for none. (default 6)
-diskRom string -diskRom string
rom file for the disk drive controller (default "<internal>/DISK2.rom") rom file for the disk drive controller (default "<internal>/DISK2.rom")
-dumpChars -dumpChars
shows the character map shows the character map
-fastDisk -fastDisk
set fast mode when the disks are spinning (default true) set fast mode when the disks are spinning (default true)
-languageCardSlot int -languageCardSlot int
slot for the 16kb language card. -1 for none slot for the 16kb language card. -1 for none
-mhz float -mhz float
cpu speed in Mhz, use 0 for full speed. Use F5 to toggle. (default 1.0227142857142857) cpu speed in Mhz, use 0 for full speed. Use F5 to toggle. (default 1.0227142857142857)
-mono -mono
emulate a green phosphor monitor instead of a NTSC color TV. Use F6 to toggle. emulate a green phosphor monitor instead of a NTSC color TV. Use F6 to toggle.
-panicss -panicss
panic if a not implemented softswitch is used panic if a not implemented softswitch is used
-rom string -rom string
main rom file (default "<internal>/Apple2_Plus.rom") main rom file (default "<internal>/Apple2_Plus.rom")
-saturnCardSlot int -saturnCardSlot int
slot for the 256kb Saturn card. -1 for none (default -1) slot for the 256kb Saturn card. -1 for none (default -1)
-traceCpu
dump to the console the CPU execution
-traceSS
dump to the console the sofswitches calls
``` ```
## Building from source ## Building from source

View File

@ -20,7 +20,6 @@ type Apple2 struct {
cg *CharacterGenerator cg *CharacterGenerator
cards [8]card cards [8]card
isApple2e bool isApple2e bool
panicSS bool
commandChannel chan int commandChannel chan int
cycleDurationNs float64 // Current speed. Inverse of the cpu clock in Ghz cycleDurationNs float64 // Current speed. Inverse of the cpu clock in Ghz
isColor bool isColor bool
@ -37,14 +36,14 @@ const (
const maxWaitDuration = 100 * time.Millisecond const maxWaitDuration = 100 * time.Millisecond
// Run starts the Apple2 emulation // Run starts the Apple2 emulation
func (a *Apple2) Run(log bool) { func (a *Apple2) Run() {
// Start the processor // Start the processor
a.cpu.Reset() a.cpu.Reset()
referenceTime := time.Now() referenceTime := time.Now()
for { for {
// Run a 6502 step // Run a 6502 step
a.cpu.ExecuteInstruction(log && a.cycleDurationNs != 0) a.cpu.ExecuteInstruction()
// Execute meta commands // Execute meta commands
commandsPending := true commandsPending := true

View File

@ -4,7 +4,7 @@ import "github.com/ivanizag/apple2/core6502"
// NewApple2 instantiates an apple2 // NewApple2 instantiates an apple2
func NewApple2(charRomFile string, clockMhz float64, func NewApple2(charRomFile string, clockMhz float64,
isColor bool, fastMode bool, panicSS bool) *Apple2 { isColor bool, fastMode bool) *Apple2 {
var a Apple2 var a Apple2
a.Name = "Apple ][+" a.Name = "Apple ][+"
@ -16,7 +16,6 @@ func NewApple2(charRomFile string, clockMhz float64,
a.commandChannel = make(chan int, 100) a.commandChannel = make(chan int, 100)
a.isColor = isColor a.isColor = isColor
a.fastMode = fastMode a.fastMode = fastMode
a.panicSS = panicSS
if clockMhz <= 0 { if clockMhz <= 0 {
// Full speed // Full speed

View File

@ -16,7 +16,7 @@ func main() {
a.SetKeyboardProvider(fe) a.SetKeyboardProvider(fe)
go fe.textModeGoRoutine(a) go fe.textModeGoRoutine(a)
a.Run(false) a.Run()
} }
/* /*

View File

@ -53,7 +53,18 @@ func MainApple() *Apple2 {
panicSS := flag.Bool( panicSS := flag.Bool(
"panicss", "panicss",
false, false,
"panic if a not implemented softswitch is used") "panic if a not implemented softswitch is used",
)
traceCPU := flag.Bool(
"traceCpu",
false,
"dump to the console the CPU execution operations",
)
traceSS := flag.Bool(
"traceSS",
false,
"dump to the console the sofswitches calls",
)
dumpChars := flag.Bool( dumpChars := flag.Bool(
"dumpChars", "dumpChars",
false, false,
@ -66,7 +77,12 @@ func MainApple() *Apple2 {
) )
flag.Parse() flag.Parse()
a := NewApple2(*charRomFile, *cpuClock, !*mono, *fastDisk, *panicSS) a := NewApple2(*charRomFile, *cpuClock, !*mono, *fastDisk)
a.cpu.SetTrace(*traceCPU)
a.io.setTrace(*traceSS)
a.io.setPanicNotImplemented(*panicSS)
if *base64a { if *base64a {
NewBase64a(a) NewBase64a(a)
} else { } else {

View File

@ -22,8 +22,9 @@ func TestFunctional(t *testing.T) {
if log { if log {
fmt.Printf("[ %d ] ", testCase) fmt.Printf("[ %d ] ", testCase)
} }
s.SetTrace(log)
pc := s.reg.getPC() pc := s.reg.getPC()
s.ExecuteInstruction(log) s.ExecuteInstruction()
if pc == s.reg.getPC() { if pc == s.reg.getPC() {
t.Errorf("Failure in test %v.", testCase) t.Errorf("Failure in test %v.", testCase)
} }

View File

@ -17,6 +17,7 @@ type State struct {
mem Memory mem Memory
cycles uint64 cycles uint64
opcodes *[256]opcode opcodes *[256]opcode
trace bool
} }
const ( const (
@ -43,8 +44,13 @@ func (s *State) executeLine(line []uint8) {
opcode.action(s, line, opcode) opcode.action(s, line, opcode)
} }
// SetTrace activates tracing of the cpu execution
func (s *State) SetTrace(trace bool) {
s.trace = trace
}
// ExecuteInstruction transforms the state given after a single instruction is executed. // ExecuteInstruction transforms the state given after a single instruction is executed.
func (s *State) ExecuteInstruction(log bool) { func (s *State) ExecuteInstruction() {
pc := s.reg.getPC() pc := s.reg.getPC()
opcodeID := s.mem.Peek(pc) opcodeID := s.mem.Peek(pc)
opcode := s.opcodes[opcodeID] opcode := s.opcodes[opcodeID]
@ -60,12 +66,13 @@ func (s *State) ExecuteInstruction(log bool) {
} }
s.reg.setPC(pc) s.reg.setPC(pc)
if log { if s.trace {
//fmt.Printf("%#04x %#02x\n", pc-opcode.bytes, opcodeID)
fmt.Printf("%#04x %-12s: ", pc-opcode.bytes, lineString(line, opcode)) fmt.Printf("%#04x %-12s: ", pc-opcode.bytes, lineString(line, opcode))
} }
opcode.action(s, line, opcode) opcode.action(s, line, opcode)
s.cycles += uint64(opcode.cycles) s.cycles += uint64(opcode.cycles)
if log { if s.trace {
fmt.Printf("%v, [%02x]\n", s.reg, line) fmt.Printf("%v, [%02x]\n", s.reg, line)
} }
} }

View File

@ -181,4 +181,9 @@ var opcodesNMOS6502 = [256]opcode{
0x70: opcode{"BVS", 2, 2, modeRelative, buildOpBranch(flagV, true)}, // Extra cycles 0x70: opcode{"BVS", 2, 2, modeRelative, buildOpBranch(flagV, true)}, // Extra cycles
0xEA: opcode{"NOP", 1, 2, modeImplicit, opNOP}, 0xEA: opcode{"NOP", 1, 2, modeImplicit, opNOP},
// Undocumented opcodes, see http://bbc.nvg.org/doc/6502OpList.txt
0x1A: opcode{"NOP", 1, 2, modeImplicit, opNOP}, // INC A in the 65c02
0xC2: opcode{"NOP", 1, 2, modeImplicit, opNOP}, // Should be HALT?
0x02: opcode{"NOP", 1, 2, modeImplicit, opNOP}, // Should be HALT?
} }

View File

@ -7,14 +7,16 @@ import (
) )
type ioC0Page struct { type ioC0Page struct {
softSwitchesR [256]softSwitchR softSwitchesR [256]softSwitchR
softSwitchesW [256]softSwitchW softSwitchesW [256]softSwitchW
softSwitchesData [128]uint8 softSwitchesData [128]uint8
keyboard KeyboardProvider keyboard KeyboardProvider
speaker SpeakerProvider speaker SpeakerProvider
paddlesStrobeCycle uint64 paddlesStrobeCycle uint64
joysticks JoysticksProvider joysticks JoysticksProvider
apple2 *Apple2 apple2 *Apple2
trace bool
panicNotImplemented bool
} }
type softSwitchR func(io *ioC0Page) uint8 type softSwitchR func(io *ioC0Page) uint8
@ -57,6 +59,14 @@ func newIoC0Page(a *Apple2) *ioC0Page {
return &io return &io
} }
func (p *ioC0Page) setTrace(trace bool) {
p.trace = trace
}
func (p *ioC0Page) setPanicNotImplemented(value bool) {
p.panicNotImplemented = value
}
func (p *ioC0Page) save(w io.Writer) { func (p *ioC0Page) save(w io.Writer) {
binary.Write(w, binary.BigEndian, p.softSwitchesData) binary.Write(w, binary.BigEndian, p.softSwitchesData)
} }
@ -106,23 +116,27 @@ func (p *ioC0Page) peek(address uint16) uint8 {
pageAddress := uint8(address) pageAddress := uint8(address)
ss := p.softSwitchesR[pageAddress] ss := p.softSwitchesR[pageAddress]
if ss == nil { if ss == nil {
if p.apple2.panicSS { if p.panicNotImplemented {
panic(fmt.Sprintf("Unknown softswitch on read to 0xC0%02x", pageAddress)) panic(fmt.Sprintf("Unknown softswitch on read to $%04x", address))
} }
return 0 return 0
} }
value := ss(p) value := ss(p)
//fmt.Printf("Peek on $%02x: $%02x\n", address, value) if p.trace {
fmt.Printf("Softswitch peek on $%04x: $%02x\n", address, value)
}
return value return value
} }
func (p *ioC0Page) poke(address uint16, value uint8) { func (p *ioC0Page) poke(address uint16, value uint8) {
//fmt.Printf("Poke on $%02x with %02x\n", address, value) if p.trace {
fmt.Printf("Softswtich poke on $%04x with %02x\n", address, value)
}
pageAddress := uint8(address) pageAddress := uint8(address)
ss := p.softSwitchesW[pageAddress] ss := p.softSwitchesW[pageAddress]
if ss == nil { if ss == nil {
if p.apple2.panicSS { if p.panicNotImplemented {
panic(fmt.Sprintf("Unknown softswitch on write to 0xC0%02x", pageAddress)) panic(fmt.Sprintf("Unknown softswitch on write to $%04x", address))
} }
return return
} }