-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgameboy.go
120 lines (95 loc) · 2.46 KB
/
gameboy.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
package main
import (
"github.com/moshenahmias/gopherboy/cpu"
"github.com/moshenahmias/gopherboy/display"
"github.com/moshenahmias/gopherboy/game"
"github.com/moshenahmias/gopherboy/joypad"
"github.com/moshenahmias/gopherboy/memory"
"github.com/moshenahmias/gopherboy/timers"
)
// Gameboy console
type Gameboy struct {
core *cpu.Core
mmu *memory.MMU
bios bool
}
// NewGameboy creates Gameboy instance
func NewGameboy(
cartridge *game.Cartridge,
mmu *memory.MMU,
core *cpu.Core,
biosData []byte,
joyp *joypad.JOYP,
gpu *display.GPU) (*Gameboy, error) {
// map FEA0-FEFF (unused)
if err := mmu.Map(&memory.Null{}, 0xFEA0, 0xFEFF); err != nil {
return nil, err
}
// map joypad
if err := mmu.Map(joyp, joypad.AddrJOYP, joypad.AddrJOYP); err != nil {
return nil, err
}
// create and map the timer
timer := timers.NewTimer(core)
// map timer
if err := mmu.Map(timer, 0xFF04, 0xFF07); err != nil {
return nil, err
}
bios := len(biosData) > 0
if bios {
// map bios
if err := mmu.Map(memory.NewROM(biosData, 0), 0x0000, 0x00FF); err != nil {
return nil, err
}
// map cartridge
if err := mmu.Map(cartridge, 0x0100, 0x7FFF); err != nil {
return nil, err
}
} else {
// map cartridge
if err := mmu.Map(cartridge, 0x0000, 0x7FFF); err != nil {
return nil, err
}
}
// map external ram
if err := mmu.Map(cartridge, 0xA000, 0xBFFF); err != nil {
return nil, err
}
// map bios unmapper
if err := mmu.Map(memory.NewBiosUnmapper(mmu, cartridge), 0xFF50, 0xFF50); err != nil {
return nil, err
}
// map working ram
wram := memory.NewRAM(make([]byte, 8192), 0xC000)
if err := mmu.Map(wram, 0xC000, 0xDFFF); err != nil {
return nil, err
}
// map shadow
for src := uint16(0xE000); src <= uint16(0xFDFF); src++ {
if err := mmu.Map(memory.NewEchoer(mmu, src-0x2000), src, src); err != nil {
return nil, err
}
}
// map zero page information ram
zpram := memory.NewRAM(make([]byte, 127), 0xFF80)
if err := mmu.Map(zpram, 0xFF80, 0xFFFE); err != nil {
return nil, err
}
core.RegisterToClockChanges(gpu)
return &Gameboy{core: core, mmu: mmu, bios: bios}, nil
}
// Start the cpu
func (g *Gameboy) Start() error {
if g.bios {
return g.core.Start(0x0000)
}
return g.core.Start(0x0100)
}
// Pause the cpu
func (g *Gameboy) Pause() {
g.core.Pause()
}
// Stop the cpu
func (g *Gameboy) Stop() {
g.core.Stop()
}