diff --git a/bank_switch_test.go b/bank_switch_test.go index 9a9d2d4..29a19ff 100644 --- a/bank_switch_test.go +++ b/bank_switch_test.go @@ -11,6 +11,15 @@ import ( "github.com/stretchr/testify/assert" ) +func assertMemoryConfiguration(t *testing.T, address uint16, upperRamReadOnly bool, upperReadMappedToROM bool, d000Bank int) { + mmu.WriteMemory(address, 0x00) + assert.Equal(t, upperReadMappedToROM, mmu.UpperReadMappedToROM) + assert.Equal(t, d000Bank, mmu.D000Bank) +} + +// TestBankSwitching tests the area starting at $d000 and managed by $c08x. +// First the initial settings are checked. Then a bunch of assertions on the +// internal code. Then writes to $c08x. func TestBankSwitching(t *testing.T) { cpu.InitInstructionDecoder() mmu.InitRAM() @@ -79,17 +88,7 @@ func TestBankSwitching(t *testing.T) { assert.Equal(t, uint8(0x6f), mmu.ReadMemory(0xd000)) // read from ROM assert.Equal(t, uint8(0xc3), mmu.ReadMemory(0xffff)) // read from ROM - testSwitches(t) -} - -func assertMemoryConfiguration(t *testing.T, address uint16, upperRamReadOnly bool, upperReadMappedToROM bool, d000Bank int) { - mmu.WriteMemory(address, 0x00) - // assert.Equal(t, upperRamReadOnly, mmu.UpperRamReadOnly) - assert.Equal(t, upperReadMappedToROM, mmu.UpperReadMappedToROM) - assert.Equal(t, d000Bank, mmu.D000Bank) -} - -func testSwitches(t *testing.T) { + // Test writes to 0xc08x lead to correct memory configurations assertMemoryConfiguration(t, 0xc080, true, false, 2) assertMemoryConfiguration(t, 0xc081, false, true, 2) assertMemoryConfiguration(t, 0xc082, true, true, 2) diff --git a/bell_test.go b/bell_test.go index 1fbf9d6..08fb104 100644 --- a/bell_test.go +++ b/bell_test.go @@ -5,32 +5,33 @@ import ( "testing" "github.com/freewilll/apple2/cpu" - "github.com/freewilll/apple2/keyboard" "github.com/freewilll/apple2/mmu" "github.com/freewilll/apple2/system" - "github.com/freewilll/apple2/video" ) 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 + // Add some code to $800 + mmu.WriteMemory(0x800, 0xa9) // LDA #delay + mmu.WriteMemory(0x801, uint8(delay)) // + mmu.WriteMemory(0x802, 0x20) // JSR $fca8 BELL + mmu.WriteMemory(0x803, 0xa8) // + mmu.WriteMemory(0x804, 0xfc) // + mmu.WriteMemory(0x805, 0x00) // BRK + // Run the code until the BRK instruction and count the cycles system.FrameCycles = 0 showInstructions := false breakAddress := uint16(0x805) exitAtBreak := false disableFirmwareWait := false + cpu.State.PC = 0x800 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) + gotCycles := int(system.FrameCycles - 2) // Exclude the cycles taken by the LDA + fmt.Printf("Delay %3d ", delay) if gotCycles == expectedCycles { fmt.Println("OK") @@ -40,14 +41,15 @@ func testBellCycles(delay int) { } } +// TestBell tests the nunber of cycles in the system BELL loop for different +// values of the accumulator. This test was mainly used to diagnose a bug +// related to sound frequencies being incorrect due to invalid cycle +// housekeeping in the CPU branch code. func TestBell(t *testing.T) { cpu.InitInstructionDecoder() mmu.InitRAM() mmu.InitApple2eROM() - mmu.InitIO() cpu.Init() - keyboard.Init() - video.Init() system.Init() testBellCycles(1) diff --git a/cmd/disasm.go b/cmd/disasm.go index 10fcd55..e3eb477 100644 --- a/cmd/disasm.go +++ b/cmd/disasm.go @@ -1,7 +1,11 @@ package main +// Command line tool to disassemble a range of addresses + import ( "flag" + "fmt" + "os" "github.com/freewilll/apple2/cpu" "github.com/freewilll/apple2/mmu" @@ -9,6 +13,14 @@ import ( ) func main() { + var Usage = func() { + fmt.Fprintf(flag.CommandLine.Output(), "Usage of %s:\n\n", os.Args[0]) + fmt.Fprintf(flag.CommandLine.Output(), "Synopsis:\n %s -start ADDRESS [-end ADDRESS]\n\n", os.Args[0]) + fmt.Fprintf(flag.CommandLine.Output(), "Example:\n %s -start d000 -end ffff\n\n", os.Args[0]) + flag.PrintDefaults() + } + flag.Usage = Usage + startString := flag.String("start", "", "Start address") endString := flag.String("end", "", "End address") flag.Parse() diff --git a/dos33_boot_test.go b/dos33_boot_test.go index a76afd2..56db44d 100644 --- a/dos33_boot_test.go +++ b/dos33_boot_test.go @@ -16,14 +16,8 @@ import ( const dosDiskImage = "dos33.dsk" -func runDos33Boot(t *testing.T) { - // Boot up DOS3.3 - utils.RunUntilBreakPoint(t, 0x0801, 2, false, "Boot0") - utils.RunUntilBreakPoint(t, 0xb700, 1, false, "Boot1") // $3700 is for master disk, $b700 for a slave disk - utils.RunUntilBreakPoint(t, 0x9d84, 3, false, "Boot2") - utils.RunUntilBreakPoint(t, 0xd7d2, 2, false, "JMP to basic interpreter NEWSTT") -} - +// TestDOS33Boot goes through the boot process and asserts that the code ends +// up in the BASIC interpreter after DOS has loaded. func TestDOS33Boot(t *testing.T) { cpu.InitInstructionDecoder() mmu.InitRAM() @@ -39,7 +33,11 @@ func TestDOS33Boot(t *testing.T) { t0 := time.Now() - runDos33Boot(t) + // Boot up DOS3.3 + utils.RunUntilBreakPoint(t, 0x0801, 2, false, "Boot0") + utils.RunUntilBreakPoint(t, 0xb700, 1, false, "Boot1") // $3700 is for master disk, $b700 for a slave disk + utils.RunUntilBreakPoint(t, 0x9d84, 3, false, "Boot2") + utils.RunUntilBreakPoint(t, 0xd7d2, 2, false, "JMP to basic interpreter NEWSTT") elapsed := float64(time.Since(t0) / time.Millisecond) fmt.Printf("CPU Cycles: %d\n", system.FrameCycles) diff --git a/io_test.go b/io_test.go index 3518305..3712967 100644 --- a/io_test.go +++ b/io_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" ) +// TestIoBankSwitching tests the switching of the IO memory ROM at $c000-$c7ff func TestIoBankSwitching(t *testing.T) { cpu.InitInstructionDecoder() mmu.InitRAM() diff --git a/prodos_boot_test.go b/prodos_boot_test.go index bd018e6..752ea77 100644 --- a/prodos_boot_test.go +++ b/prodos_boot_test.go @@ -16,7 +16,9 @@ import ( const prodosDiskImage = "prodos19.dsk" -func TestProdosBoot(t *testing.T) { +// TestProdos19Boot goes through the boot process and asserts that the code ends +// up in the BASIC interpreter after Prodos has loaded. +func TestProdos19Boot(t *testing.T) { cpu.InitInstructionDecoder() mmu.InitRAM() mmu.InitApple2eROM() @@ -40,7 +42,7 @@ func TestProdosBoot(t *testing.T) { utils.RunUntilBreakPoint(t, 0xd000, 1, false, "First call to MLI kernel") utils.RunUntilBreakPoint(t, 0x0800, 2, false, "BI loader") utils.RunUntilBreakPoint(t, 0x2000, 2, false, "BI Relocator") - utils.RunUntilBreakPoint(t, 0xbe00, 52, false, "BI Start") + utils.RunUntilBreakPoint(t, 0xbe00, 1, false, "BI Start") elapsed := float64(time.Since(t0) / time.Millisecond) fmt.Printf("CPU Cycles: %d\n", system.FrameCycles) diff --git a/rwts_write_test.go b/rwts_write_test.go index 071bca2..dafa291 100644 --- a/rwts_write_test.go +++ b/rwts_write_test.go @@ -14,12 +14,16 @@ import ( const rwtsDosDiskImage = "dos33.dsk" +// Write a number of bytes to an address func writeBytes(address int, data []uint8) { for i := 0; i < len(data); i++ { mmu.WriteMemory(uint16(address)+uint16(i), data[i]) } } +// TestDos33RwtsWriteRead goes through the boot process and then calls RWTS +// with a write and read request. Then the result of the read is cheked to make +// sure it maches the write. This tests the disk image IO code. func TestDos33RwtsWriteRead(t *testing.T) { // Test writing and reading a sector using DOS 3.3's RWTS cpu.InitInstructionDecoder() @@ -75,6 +79,7 @@ func TestDos33RwtsWriteRead(t *testing.T) { writeBytes(start+0x2e, []uint8{0x20, 0xd9, 0x03}) // JSR $03D9 RWTS writeBytes(start+0x31, []uint8{0x00}) // BRK + // Run until the RWTS write returns cpu.State.PC = uint16(start) utils.RunUntilBreakPoint(t, 0xb944, 128, false, "RWTS RDADDR") utils.RunUntilBreakPoint(t, 0xb82a, 8, false, "RWTS WRITESEC") @@ -92,6 +97,7 @@ func TestDos33RwtsWriteRead(t *testing.T) { writeBytes(start+0x1b, []uint8{0xa0, 0x09}) // LDY #$09 writeBytes(start+0x1d, []uint8{0x91, 0x00}) // STA ($00),Y + // Run until the RWTS read returns cpu.State.PC = uint16(start) utils.RunUntilBreakPoint(t, uint16(start+0x31), 1, false, "Read routine break")