From 0c615fc96ca14650686f37237c07e2f4b85e91d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Izaguirre?= Date: Thu, 25 Jan 2024 22:20:22 +0100 Subject: [PATCH] Some traces for CP/M 65, test for CP/M 65 boot and some other changes --- a2audit_test.go | 4 +- apple2Run.go | 2 +- apple2Tester.go | 46 +++++++++++++++++- cardCat_test.go | 4 +- cardSwyft_test.go | 5 +- e2e_boot_test.go | 27 +++++++---- memoryRange.go | 4 -- resources/cpm65.po | Bin 0 -> 143360 bytes traceBuilder.go | 5 ++ traceCpm65.go | 116 +++++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 188 insertions(+), 25 deletions(-) create mode 100644 resources/cpm65.po create mode 100644 traceCpm65.go diff --git a/a2audit_test.go b/a2audit_test.go index 67d9070..7229ad4 100644 --- a/a2audit_test.go +++ b/a2audit_test.go @@ -22,9 +22,7 @@ func testA2AuditInternal(t *testing.T, model string, removeLangCard bool, cycles if err != nil { t.Fatal(err) } - at.terminateCondition = func(a *Apple2) bool { - return a.cpu.GetCycles() > cycles - } + at.terminateCondition = buildTerminateConditionTexts(at, messages, false, cycles) at.run() text := at.getText() diff --git a/apple2Run.go b/apple2Run.go index b36d641..e3399db 100644 --- a/apple2Run.go +++ b/apple2Run.go @@ -37,7 +37,7 @@ func (a *Apple2) Start(paused bool) { for i := 0; i < cpuSpinLoops; i++ { // Conditional tracing //pc, _ := a.cpu.GetPCAndSP() - //a.cpu.SetTrace((pc >= 0xc500 && pc < 0xc600) || (pc >= 0xc700 && pc < 0xc800)) + //a.cpu.SetTrace(pc >= 0x7f0 && pc < 0x0820) // Execution a.cpu.ExecuteInstruction() diff --git a/apple2Tester.go b/apple2Tester.go index f8b4251..ecb0c8a 100644 --- a/apple2Tester.go +++ b/apple2Tester.go @@ -1,12 +1,16 @@ package izapple2 import ( + "strings" + "github.com/ivanizag/izapple2/screen" ) +type terminateConditionFunc func(a *Apple2) bool + type apple2Tester struct { a *Apple2 - terminateCondition func(a *Apple2) bool + terminateCondition terminateConditionFunc } func makeApple2Tester(model string, overrides *configuration) (*apple2Tester, error) { @@ -46,3 +50,43 @@ func (at *apple2Tester) getText() string { func (at *apple2Tester) getText80() string { return screen.RenderTextModeString(at.a, true, false, false, at.a.isApple2e) } + +func buildTerminateConditionCycles(cycles uint64) terminateConditionFunc { + return func(a *Apple2) bool { + return a.cpu.GetCycles() > cycles + } +} + +const textCheckInterval = uint64(100_000) + +func buildTerminateConditionText(at *apple2Tester, needle string, col80 bool, timeoutCycles uint64) terminateConditionFunc { + needles := []string{needle} + return buildTerminateConditionTexts(at, needles, col80, timeoutCycles) +} + +func buildTerminateConditionTexts(at *apple2Tester, needles []string, col80 bool, timeoutCycles uint64) terminateConditionFunc { + lastCheck := uint64(0) + found := false + return func(a *Apple2) bool { + cycles := a.cpu.GetCycles() + if cycles > timeoutCycles { + return true + } + if cycles-lastCheck > textCheckInterval { + lastCheck = cycles + var text string + if col80 { + text = at.getText80() + } else { + text = at.getText() + } + for _, needle := range needles { + if !strings.Contains(text, needle) { + return false + } + } + found = true + } + return found + } +} diff --git a/cardCat_test.go b/cardCat_test.go index 84bd3e4..44add60 100644 --- a/cardCat_test.go +++ b/cardCat_test.go @@ -19,9 +19,7 @@ func testCardDetectedInternal(t *testing.T, model string, card string, cycles ui if err != nil { t.Fatal(err) } - at.terminateCondition = func(a *Apple2) bool { - return a.cpu.GetCycles() > cycles - } + at.terminateCondition = buildTerminateConditionText(at, banner, true, cycles) at.run() text := at.getText80() diff --git a/cardSwyft_test.go b/cardSwyft_test.go index e8a37e0..d7898c7 100644 --- a/cardSwyft_test.go +++ b/cardSwyft_test.go @@ -11,9 +11,8 @@ func TestSwyftTutorial(t *testing.T) { t.Fatal(err) } - at.terminateCondition = func(a *Apple2) bool { - return a.cpu.GetCycles() > 10_000_000 - } + at.terminateCondition = buildTerminateConditionText(at, "HOW TO USE SWYFTCARD", true, 10_000_000) + at.run() text := at.getText80() diff --git a/e2e_boot_test.go b/e2e_boot_test.go index aa536bc..eec1c79 100644 --- a/e2e_boot_test.go +++ b/e2e_boot_test.go @@ -5,7 +5,7 @@ import ( "testing" ) -func testBoots(t *testing.T, model string, disk string, cycles uint64, banner string, prompt string) { +func testBoots(t *testing.T, model string, disk string, cycles uint64, banner string, prompt string, col80 bool) { overrides := newConfiguration() if disk != "" { overrides.set(confS6, "diskii,disk1=\""+disk+"\"") @@ -17,12 +17,15 @@ func testBoots(t *testing.T, model string, disk string, cycles uint64, banner st if err != nil { t.Fatal(err) } - at.terminateCondition = func(a *Apple2) bool { - return a.cpu.GetCycles() > cycles - } + at.terminateCondition = buildTerminateConditionTexts(at, []string{banner, prompt}, col80, cycles) at.run() - text := at.getText() + var text string + if col80 { + text = at.getText80() + } else { + text = at.getText() + } if !strings.Contains(text, banner) { t.Errorf("Expected '%s', got '%s'", banner, text) } @@ -33,21 +36,25 @@ func testBoots(t *testing.T, model string, disk string, cycles uint64, banner st } func TestPlusBoots(t *testing.T) { - testBoots(t, "2plus", "", 200_000, "APPLE ][", "\n]") + testBoots(t, "2plus", "", 200_000, "APPLE ][", "\n]", false) } func Test2EBoots(t *testing.T) { - testBoots(t, "2e", "", 200_000, "Apple ][", "\n]") + testBoots(t, "2e", "", 200_000, "Apple ][", "\n]", false) } func Test2EnhancedBoots(t *testing.T) { - testBoots(t, "2enh", "", 200_000, "Apple //e", "\n]") + testBoots(t, "2enh", "", 200_000, "Apple //e", "\n]", false) } func TestBase64Boots(t *testing.T) { - testBoots(t, "base64a", "", 1_000_000, "BASE 64A", "\n]") + testBoots(t, "base64a", "", 1_000_000, "BASE 64A", "\n]", false) } func TestPlusDOS33Boots(t *testing.T) { - testBoots(t, "2plus", "/dos33.dsk", 100_000_000, "DOS VERSION 3.3", "\n]") + testBoots(t, "2plus", "/dos33.dsk", 100_000_000, "DOS VERSION 3.3", "\n]", false) +} + +func TestCPM65Boots(t *testing.T) { + testBoots(t, "2enh", "/cpm65.po", 5_000_000, "CP/M-65 for the Apple II", "\nA>", true) } diff --git a/memoryRange.go b/memoryRange.go index 3467747..af5a721 100644 --- a/memoryRange.go +++ b/memoryRange.go @@ -72,10 +72,6 @@ func (m *memoryRangeROM) poke(address uint16, value uint8) { // Ignore } -func (m *memoryRangeROM) subRange(a, b uint16) []uint8 { - return m.data[a-m.base+m.pageOffset : b-m.base+m.pageOffset] -} - //lint:ignore U1000 this is used to write debug code func identifyMemory(m memoryHandler) string { ram, ok := m.(*memoryRange) diff --git a/resources/cpm65.po b/resources/cpm65.po new file mode 100644 index 0000000000000000000000000000000000000000..b6913d234957ac252011ce675c5d51af363aed65 GIT binary patch literal 143360 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 literal 0 HcmV?d00001 diff --git a/traceBuilder.go b/traceBuilder.go index 7996b8b..8ec16b9 100644 --- a/traceBuilder.go +++ b/traceBuilder.go @@ -62,6 +62,11 @@ func buildTracerFactory() map[string]*traceBuilder { description: "Panic on unimplemented softswitches", connectFunc: func(a *Apple2) { a.io.setPanicNotImplemented(true) }, } + tracerFactory["cpm65"] = &traceBuilder{ + name: "cpm65", + description: "Trace CPM65 BDOS calls", + executionTracer: newTraceCpm65(false), + } return tracerFactory } diff --git a/traceCpm65.go b/traceCpm65.go new file mode 100644 index 0000000..597aebe --- /dev/null +++ b/traceCpm65.go @@ -0,0 +1,116 @@ +package izapple2 + +import ( + "fmt" +) + +/* + See: + https://github.com/davidgiven/cpm65 +*/ + +type traceCpm65 struct { + a *Apple2 + skipConsole bool +} + +const ( + cpm65BdosEntrypoint uint16 = 0x0804 // start-3, not really sure about this +) + +func newTraceCpm65(skipConsole bool) *traceCpm65 { + var t traceCpm65 + t.skipConsole = skipConsole + return &t +} + +func (t *traceCpm65) connect(a *Apple2) { + t.a = a +} + +func (t *traceCpm65) inspect() { + pc, _ := t.a.cpu.GetPCAndSP() + if pc == cpm65BdosEntrypoint { + regA, regX, regY, _ := t.a.cpu.GetAXYP() + param := uint16(regX)<<8 | uint16(regA) + switch regY { + case 2: // CONSOLE_OUTPUT + if !t.skipConsole { + fmt.Printf("CPM65 BDOS call $%02x:%s from $%04x with \"%c\"\n", regY, bdosCodeToName(regY), pc, regA) + } + case 9: // WRITE_STRING + if !t.skipConsole { + text := t.getCpmString(param) + fmt.Printf("CPM65 BDOS call $%02x:%s from $%04x with \"%s\"\n", regY, bdosCodeToName(regY), pc, text) + } + default: + fmt.Printf("CPM65 BDOS call $%02x:%s from $%04x\n", regY, bdosCodeToName(regY), pc) + } + } +} + +var cpm65BdosNames = []string{ + "EXIT_PROGRAM", // 0 + "CONSOLE_INPUT", // 1 + "CONSOLE_OUTPUT", // 2 + "AUX_INPUT", // 3 + "AUX_OUTPUT", // 4 + "PRINTER_OUTPUT", // 5 + "DIRECT_IO", // 6 + "GET_IO_BYTE", // 7 + "SET_IO_BYTE", // 8 + "WRITE_STRING", // 9 + "READ_LINE", // 10 + "CONSOLE_STATUS", // 11 + "GET_VERSION", // 12 + "RESET_DISKS", // 13 + "SELECT_DISK", // 14 + "OPEN_FILE", // 15 + "CLOSE_FILE", // 16 + "FIND_FIRST", // 17 + "FIND_NEXT", // 18 + "DELETE_FILE", // 19 + "READ_SEQUENTIAL", // 20 + "WRITE_SEQUENTIAL", // 21 + "CREATE_FILE", // 22 + "RENAME_FILE", // 23 + "GET_LOGIN_BITMAP", // 24 + "GET_CURRENT_DRIVE", // 25 + "SET_DMA_ADDRESS", // 26 + "GET_ALLOCATION_BITMAP", // 27 + "SET_DRIVE_READONLY", // 28 + "GET_READONLY_BITMAP", // 29 + "SET_FILE_ATTRIBUTES", // 30 + "GET_DPB", // 31 + "GET_SET_USER_NUMBER", // 32 + "READ_RANDOM", // 33 + "WRITE_RANDOM", // 34 + "COMPUTE_FILE_SIZE", // 35 + "COMPUTE_RANDOM_POINTER", // 36 + "RESET_DISK", // 37 + "GET_BIOS", // 38 + "", // 39 + "WRITE_RANDOM_FILLED", // 40 + "GETZP", // 41 + "GETTPA", // 42 +} + +func bdosCodeToName(code uint8) string { + if code < uint8(len(cpm65BdosNames)) { + return cpm65BdosNames[code] + } + return fmt.Sprintf("BDOS_%d", code) +} + +func (t *traceCpm65) getCpmString(address uint16) string { + s := "" + for { + ch := t.a.mmu.Peek(address) + if ch == '$' { + break + } + s += string(ch) + address++ + } + return s +}