Skip to content

Commit

Permalink
Support for the Softcard Z80 card and CP/M
Browse files Browse the repository at this point in the history
  • Loading branch information
ivanizag committed Sep 15, 2024
1 parent c89aa36 commit 87dbe86
Show file tree
Hide file tree
Showing 9 changed files with 160 additions and 0 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Portable emulator of an Apple II+ or //e. Written in Go.
- MultiROM card
- Dan ][ Controller card
- ProDOS ROM card
- Microsoft Z80 Softcard using the [Z80](https://github.com/koron-go/z80) emulation from Koron
- Useful cards not emulating a real card
- Bootable SmartPort / ProDOS card with the following smartport devices:
- Block device (hard disks)
Expand Down Expand Up @@ -230,6 +231,7 @@ The available pre-configured models are:
2plus: Apple ][+
base64a: Base 64A
basis108: Basis 108
cpm: Apple ][+ with CP/M
dos32: Apple ][ with 13 sectors disk adapter and DOS 3.2x
swyft: swyft
Expand All @@ -256,6 +258,7 @@ The available cards are:
thunderclock: Clock card
videx: Videx compatible 80 columns card
vidhd: Firmware signature of the VidHD card to trick Total Replay to use the SHR mode
z80softcard: Microsoft Z80 SoftCard to run CP/M
The available tracers are:
cpm65: Trace CPM65 BDOS calls
Expand Down
1 change: 1 addition & 0 deletions cardBuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ func getCardFactory() map[string]*cardBuilder {
cardFactory["thunderclock"] = newCardThunderClockPlusBuilder()
cardFactory["videx"] = newCardVidexBuilder()
cardFactory["vidhd"] = newCardVidHDBuilder()
cardFactory["z80softcard"] = newCardZ80SoftCardBuilder()
return cardFactory
}

Expand Down
117 changes: 117 additions & 0 deletions cardZ80Softcard.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package izapple2

import (
"fmt"

"github.com/koron-go/z80"
)

/*
Microsoft Z80 SoftCard
See:
http://mirrors.apple2.org.za/Apple%20II%20Documentation%20Project/Interface%20Cards/Z80%20Cards/Microsoft%20SoftCard/
This card activates DMA to take control of the system. DMA is actiavted or
deactivated by writing to the Csxx area.
The emulation works on the Apple II+, but doesn't work when 80 columns are
available. It is not working then on the Apple IIe or the Apple II+ with a
Videx card.
*/

// CardVidHD represents a VidHD card
type CardZ80SoftCard struct {
cardBase

cpu *z80.CPU
z80Active bool
}

func newCardZ80SoftCardBuilder() *cardBuilder {
return &cardBuilder{
name: "Microsoft Z80 SoftCard",
description: "Microsoft Z80 SoftCard to run CP/M",
buildFunc: func(params map[string]string) (Card, error) {
var c CardZ80SoftCard
c.romCxxx = &cardROMWriteTrap{
callback: func() {
c.flipDMA()
},
}

return &c, nil
},
}
}

func (c *CardZ80SoftCard) assign(a *Apple2, slot int) {
mem := &cardZ80SoftCardMMU{
mmu: a.mmu,
}

c.cpu = &z80.CPU{
Memory: mem,
}

c.cardBase.assign(a, slot)
}

func (c *CardZ80SoftCard) flipDMA() {
c.tracef("Z80 DMA flip\n")
c.z80Active = !c.z80Active
if c.z80Active {
c.activateDMA()
} else {
c.deactivateDMA()
}
}

func (c *CardZ80SoftCard) runDMACycle() {
if c.a.cpuTrace {
fmt.Printf("Z80 pc=$%04x ($%04x for the 6502) Opcode: $%02x \n",
c.cpu.PC, z80AddressTranslation(c.cpu.PC), c.cpu.Memory.Get(c.cpu.PC))
}
c.cpu.Step()
}

type cardROMWriteTrap struct {
callback func()
}

func (r *cardROMWriteTrap) peek(address uint16) uint8 {
return 0
}

func (r *cardROMWriteTrap) poke(address uint16, value uint8) {
if address >= 0xC000 && address < 0xC800 {
r.callback()
}
}

type cardZ80SoftCardMMU struct {
mmu *memoryManager
}

func (m *cardZ80SoftCardMMU) Get(addr uint16) uint8 {
return m.mmu.Peek(z80AddressTranslation(addr))
}

func (m *cardZ80SoftCardMMU) Set(addr uint16, value uint8) {
m.mmu.Poke(z80AddressTranslation(addr), value)
}

func z80AddressTranslation(addr uint16) uint16 {
if addr < 0xb000 {
return addr + 0x1000
} else if addr < 0xe000 {
return addr + 0x2000
} else if addr < 0xf000 {
return addr - 0x2000
} else {
return addr - 0xf000
}
}
28 changes: 28 additions & 0 deletions cardZ80softcard_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package izapple2

import (
"strings"
"testing"
)

func TestCPMBoot(t *testing.T) {
at, err := makeApple2Tester("cpm", nil)
if err != nil {
t.Fatal(err)
}

banner := "APPLE ][ CP/M"
prompt := "A>"
at.terminateCondition = buildTerminateConditionTexts([]string{banner, prompt}, testTextMode40, 10_000_000)

at.run()

text := at.getText(testTextMode40)
if !strings.Contains(text, banner) {
t.Errorf("Expected '%s', got '%s'", banner, text)
}
if !strings.Contains(text, prompt) {
t.Errorf("Expected prompt '%s', got '%s'", prompt, text)
}

}
6 changes: 6 additions & 0 deletions configs/cpm.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name: Apple ][+ with CP/M
parent: 2plus
# Fails with 80 columns
s3: empty
s4: z80softcard
s6: diskii,disk1=<internal>/cpm_2.20B_56K.po
2 changes: 2 additions & 0 deletions doc/usage.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ The available pre-configured models are:
2plus: Apple ][+
base64a: Base 64A
basis108: Basis 108
cpm: Apple ][+ with CP/M
dos32: Apple ][ with 13 sectors disk adapter and DOS 3.2x
swyft: swyft

Expand All @@ -77,6 +78,7 @@ The available cards are:
thunderclock: Clock card
videx: Videx compatible 80 columns card
vidhd: Firmware signature of the VidHD card to trick Total Replay to use the SHR mode
z80softcard: Microsoft Z80 SoftCard to run CP/M

The available tracers are:
cpm65: Trace CPM65 BDOS calls
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
fyne.io/fyne/v2 v2.1.4
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240118000515-a250818d05e3
github.com/ivanizag/iz6502 v1.4.0
github.com/koron-go/z80 v0.10.1
github.com/pkg/profile v1.7.0
github.com/veandco/go-sdl2 v0.4.38
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ github.com/ivanizag/iz6502 v1.4.0 h1:7eYygUkCPwFRH0tf2JSg1k+Sy27wwPi3ActuVNVv1Uc
github.com/ivanizag/iz6502 v1.4.0/go.mod h1:h4gbw3IK6WCYawi00kBhQ4ACeQkGWgqbUeAgDaQpy6s=
github.com/jackmordaunt/icns v0.0.0-20181231085925-4f16af745526/go.mod h1:UQkeMHVoNcyXYq9otUupF7/h/2tmHlhrS2zw7ZVvUqc=
github.com/josephspurrier/goversioninfo v0.0.0-20200309025242-14b0ab84c6ca/go.mod h1:eJTEwMjXb7kZ633hO3Ln9mBUCOjX2+FlTljvpl9SYdE=
github.com/koron-go/z80 v0.10.1 h1:Jfb0esP/QFL4cvcr+eFECVG0Y/mA9JBLC4EKbMU5zAY=
github.com/koron-go/z80 v0.10.1/go.mod h1:ry+Zl9kRKelzaDG9UzEtUpUnXy0Yv/kk1YEaX958xdk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
Expand Down
Binary file added resources/cpm_2.20B_56K.po
Binary file not shown.

0 comments on commit 87dbe86

Please sign in to comment.