diff --git a/apple2.go b/apple2.go index db9771b..920b396 100644 --- a/apple2.go +++ b/apple2.go @@ -23,6 +23,7 @@ import ( var ( showInstructions *bool // Display all instructions as they are executed disableFirmwareWait *bool // Disable the WAIT function at $fca8 + disableDosDelay *bool // Disable DOS delay functions breakAddress *uint16 // Break address from the command line resetKeysDown bool // Keep track of ctrl-alt-R key down state @@ -65,7 +66,7 @@ func update(screen *ebiten.Image) error { exitAtBreak := true // Die if a BRK instruction is seen // Run for 1/60 of a second, the duration of an ebiten frame - cpu.Run(*showInstructions, breakAddress, exitAtBreak, *disableFirmwareWait, system.CPUFrequency/60) + cpu.Run(*showInstructions, breakAddress, exitAtBreak, *disableFirmwareWait, *disableDosDelay, system.CPUFrequency/60) // Process any audio speaker clicks from this frame audio.ForwardToFrameCycle() @@ -88,6 +89,7 @@ func main() { showInstructions = flag.Bool("show-instructions", false, "Show instructions code while running") disableFirmwareWait = flag.Bool("disable-wait", false, "Ignore JSRs to firmware wait at $FCA8") + disableDosDelay = flag.Bool("disable-dos-delay", false, "Ignore DOS ARM move and motor on waits") breakAddressString := flag.String("break", "", "Break on address") mute := flag.Bool("mute", false, "Mute sound") clickWhenDriveHeadMoves := flag.Bool("drive-head-click", false, "Click speaker when drive head moves") diff --git a/bell_test.go b/bell_test.go index 265d3b1..e14e9a3 100644 --- a/bell_test.go +++ b/bell_test.go @@ -23,8 +23,9 @@ func testBellCycles(delay int) { breakAddress := uint16(0x805) exitAtBreak := false disableFirmwareWait := false + disableDosDelay := false cpu.State.PC = 0x800 - cpu.Run(showInstructions, &breakAddress, exitAtBreak, disableFirmwareWait, system.CPUFrequency*1000) + cpu.Run(showInstructions, &breakAddress, exitAtBreak, disableFirmwareWait, disableDosDelay, system.CPUFrequency*1000) // See http://apple2.org.za/gswv/a2zine/GS.WorldView/Resources/USEFUL.TABLES/WAIT.DELAY.CR.txt expectedCycles := (26 + 27*delay + 5*delay*delay) / 2 diff --git a/cpu/cpu.go b/cpu/cpu.go index 6f9e665..ce7e064 100644 --- a/cpu/cpu.go +++ b/cpu/cpu.go @@ -551,7 +551,7 @@ func nmi() { // Run runs the CPU until either wantedCycles has been reached (if non-zero) or the program counter reaches breakAddress. // system.FrameCycles is the amount of cycles executed so far. -func Run(showInstructions bool, breakAddress *uint16, exitAtBreak bool, disableFirmwareWait bool, wantedCycles uint64) { +func Run(showInstructions bool, breakAddress *uint16, exitAtBreak bool, disableFirmwareWait bool, disableDosDelay bool, wantedCycles uint64) { system.FrameCycles = 0 for { @@ -632,6 +632,10 @@ func Run(showInstructions bool, breakAddress *uint16, exitAtBreak bool, disableF State.PC += 3 State.A = 0 continue + } else if disableDosDelay && value == 0xba00 { + // Don't call the delay, just move forward and pretend it happened. + State.PC += 3 + continue } push16(State.PC + 2) @@ -647,6 +651,15 @@ func Run(showInstructions bool, breakAddress *uint16, exitAtBreak bool, disableF case 0xa2, 0xa6, 0xb6, 0xae, 0xbe: // LDX State.X = load(addressMode) case 0xa0, 0xa4, 0xb4, 0xac, 0xbc: // LDY + if disableDosDelay { + pc := uint16(mmu.ReadMemory(State.PC+1)) + uint16(mmu.ReadMemory(State.PC+2))<<8 + if pc == 0xbd9e { + // Don't do delay, just move forward and pretend it happened. + State.PC += 13 + continue + } + } + State.Y = load(addressMode) case 0x85, 0x95, 0x8d, 0x9d, 0x99, 0x81, 0x91: //STA diff --git a/cpu/cpu_test.go b/cpu/cpu_test.go index 1735b31..de4e86e 100644 --- a/cpu/cpu_test.go +++ b/cpu/cpu_test.go @@ -76,7 +76,7 @@ func TestCPU(t *testing.T) { mmu.WritePageTable[0xc0+i] = RomPretendingToBeRAM[i*0x100 : i*0x100+0x100] } - cpu.Run(*showInstructions, breakAddress, true, false, 0) + cpu.Run(*showInstructions, breakAddress, true, false, false, 0) fmt.Printf("Finished running %s\n\n", rom) } } diff --git a/utils/utils.go b/utils/utils.go index e50e1c1..2b072e3 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -60,7 +60,8 @@ func RunUntilBreakPoint(t *testing.T, breakAddress uint16, seconds int, showInst system.LastAudioCycles = 0 exitAtBreak := false disableFirmwareWait := false - cpu.Run(showInstructions, &breakAddress, exitAtBreak, disableFirmwareWait, uint64(system.CPUFrequency*seconds)) + disableDosDelay := false + cpu.Run(showInstructions, &breakAddress, exitAtBreak, disableFirmwareWait, disableDosDelay, uint64(system.CPUFrequency*seconds)) if cpu.State.PC != breakAddress { t.Fatalf("Did not reach breakpoint at %04x. Got to %04x", breakAddress, cpu.State.PC) }