Skip to content

Commit

Permalink
CPM-65 preconfigured model and better CPM-65 BIOS and BDOS tracing
Browse files Browse the repository at this point in the history
  • Loading branch information
ivanizag committed Oct 18, 2024
1 parent 83f72fe commit e8a44a8
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 7 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ The available pre-configured models are:
basis108: Basis 108
cpm: Apple ][+ with CP/M
cpm3: Apple //e with CP/M 3.0
cpm65: Apple //e with CPM-65
dos32: Apple ][ with 13 sectors disk adapter and DOS 3.2x
swyft: swyft
Expand Down Expand Up @@ -263,7 +264,8 @@ The available cards are:
The available tracers are:
cpm: Trace CPM BDOS calls
cpm65: Trace CPM65 BDOS calls
cpm65: Trace CPM65 BDOS calls skipping terminal IO
cpm65full: Trace CPM65 BDOS calls
cpu: Trace CPU execution
mli: Trace ProDOS MLI calls
mos: Trace MOS calls with Applecorn skipping terminal IO
Expand Down
3 changes: 3 additions & 0 deletions configs/cpm65.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
name: Apple //e with CPM-65
parent: 2enh
s6: diskii,disk1=<internal>/cpm65.po
16 changes: 16 additions & 0 deletions doc/cpm65.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# CPM-65

CPM-65 is a native port of Digital Research's seminal 1977 operating system CP/M to the 6502. See https://github.com/davidgiven/cpm65

It runs on an Apple IIe with 80 columns.
To run use the preconfigured model `cpm65`.

Usefull commands:

- `ìzapple -model cpm65` : To run the preconfigured setup
- `izapple apple2e.po`: To use the disk apple2e.po to run any release from [cpm65 releases](https://github.com/davidgiven/cpm65/releases/tag/dev)
- `ìzapple -model cpm65 -trace cpm65` : To trace the BDOS calls, skipping the console related calls
- `ìzapple -model cpm65 -trace cpm65full` : To trace all the BDOS calls.

Todo:
- The address for the BIOS and BDOS entrypoints is hardwired. It should be extracted somehow from the running memory.
4 changes: 3 additions & 1 deletion doc/usage.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ The available pre-configured models are:
basis108: Basis 108
cpm: Apple ][+ with CP/M
cpm3: Apple //e with CP/M 3.0
cpm65: Apple //e with CPM-65
dos32: Apple ][ with 13 sectors disk adapter and DOS 3.2x
swyft: swyft

Expand Down Expand Up @@ -83,7 +84,8 @@ The available cards are:

The available tracers are:
cpm: Trace CPM BDOS calls
cpm65: Trace CPM65 BDOS calls
cpm65: Trace CPM65 BDOS calls skipping terminal IO
cpm65full: Trace CPM65 BDOS calls
cpu: Trace CPU execution
mli: Trace ProDOS MLI calls
mos: Trace MOS calls with Applecorn skipping terminal IO
Expand Down
Binary file modified resources/cpm65.po
Binary file not shown.
12 changes: 12 additions & 0 deletions traceBuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,19 @@ func getTracerFactory() map[string]*traceBuilder {
}
tracerFactory["cpm65"] = &traceBuilder{
name: "cpm65",
description: "Trace CPM65 BDOS calls skipping terminal IO",
executionTracer: newTraceCpm65(true),
}
tracerFactory["cpm65full"] = &traceBuilder{
name: "cpm65full",
description: "Trace CPM65 BDOS calls",
executionTracer: newTraceCpm65(false),
}
tracerFactory["cpm"] = &traceBuilder{
name: "cpm",
description: "Trace CPM BDOS calls skipping terminal IO",
executionTracer: newTraceCpm(true),
}
tracerFactory["cpm"] = &traceBuilder{
name: "cpm",
description: "Trace CPM BDOS calls",
Expand Down Expand Up @@ -109,6 +119,8 @@ func setupTracers(a *Apple2, paramString string) error {
if builder.executionTracer != nil {
a.addTracer(builder.executionTracer)
}

fmt.Printf("Tracer %s enabled\n", builder.name)
}
return nil
}
Expand Down
49 changes: 44 additions & 5 deletions traceCpm65.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ type traceCpm65 struct {
}

const (
cpm65BdosEntrypoint uint16 = 0x0804 // start-3, not really sure about this
cpm65BdosEntrypoint uint16 = 0xeb8f // TODO: find the correct address dinamically
cpm65BiosEntrypoint uint16 = 0xfdce // TODO: find the correct address dinamically
)

func newTraceCpm65(skipConsole bool) *traceCpm65 {
Expand All @@ -40,15 +41,26 @@ func (t *traceCpm65) inspect() {
switch regY {
case 2: // CONSOLE_OUTPUT
if !t.skipConsole {
fmt.Printf("CPM65 BDOS call $%02x:%s from $%04x with \"%c\"\n", regY, bdos65CodeToName(regY), pc, regA)
fmt.Printf("CPM65 BDOS call %02v:%s with \"%c\"\n", regY, bdos65CodeToName(regY), regA)
}
case 9: // WRITE_STRING
if !t.skipConsole {
text := t.getCpm65String(param)
fmt.Printf("CPM65 BDOS call $%02x:%s from $%04x with \"%s\"\n", regY, bdos65CodeToName(regY), pc, text)
fmt.Printf("CPM65 BDOS call %02v:%s with \"%s\"\n", regY, bdos65CodeToName(regY), text)
}
default:
fmt.Printf("CPM65 BDOS call $%02x:%s from $%04x\n", regY, bdos65CodeToName(regY), pc)
fmt.Printf("CPM65 BDOS call %02v:%s($%04x)\n", regY, bdos65CodeToName(regY), param)
}
}

if pc == cpm65BiosEntrypoint {
regA, regX, regY, _ := t.a.cpu.GetAXYP()
param := uint16(regX)<<8 | uint16(regA)
if regY > 2 /*CONOUT*/ || !t.skipConsole {
switch regY {
default:
fmt.Printf("CPM65 BIOS call %02v:%s($%04x)\n", regY, bios65CodeToName(regY), param)
}
}
}
}
Expand Down Expand Up @@ -97,6 +109,26 @@ var cpm65BdosNames = []string{
"WRITE_RANDOM_FILLED", // 40
"GETZP", // 41
"GETTPA", // 42
"PARSE_FILENAME", // 43
}

var cpm65BiosNames = []string{
"CONST", // 0
"CONIN", // 1
"CONOUT", // 2
"SELDSK", // 3
"SETSEC", // 4
"SETDMA", // 5
"READ", // 6
"WRITE", // 7
"RELOCATE", // 8
"GETTPA", // 9
"SETTPA", // 10
"GETZP", // 11
"SETZP", // 12
"SETBANK", // 13
"ADDDRV", // 14
"FINDDRV", // 15
}

func bdos65CodeToName(code uint8) string {
Expand All @@ -106,11 +138,18 @@ func bdos65CodeToName(code uint8) string {
return fmt.Sprintf("BDOS_%d", code)
}

func bios65CodeToName(code uint8) string {
if code < uint8(len(cpm65BiosNames)) {
return cpm65BiosNames[code]
}
return fmt.Sprintf("BIOS_%d", code)
}

func (t *traceCpm65) getCpm65String(address uint16) string {
s := ""
for {
ch := t.a.mmu.Peek(address)
if ch == '$' {
if ch == '$' || ch == 0 {
break
}
s += string(ch)
Expand Down

0 comments on commit e8a44a8

Please sign in to comment.