-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBus.cpp
More file actions
101 lines (90 loc) · 3.2 KB
/
Copy pathBus.cpp
File metadata and controls
101 lines (90 loc) · 3.2 KB
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
#include "Bus.h"
Bus::Bus() {
// Clear RAM
for(uint8_t &x : CPURAM)
x = 0x00;
// Connect this bus to the CPU
cpu.ConnectBus(this);
}
Bus::~Bus() {
}
uint8_t Bus::CPURead(uint16_t addr, bool bReadOnly) {
uint8_t data = 0x00;
if(cartridge->cpuRead(addr, data)) { // intercept by Loader
return data;
// Loader handled read, do nothing
} else if(addr >= 0x0000 && addr <= 0x1FFF) { // CPU read
return CPURAM[addr & 0x07FF];
} else if(addr >= 0x2000 && addr <= 0x3FFF) { // PPU write
return PPU.CPURead(addr & 0x0007, bReadOnly);
} else if(addr == 0x4016 || addr == 0x4017) { //capture the current state of the controller (user input)
/*
there are 8 controller bits, but we only read them one at a time.
each time, we read the leftmost bit (most significant bit). thus, after
each read, we shift the state left, so that the most significant bit gets kicked out,
and the next bit we need to read gets put into the leftmost bit.
*/
uint8_t ControllerMSB = (ControllerState[addr & 0x0001] & 0x80) > 0;
ControllerState[addr & 0x0001] <<= 1;
return ControllerMSB;
}
return 0x00;
}
void Bus::CPUWrite(uint16_t addr, uint8_t data) {
if(cartridge->cpuWrite(addr, data)) { // intercept by Loader
// Loader handled write, do nothing
} else if(addr >= 0x0000 && addr <= 0x1FFF) { // writing to CPU
CPURAM[addr & 0x07FF] = data;
} else if(addr >= 0x2000 && addr <= 0x3FFF) { // writing to PPU
PPU.CPUWrite(addr & 0x0007, data);
} else if(addr == 0x4014) { //DMA transfer, so passing data through OAM
DMA_MSB = data;
DMA_LSB = 0x00;
//initiate transfer
DMA_Transfer = 1;
} else if(addr == 0x4016 || addr == 0x4017) { //capture the current state of the controller (user input)
ControllerState[addr & 0x0001] = Controller[addr & 0x0001];
}
}
void Bus::InsertCartridge(std::shared_ptr<Loader>& loader) {
this->cartridge = loader;
PPU.ConnectCartridge(loader);
}
void Bus::RST() {
cpu.RST();
cartridge->RST();
//TODO: call ppu.RST();
ClockCounter = 0;
DMA_MSB = DMA_LSB = DMA_Data = 0;
DMA_Transfer = 0;
DMA_Stall = 1;
}
void Bus::CLK() {
// call PPU clock function
PPU.CLK();
// call CPU clock function
if(ClockCounter % 3 == 0) { //cpu clock only ticks every 3 cycles, whereas ppu ticks every cycle
if(DMA_Transfer) {
if(DMA_Stall) {
//stall for 1 or 2 cycles
DMA_Stall = ClockCounter % 2 == 1;
} else {
//on even cycles, read, and on odd cycles, write
if(ClockCounter % 2 == 0) {
DMA_Data = CPURead(DMA_MSB << 8 | DMA_LSB);
} else {
PPU._OAM[DMA_LSB] = DMA_Data;
DMA_LSB++;
if(DMA_LSB == 0x00) { //wrapped around, so we wrote 256 bytes
DMA_Transfer = 0;
DMA_Stall = 1;
}
}
}
} else {
cpu.CLK();
}
}
// increment system clock counter
ClockCounter++;
}