-
Notifications
You must be signed in to change notification settings - Fork 9
/
cardZ80Softcard.go
123 lines (97 loc) · 2.41 KB
/
cardZ80Softcard.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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) reset() {
c.cpu.States = z80.States{}
}
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, A: $%02X, B: $%02X, C: $%02X, D: $%02X, E: $%02X, HL: $%04X\n",
c.cpu.States.PC, c.cpu.States.AF.Hi, c.cpu.States.BC.Hi,
c.cpu.States.BC.Lo, c.cpu.States.DE.Hi, c.cpu.States.DE.Lo,
c.cpu.States.HL.U16())
}
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
}
}