From 94c6ecd97dc835fb55708d1ea8080e9ced557a77 Mon Sep 17 00:00:00 2001 From: Will Angenent Date: Tue, 15 May 2018 11:12:38 +0100 Subject: [PATCH] Added some comments to the audio samples calculation --- appleiie.go | 3 ++- audio/audio.go | 13 +++++++--- bell_test.go | 63 ++++++++++++++++++++++++++++++++++++++++++++++ cpu/cpu.go | 12 ++++++--- cpu/cpu_test.go | 2 +- dos33_boot_test.go | 3 ++- 6 files changed, 85 insertions(+), 11 deletions(-) create mode 100644 bell_test.go diff --git a/appleiie.go b/appleiie.go index 2ce847b..a767e3d 100644 --- a/appleiie.go +++ b/appleiie.go @@ -53,7 +53,8 @@ func update(screen *ebiten.Image) error { system.FrameCycles = 0 system.LastAudioCycles = 0 - cpu.Run(*showInstructions, breakAddress, *disableFirmwareWait, system.CpuFrequency/60) + exitAtBreak := true + cpu.Run(*showInstructions, breakAddress, exitAtBreak, *disableFirmwareWait, system.CpuFrequency/60) audio.ForwardToFrameCycle() system.Cycles += system.FrameCycles system.FrameCycles = 0 diff --git a/audio/audio.go b/audio/audio.go index fa1c480..29d2d8e 100644 --- a/audio/audio.go +++ b/audio/audio.go @@ -20,11 +20,16 @@ func attenuate(sample int16) int16 { } func ForwardToFrameCycle() { - ratio := float64(system.AudioSampleRate) / system.CpuFrequency + // 1023000/44100=23.19 cycles per audio sample + cyclesPerAudioSample := system.CpuFrequency / float64(system.AudioSampleRate) - samples := uint64(ratio * float64(system.FrameCycles-system.LastAudioCycles)) - var i uint64 - for i = 0; i < samples; i++ { + // Should be about 1023000/60=17050 + elapsedCycles := system.FrameCycles - system.LastAudioCycles + + // Should be about 17050/23.19=735 audio samples per frame + audioSamples := uint64(float64(elapsedCycles) / cyclesPerAudioSample) + + for i := uint64(0); i < audioSamples; i++ { b := attenuate(system.LastAudioValue) system.AudioChannel <- b } diff --git a/bell_test.go b/bell_test.go new file mode 100644 index 0000000..f806480 --- /dev/null +++ b/bell_test.go @@ -0,0 +1,63 @@ +package main + +import ( + "fmt" + "mos6502go/cpu" + "mos6502go/keyboard" + "mos6502go/mmu" + "mos6502go/system" + "mos6502go/video" + "testing" +) + +func testBellCycles(delay int) { + cpu.State.PC = 0x800 + mmu.WriteMemory(0x800, 0xa9) // LDA #$xx + mmu.WriteMemory(0x801, uint8(delay)) + mmu.WriteMemory(0x802, 0x20) // JSR $fca8 + mmu.WriteMemory(0x803, 0xa8) + mmu.WriteMemory(0x804, 0xfc) + mmu.WriteMemory(0x805, 0x00) // Break address + + system.FrameCycles = 0 + showInstructions := false + breakAddress := uint16(0x805) + exitAtBreak := false + disableFirmwareWait := false + cpu.Run(showInstructions, &breakAddress, exitAtBreak, disableFirmwareWait, 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 + + gotCycles := int(system.FrameCycles - 2) + fmt.Printf("Delay %3d ", delay) + if gotCycles == expectedCycles { + fmt.Println("OK") + + } else { + fmt.Printf("Failed expected %6d, got %6d\n", expectedCycles, gotCycles) + } +} + +func TestBell(t *testing.T) { + cpu.InitInstructionDecoder() + mmu.InitRAM() + mmu.InitApple2eROM() + mmu.InitIO() + cpu.Init() + keyboard.Init() + video.Init() + system.Init() + + testBellCycles(1) + testBellCycles(2) + testBellCycles(3) + testBellCycles(4) + testBellCycles(12) + testBellCycles(0x10) + testBellCycles(0x20) + testBellCycles(0x40) + testBellCycles(0x80) + testBellCycles(0xc0) + testBellCycles(0xff) +} diff --git a/cpu/cpu.go b/cpu/cpu.go index 2e72dcb..ba68dbf 100644 --- a/cpu/cpu.go +++ b/cpu/cpu.go @@ -530,7 +530,7 @@ func nmi() { system.FrameCycles += 7 } -func Run(showInstructions bool, breakAddress *uint16, disableFirmwareWait bool, wantedCycles uint64) { +func Run(showInstructions bool, breakAddress *uint16, exitAtBreak bool, disableFirmwareWait bool, wantedCycles uint64) { system.FrameCycles = 0 for { @@ -568,9 +568,13 @@ func Run(showInstructions bool, breakAddress *uint16, disableFirmwareWait bool, addressMode := OpCodes[opcode].AddressingMode.Mode if breakAddress != nil && State.PC == *breakAddress { - fmt.Printf("Break at $%04x\n", *breakAddress) - PrintInstruction(true) - os.Exit(0) + if exitAtBreak { + fmt.Printf("Break at $%04x\n", *breakAddress) + PrintInstruction(true) + os.Exit(0) + } else { + return + } } switch opcode { diff --git a/cpu/cpu_test.go b/cpu/cpu_test.go index 1d6a454..f0f67cc 100644 --- a/cpu/cpu_test.go +++ b/cpu/cpu_test.go @@ -73,7 +73,7 @@ func TestCPU(t *testing.T) { keyboard.Init() - cpu.Run(*showInstructions, breakAddress, false, 0) + cpu.Run(*showInstructions, breakAddress, true, false, 0) fmt.Printf("Finished running %s\n\n", rom) } } diff --git a/dos33_boot_test.go b/dos33_boot_test.go index b52106c..a4294d7 100644 --- a/dos33_boot_test.go +++ b/dos33_boot_test.go @@ -29,9 +29,10 @@ func TestDOS33Boot(t *testing.T) { system.LastAudioCycles = 0 showInstructions := false var breakAddress uint16 + exitAtBreak := true disableFirmwareWait := false t0 := time.Now() - cpu.Run(showInstructions, &breakAddress, disableFirmwareWait, system.CpuFrequency*1000) + cpu.Run(showInstructions, &breakAddress, exitAtBreak, disableFirmwareWait, system.CpuFrequency*1000) elapsed := float64(time.Since(t0) / time.Millisecond) fmt.Printf("CPU Cycles: %d\n", system.FrameCycles)