yaze 0.2.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
spc700.h
Go to the documentation of this file.
1#ifndef YAZE_APP_EMU_SPC700_H
2#define YAZE_APP_EMU_SPC700_H
3
4#include <cstdint>
5#include <functional>
6#include <vector>
7#include <string>
8
9namespace yaze {
10namespace emu {
11
15class AudioRam {
16 public:
17 virtual ~AudioRam() = default;
18 virtual void reset() = 0;
19 virtual uint8_t read(uint16_t address) const = 0;
20 virtual uint8_t& mutable_read(uint16_t address) = 0;
21 virtual void write(uint16_t address, uint8_t value) = 0;
22 uint8_t operator[](uint16_t address) { return mutable_read(address); }
23};
24
28class AudioRamImpl : public AudioRam {
29 static const int ARAM_SIZE = 0x10000;
30 std::vector<uint8_t> ram = std::vector<uint8_t>(ARAM_SIZE, 0);
31
32 public:
33 AudioRamImpl() = default;
34 void reset() override { ram = std::vector<uint8_t>(ARAM_SIZE, 0); }
35
36 uint8_t read(uint16_t address) const override {
37 return ram[address % ARAM_SIZE];
38 }
39
40 uint8_t& mutable_read(uint16_t address) override {
41 return ram.at(address % ARAM_SIZE);
42 }
43
44 void write(uint16_t address, uint8_t value) override {
45 ram[address % ARAM_SIZE] = value;
46 }
47
48 // add [] operators
49 uint8_t operator[](uint16_t address) const { return read(address); }
50};
51
52typedef struct ApuCallbacks {
53 std::function<void(uint16_t, uint8_t)> write;
54 std::function<uint8_t(uint16_t)> read;
55 std::function<void(bool)> idle;
57
69class Spc700 {
70 private:
72 std::vector<std::string> log_;
73
76 // single-cycle
77 uint8_t opcode;
78 uint32_t step = 0;
79 uint32_t bstep;
80 uint16_t adr;
81 uint16_t adr1;
82 uint8_t dat;
83 uint16_t dat16;
84 uint8_t param;
85
86 const uint8_t ipl_rom_[64]{
87 0xCD, 0xEF, 0xBD, 0xE8, 0x00, 0xC6, 0x1D, 0xD0, 0xFC, 0x8F, 0xAA,
88 0xF4, 0x8F, 0xBB, 0xF5, 0x78, 0xCC, 0xF4, 0xD0, 0xFB, 0x2F, 0x19,
89 0xEB, 0xF4, 0xD0, 0xFC, 0x7E, 0xF4, 0xD0, 0x0B, 0xE4, 0xF5, 0xCB,
90 0xF4, 0xD7, 0x00, 0xFC, 0xD0, 0xF3, 0xAB, 0x01, 0x10, 0xEF, 0x7E,
91 0xF4, 0x10, 0xEB, 0xBA, 0xF6, 0xDA, 0x00, 0xBA, 0xF4, 0xC4, 0xF4,
92 0xDD, 0x5D, 0xD0, 0xDB, 0x1F, 0x00, 0x00, 0xC0, 0xFF};
93
94 public:
95 explicit Spc700(ApuCallbacks& callbacks) : callbacks_(callbacks) {}
96
97 // Registers
98 uint8_t A = 0x00; // 8-bit accumulator
99 uint8_t X = 0x00; // 8-bit index
100 uint8_t Y = 0x00; // 8-bit index
101 uint16_t YA = 0x00; // 16-bit pair of A (lsb) and Y (msb)
102 uint16_t PC = 0xFFC0; // program counter
103 uint8_t SP = 0x00; // stack pointer
104
105 struct Flags {
106 bool N : 1; // Negative flag
107 bool V : 1; // Overflow flag
108 bool P : 1; // Direct page flag
109 bool B : 1; // Break flag
110 bool H : 1; // Half-carry flag
111 bool I : 1; // Interrupt enable
112 bool Z : 1; // Zero flag
113 bool C : 1; // Carry flag
114 };
115 Flags PSW; // Processor status word
116
117 uint8_t FlagsToByte(Flags flags) {
118 return (flags.N << 7) | (flags.V << 6) | (flags.P << 5) | (flags.B << 4) |
119 (flags.H << 3) | (flags.I << 2) | (flags.Z << 1) | (flags.C);
120 }
121
122 Flags ByteToFlags(uint8_t byte) {
123 Flags flags;
124 flags.N = (byte & 0x80) >> 7;
125 flags.V = (byte & 0x40) >> 6;
126 flags.P = (byte & 0x20) >> 5;
127 flags.B = (byte & 0x10) >> 4;
128 flags.H = (byte & 0x08) >> 3;
129 flags.I = (byte & 0x04) >> 2;
130 flags.Z = (byte & 0x02) >> 1;
131 flags.C = (byte & 0x01);
132 return flags;
133 }
134
135 void Reset(bool hard = false);
136
137 void RunOpcode();
138
139 void ExecuteInstructions(uint8_t opcode);
140 void LogInstruction(uint16_t initial_pc, uint8_t opcode);
141
142 // Read a byte from the memory-mapped registers
143 uint8_t read(uint16_t address) { return callbacks_.read(address); }
144
145 uint16_t read_word(uint16_t address) {
146 uint8_t adrl = address;
147 uint8_t adrh = address + 1;
148 uint8_t value = callbacks_.read(adrl);
149 return value | (callbacks_.read(adrh) << 8);
150 }
151
152 uint8_t ReadOpcode() {
153 uint8_t opcode = callbacks_.read(PC++);
154 return opcode;
155 }
156
157 uint16_t ReadOpcodeWord() {
158 uint8_t low = ReadOpcode();
159 uint8_t high = ReadOpcode();
160 return low | (high << 8);
161 }
162
163 void DoBranch(uint8_t value, bool check) {
164 if (check) {
165 // taken branch: 2 extra cycles
166 callbacks_.idle(false);
167 callbacks_.idle(false);
168 PC += (int8_t)value;
169 }
170 }
171
172 // Write a byte to the memory-mapped registers
173 void write(uint16_t address, uint8_t value) {
174 callbacks_.write(address, value);
175 }
176
177 void push_byte(uint8_t value) {
178 callbacks_.write(0x100 | SP, value);
179 SP--;
180 }
181
182 void push_word(uint16_t value) {
183 push_byte(value >> 8);
184 push_byte(value & 0xFF);
185 }
186
187 uint8_t pull_byte() {
188 SP++;
189 return read(0x100 | SP);
190 }
191
192 uint16_t pull_word() {
193 uint16_t value = pull_byte();
194 value |= pull_byte() << 8;
195 return value;
196 }
197
198 // ======================================================
199 // Addressing modes
200
201 // Immediate
202 uint16_t imm();
203
204 // Direct page
205 uint8_t dp();
206 uint16_t dpx();
207
208 uint8_t get_dp_addr();
209
210 uint8_t abs_bit(uint16_t* adr);
211 uint16_t dp_dp(uint8_t* src);
212 uint16_t ind();
213 uint16_t ind_ind(uint8_t* srcVal);
214 uint16_t dp_word(uint16_t* low);
215 uint16_t ind_p();
216 uint16_t abs_x();
217 uint16_t abs_y();
218 uint16_t idx();
219 uint16_t idy();
220 uint16_t dp_y();
221 uint16_t dp_imm(uint8_t* srcVal);
222 uint16_t abs();
223
224 int8_t rel();
225
226 // Direct page indexed by X
227 uint8_t dp_plus_x();
228
229 // Direct page indexed by Y
230 uint8_t dp_plus_y();
231
232 // Indexed indirect (add index before 16-bit lookup).
233 uint16_t dp_plus_x_indirect();
234
235 // Indirect indexed (add index after 16-bit lookup).
236 uint16_t dp_indirect_plus_y();
237 uint8_t i();
238
239 uint8_t i_postinc();
240
241 uint16_t addr_plus_i();
242
243 uint16_t addr_plus_i_indexed();
244
245 // ==========================================================================
246 // Instructions
247
248 void MOV(uint16_t adr);
249 void MOV_ADDR(uint16_t address, uint8_t operand);
250 void MOVY(uint16_t adr);
251 void MOVX(uint16_t adr);
252 void MOVS(uint16_t adr);
253 void MOVSX(uint16_t adr);
254 void MOVSY(uint16_t adr);
255
256 void ADC(uint16_t adr);
257 void ADCM(uint16_t& dest, uint8_t operand);
258
259 void SBC(uint16_t adr);
260 void SBCM(uint16_t& dest, uint8_t operand);
261
262 void CMP(uint16_t adr);
263 void CMPX(uint16_t adr);
264 void CMPM(uint16_t dst, uint8_t value);
265 void CMPY(uint16_t adr);
266
267 void AND(uint16_t adr);
268 void ANDM(uint16_t dest, uint8_t operand);
269
270 void OR(uint16_t adr);
271 void ORM(uint16_t dest, uint8_t operand);
272
273 void EOR(uint16_t adr);
274 void EORM(uint16_t dest, uint8_t operand);
275
276 void ASL(uint16_t operand);
277 void LSR(uint16_t adr);
278
279 void ROL(uint16_t operand);
280 void ROR(uint16_t adr);
281
282 void XCN(uint8_t operand, bool isImmediate = false);
283 void INC(uint16_t adr);
284 void DEC(uint16_t operand);
285 void MOVW(uint16_t& dest, uint16_t operand);
286 void INCW(uint16_t& operand);
287 void DECW(uint16_t& operand);
288 void ADDW(uint16_t& dest, uint16_t operand);
289 void SUBW(uint16_t& dest, uint16_t operand);
290 void CMPW(uint16_t operand);
291 void MUL(uint8_t operand);
292 void DIV(uint8_t operand);
293 void BRA(int8_t offset);
294 void BEQ(int8_t offset);
295 void BNE(int8_t offset);
296 void BCS(int8_t offset);
297 void BCC(int8_t offset);
298 void BVS(int8_t offset);
299 void BVC(int8_t offset);
300 void BMI(int8_t offset);
301 void BPL(int8_t offset);
302 void BBS(uint8_t bit, uint8_t operand);
303 void BBC(uint8_t bit, uint8_t operand);
304 void JMP(uint16_t address);
305 void CALL(uint16_t address);
306 void PCALL(uint8_t offset);
307 void TCALL(uint8_t offset);
308 void BRK();
309 void RET();
310 void RETI();
311 void PUSH(uint8_t operand);
312 void POP(uint8_t& operand);
313 void SET1(uint8_t bit, uint8_t& operand);
314 void CLR1(uint8_t bit, uint8_t& operand);
315 void TSET1(uint8_t bit, uint8_t& operand);
316 void TCLR1(uint8_t bit, uint8_t& operand);
317 void AND1(uint8_t bit, uint8_t& operand);
318 void OR1(uint8_t bit, uint8_t& operand);
319 void EOR1(uint8_t bit, uint8_t& operand);
320 void NOT1(uint8_t bit, uint8_t& operand);
321 void MOV1(uint8_t bit, uint8_t& operand);
322 void CLRC();
323 void SETC();
324 void NOTC();
325 void CLRV();
326 void CLRP();
327 void SETP();
328 void EI();
329 void DI();
330 void NOP();
331 void SLEEP();
332 void STOP();
333
334 // CBNE DBNZ
335};
336
337} // namespace emu
338} // namespace yaze
339
340#endif // YAZE_APP_EMU_SPC700_H
uint8_t read(uint16_t address) const override
Definition spc700.h:36
void reset() override
Definition spc700.h:34
std::vector< uint8_t > ram
Definition spc700.h:30
void write(uint16_t address, uint8_t value) override
Definition spc700.h:44
uint8_t & mutable_read(uint16_t address) override
Definition spc700.h:40
uint8_t operator[](uint16_t address) const
Definition spc700.h:49
static const int ARAM_SIZE
Definition spc700.h:29
AudioRam is an interface for the Audio RAM used by the SPC700.
Definition spc700.h:15
virtual void reset()=0
uint8_t operator[](uint16_t address)
Definition spc700.h:22
virtual void write(uint16_t address, uint8_t value)=0
virtual uint8_t & mutable_read(uint16_t address)=0
virtual uint8_t read(uint16_t address) const =0
virtual ~AudioRam()=default
uint16_t adr1
Definition spc700.h:81
void CMPM(uint16_t dst, uint8_t value)
void BEQ(int8_t offset)
void SUBW(uint16_t &dest, uint16_t operand)
std::vector< std::string > log_
Definition spc700.h:72
void PCALL(uint8_t offset)
void JMP(uint16_t address)
void MOVS(uint16_t adr)
uint16_t pull_word()
Definition spc700.h:192
uint8_t read(uint16_t address)
Definition spc700.h:143
uint8_t dp_plus_x()
Definition addressing.cc:87
void MOVSX(uint16_t adr)
void NOT1(uint8_t bit, uint8_t &operand)
uint16_t ind_p()
Definition addressing.cc:73
uint16_t adr
Definition spc700.h:80
void MOVX(uint16_t adr)
uint16_t dp_y()
Definition addressing.cc:25
uint32_t bstep
Definition spc700.h:79
uint8_t abs_bit(uint16_t *adr)
Definition addressing.cc:61
void AND1(uint8_t bit, uint8_t &operand)
void SBC(uint16_t adr)
void CMPY(uint16_t adr)
void ANDM(uint16_t dest, uint8_t operand)
uint8_t opcode
Definition spc700.h:77
uint16_t dat16
Definition spc700.h:83
void MOVW(uint16_t &dest, uint16_t operand)
uint8_t dat
Definition spc700.h:82
void EORM(uint16_t dest, uint8_t operand)
uint16_t dp_indirect_plus_y()
uint16_t addr_plus_i_indexed()
void DEC(uint16_t operand)
uint16_t ind_ind(uint8_t *srcVal)
Definition addressing.cc:55
uint32_t step
Definition spc700.h:78
uint8_t i_postinc()
uint16_t dp_plus_x_indirect()
void BCS(int8_t offset)
uint16_t addr_plus_i()
void DIV(uint8_t operand)
uint8_t dp_plus_y()
Definition addressing.cc:94
void MOV(uint16_t adr)
void EOR1(uint8_t bit, uint8_t &operand)
void BVS(int8_t offset)
void SBCM(uint16_t &dest, uint8_t operand)
void BVC(int8_t offset)
void Reset(bool hard=false)
Definition spc700.cc:13
void LSR(uint16_t adr)
void SET1(uint8_t bit, uint8_t &operand)
void push_byte(uint8_t value)
Definition spc700.h:177
void CMPX(uint16_t adr)
void TCLR1(uint8_t bit, uint8_t &operand)
uint8_t FlagsToByte(Flags flags)
Definition spc700.h:117
bool reset_wanted_
Definition spc700.h:75
void LogInstruction(uint16_t initial_pc, uint8_t opcode)
Definition spc700.cc:1296
const uint8_t ipl_rom_[64]
Definition spc700.h:86
uint16_t abs_y()
Definition addressing.cc:37
uint16_t dp_imm(uint8_t *srcVal)
Definition addressing.cc:50
void TCALL(uint8_t offset)
uint16_t ReadOpcodeWord()
Definition spc700.h:157
void CMP(uint16_t adr)
uint16_t dp_dp(uint8_t *src)
void ROL(uint16_t operand)
void MOV_ADDR(uint16_t address, uint8_t operand)
void write(uint16_t address, uint8_t value)
Definition spc700.h:173
uint8_t param
Definition spc700.h:84
void XCN(uint8_t operand, bool isImmediate=false)
void PUSH(uint8_t operand)
void INC(uint16_t adr)
void ADDW(uint16_t &dest, uint16_t operand)
uint16_t abs_x()
Definition addressing.cc:31
void INCW(uint16_t &operand)
void BBC(uint8_t bit, uint8_t operand)
void BMI(int8_t offset)
void CALL(uint16_t address)
void BNE(int8_t offset)
uint16_t dp_word(uint16_t *low)
Definition addressing.cc:67
uint8_t get_dp_addr()
void DECW(uint16_t &operand)
void push_word(uint16_t value)
Definition spc700.h:182
void ADC(uint16_t adr)
void EOR(uint16_t adr)
void ROR(uint16_t adr)
void BBS(uint8_t bit, uint8_t operand)
uint16_t read_word(uint16_t address)
Definition spc700.h:145
void POP(uint8_t &operand)
void ASL(uint16_t operand)
void BCC(int8_t offset)
void CLR1(uint8_t bit, uint8_t &operand)
uint16_t YA
Definition spc700.h:101
void OR(uint16_t adr)
void ADCM(uint16_t &dest, uint8_t operand)
void BRA(int8_t offset)
void BPL(int8_t offset)
void OR1(uint8_t bit, uint8_t &operand)
void DoBranch(uint8_t value, bool check)
Definition spc700.h:163
void CMPW(uint16_t operand)
uint16_t PC
Definition spc700.h:102
Spc700(ApuCallbacks &callbacks)
Definition spc700.h:95
void AND(uint16_t adr)
uint8_t pull_byte()
Definition spc700.h:187
void MOV1(uint8_t bit, uint8_t &operand)
void TSET1(uint8_t bit, uint8_t &operand)
ApuCallbacks callbacks_
Definition spc700.h:71
void MOVSY(uint16_t adr)
void ExecuteInstructions(uint8_t opcode)
Definition spc700.cc:55
void MOVY(uint16_t adr)
void ORM(uint16_t dest, uint8_t operand)
uint16_t ind()
Definition addressing.cc:8
uint8_t ReadOpcode()
Definition spc700.h:152
Flags ByteToFlags(uint8_t byte)
Definition spc700.h:122
void RunOpcode()
Definition spc700.cc:27
void MUL(uint8_t operand)
SNES Emulation and debugging tools.
Definition apu.cc:13
struct yaze::emu::ApuCallbacks ApuCallbacks
Main namespace for the application.
Definition controller.cc:18
std::function< void(uint16_t, uint8_t)> write
Definition spc700.h:53
std::function< void(bool)> idle
Definition spc700.h:55
std::function< uint8_t(uint16_t)> read
Definition spc700.h:54