-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.cpp
167 lines (122 loc) · 3.82 KB
/
main.cpp
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#include <iostream>
#include <cstdio>
#include <cstdlib>
// https://www.youtube.com/watch?v=qJgsuQoy9bc&t=776s
using Byte = unsigned char;
using Word = unsigned short;
using u32 = unsigned int;
struct MEM {
static constexpr u32 MAX_MEM = 1024 * 64;
Byte Data[MAX_MEM];
void init() {
for (unsigned char & i : Data) {
i = 0x0;
}
}
// Read 1 byte
Byte operator[](u32 addr) const {
return Data[addr]; // assert here Address is < MAX_MEM
}
// Write 1 byte
Byte &operator[](u32 addr) {
return Data[addr]; // assert here Address is < MAX_MEM
}
// Write 2 bytes
void writeWord(u32 &cycles, Word value, u32 address) {
Data[address] = value & 0xFF;
Data[address + 1] = (value >> 8);
cycles -= 2;
}
};
struct CPU {
Word PC; // Program Counter
Word SP; // Stack Pointer
Byte A, X, Y; // Registers
Byte C : 1; // Status Flag - Carry
Byte Z : 1; // Status Flag - Zero
Byte I : 1; // Status Flag - Interrupt Disable
Byte D : 1; // Status Flag - Decimal Mode
Byte B : 1; // Status Flag - Break Command
Byte V : 1; // Status Flag - Overflow
Byte N : 1; // Status Flag - Negative
void reset(MEM &memory) { // Inaccurate
PC = 0xFFFC;
SP = 0x0100; // Normally it is supposed to be 0x00FF
C = Z = I = D = B = V = N = 0x0;
A = X = Y = 0x0;
memory.init();
// Set IO vectors
}
Byte fetchByte(u32 &cycles, MEM &memory) {
Byte data = memory[PC];
PC++;
cycles--;
return data;
}
static Byte readByte(u32 &cycles, Byte address, MEM &memory) {
Byte data = memory[address];
cycles--;
return data;
}
Word fetchWord(u32 &cycles, MEM &memory) {
// 6502 is little endian!
Word data = memory[PC];
PC++;
data |= (memory[PC] << 8);
PC++;
cycles-=2;
// to handle endianness swap bytes here as:
/* if(PLATFORM_BIG_ENDIAN) swapBytesInWord(data); */
return data;
}
/* OPCODES */
static constexpr Byte
INST_LDA_IM = 0xA9,
INST_LDA_ZP = 0xA5,
INST_LDA_ZPX = 0xB5,
INST_JSR = 0x20;
void LDASetStatus() {
Z = (A==0);
N = (A & 0b10000000) > 0;
}
void exec(u32 cycles, MEM &memory) {
while (cycles > 0) {
Byte inst = fetchByte(cycles, memory);
switch (inst) {
case INST_LDA_IM: {
Byte value = fetchByte(cycles, memory);
A = value;
LDASetStatus();
} break;
case INST_LDA_ZP: {
Byte zeroPageAddress = fetchByte(cycles, memory);
A = readByte(cycles, zeroPageAddress, memory);
LDASetStatus();
} break;
case INST_LDA_ZPX: {
Byte zeroPageAddress = fetchByte(cycles, memory);
zeroPageAddress += X;
cycles--;
A = readByte(cycles, zeroPageAddress, memory);
LDASetStatus();
} break;
case INST_JSR: {
Word subAddr = fetchWord(cycles, memory);
memory.writeWord(cycles,PC - 1, SP); // TODO: SP increment missing - would fail!
PC = subAddr;
cycles--;
} break;
default: {
std::cerr << "Instruction not handled: " << inst << std::endl;
} break;
}
}
}
};
int main() {
MEM mem;
CPU cpu;
cpu.reset(mem);
// cpu.exec(2, mem);
return 0;
}