1use crate::addressing_mode::*;
2use crate::instruction::*;
3pub use crate::{address, status, Address};
4use crate::{opcode, UnknownOpcode};
5#[cfg(feature = "serialize")]
6use serde::{Deserialize, Serialize};
7
8#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
9#[derive(Debug, Clone)]
10pub struct Cpu {
11 pub pc: Address,
12 pub sp: u8,
13 pub acc: u8,
14 pub x: u8,
15 pub y: u8,
16 pub status: StatusRegister,
17}
18
19impl Cpu {
20 pub fn new() -> Self {
21 Self {
22 pc: 0,
23 sp: 0xff,
24 acc: 0,
25 x: 0,
26 y: 0,
27 status: StatusRegister::new(),
28 }
29 }
30 pub fn retrieve_nmi_return_address_during_nmi<MRO: MemoryReadOnly>(
31 &self,
32 memory: &MRO,
33 ) -> Option<Address> {
34 if self.pc == memory.read_u16_le_read_only(crate::interrupt_vector::NMI_LO) {
35 let lo = memory.read_u8_stack_read_only(self.sp.wrapping_add(2));
36 let hi = memory.read_u8_stack_read_only(self.sp.wrapping_add(3));
37 Some(address::from_u8_lo_hi(lo, hi))
38 } else {
39 None
40 }
41 }
42 pub fn nmi<M: Memory>(&mut self, memory: &mut M) {
43 self.push_stack_u8(memory, address::hi(self.pc));
44 self.push_stack_u8(memory, address::lo(self.pc));
45 self.push_stack_u8(memory, self.status.masked_with_brk_and_expansion());
46 self.pc = memory.read_u16_le(crate::interrupt_vector::NMI_LO);
47 }
48 pub fn push_stack_u8<M: Memory>(&mut self, memory: &mut M, value: u8) {
49 memory.write_u8_stack(self.sp, value);
50 self.sp = self.sp.wrapping_sub(1);
51 }
52 pub fn pop_stack_u8<M: Memory>(&mut self, memory: &mut M) -> u8 {
53 self.sp = self.sp.wrapping_add(1);
54 memory.read_u8_stack(self.sp)
55 }
56 pub fn start<M: Memory>(&mut self, memory: &mut M) {
57 self.pc = memory.read_u16_le(crate::interrupt_vector::START_LO);
58 }
59 pub fn run_for_cycles<M: Memory>(
60 &mut self,
61 memory: &mut M,
62 num_cycles: usize,
63 ) -> Result<usize, UnknownOpcode> {
64 let mut cycle_count = 0;
65 while cycle_count < num_cycles {
66 cycle_count += self.step(memory)? as usize;
67 }
68 Ok(cycle_count)
69 }
70 pub fn step<M: Memory>(&mut self, memory: &mut M) -> Result<u8, UnknownOpcode> {
71 let opcode = memory.read_u8(self.pc);
72 let cycles = match opcode {
73 opcode::adc::ABSOLUTE => adc::interpret(Absolute, self, memory),
74 opcode::adc::ABSOLUTE_X_INDEXED => adc::interpret(AbsoluteXIndexed, self, memory),
75 opcode::adc::ABSOLUTE_Y_INDEXED => adc::interpret(AbsoluteYIndexed, self, memory),
76 opcode::adc::IMMEDIATE => adc::interpret(Immediate, self, memory),
77 opcode::adc::INDIRECT_Y_INDEXED => adc::interpret(IndirectYIndexed, self, memory),
78 opcode::adc::X_INDEXED_INDIRECT => adc::interpret(XIndexedIndirect, self, memory),
79 opcode::adc::ZERO_PAGE => adc::interpret(ZeroPage, self, memory),
80 opcode::adc::ZERO_PAGE_X_INDEXED => adc::interpret(ZeroPageXIndexed, self, memory),
81 opcode::ahx::unofficial0::ABSOLUTE_Y_INDEXED => {
82 ahx::interpret(AbsoluteYIndexed, self, memory)
83 }
84 opcode::ahx::unofficial0::INDIRECT_Y_INDEXED => {
85 ahx::interpret(IndirectYIndexed, self, memory)
86 }
87 opcode::alr::unofficial0::IMMEDIATE => alr::interpret(self, memory),
88 opcode::arr::unofficial0::IMMEDIATE => arr::interpret(self, memory),
89 opcode::anc::unofficial0::IMMEDIATE => anc::interpret(self, memory),
90 opcode::anc::unofficial1::IMMEDIATE => anc::interpret(self, memory),
91 opcode::and::ABSOLUTE => and::interpret(Absolute, self, memory),
92 opcode::and::ABSOLUTE_X_INDEXED => and::interpret(AbsoluteXIndexed, self, memory),
93 opcode::and::ABSOLUTE_Y_INDEXED => and::interpret(AbsoluteYIndexed, self, memory),
94 opcode::and::IMMEDIATE => and::interpret(Immediate, self, memory),
95 opcode::and::INDIRECT_Y_INDEXED => and::interpret(IndirectYIndexed, self, memory),
96 opcode::and::X_INDEXED_INDIRECT => and::interpret(XIndexedIndirect, self, memory),
97 opcode::and::ZERO_PAGE => and::interpret(ZeroPage, self, memory),
98 opcode::and::ZERO_PAGE_X_INDEXED => and::interpret(ZeroPageXIndexed, self, memory),
99 opcode::asl::ABSOLUTE => asl::interpret(Absolute, self, memory),
100 opcode::asl::ABSOLUTE_X_INDEXED => asl::interpret(AbsoluteXIndexed, self, memory),
101 opcode::asl::ACCUMULATOR => asl::interpret_acc(self),
102 opcode::asl::ZERO_PAGE => asl::interpret(ZeroPage, self, memory),
103 opcode::asl::ZERO_PAGE_X_INDEXED => asl::interpret(ZeroPageXIndexed, self, memory),
104 opcode::axs::unofficial0::IMMEDIATE => axs::interpret(self, memory),
105 opcode::bcc::RELATIVE => bcc::interpret(self, memory),
106 opcode::bcs::RELATIVE => bcs::interpret(self, memory),
107 opcode::beq::RELATIVE => beq::interpret(self, memory),
108 opcode::bmi::RELATIVE => bmi::interpret(self, memory),
109 opcode::bne::RELATIVE => bne::interpret(self, memory),
110 opcode::bpl::RELATIVE => bpl::interpret(self, memory),
111 opcode::bvc::RELATIVE => bvc::interpret(self, memory),
112 opcode::bvs::RELATIVE => bvs::interpret(self, memory),
113 opcode::bit::ABSOLUTE => bit::interpret(Absolute, self, memory),
114 opcode::bit::ZERO_PAGE => bit::interpret(ZeroPage, self, memory),
115 opcode::brk::IMPLIED => brk::interpret(self, memory),
116 opcode::clc::IMPLIED => clc::interpret(self),
117 opcode::cld::IMPLIED => cld::interpret(self),
118 opcode::cli::IMPLIED => cli::interpret(self),
119 opcode::clv::IMPLIED => clv::interpret(self),
120 opcode::cmp::ABSOLUTE => cmp::interpret(Absolute, self, memory),
121 opcode::cmp::ABSOLUTE_X_INDEXED => cmp::interpret(AbsoluteXIndexed, self, memory),
122 opcode::cmp::ABSOLUTE_Y_INDEXED => cmp::interpret(AbsoluteYIndexed, self, memory),
123 opcode::cmp::IMMEDIATE => cmp::interpret(Immediate, self, memory),
124 opcode::cmp::INDIRECT_Y_INDEXED => cmp::interpret(IndirectYIndexed, self, memory),
125 opcode::cmp::X_INDEXED_INDIRECT => cmp::interpret(XIndexedIndirect, self, memory),
126 opcode::cmp::ZERO_PAGE => cmp::interpret(ZeroPage, self, memory),
127 opcode::cmp::ZERO_PAGE_X_INDEXED => cmp::interpret(ZeroPageXIndexed, self, memory),
128 opcode::cpx::ABSOLUTE => cpx::interpret(Absolute, self, memory),
129 opcode::cpx::IMMEDIATE => cpx::interpret(Immediate, self, memory),
130 opcode::cpx::ZERO_PAGE => cpx::interpret(ZeroPage, self, memory),
131 opcode::cpy::ABSOLUTE => cpy::interpret(Absolute, self, memory),
132 opcode::cpy::IMMEDIATE => cpy::interpret(Immediate, self, memory),
133 opcode::cpy::ZERO_PAGE => cpy::interpret(ZeroPage, self, memory),
134 opcode::dcp::unofficial0::X_INDEXED_INDIRECT => {
135 dcp::interpret(XIndexedIndirect, self, memory)
136 }
137 opcode::dcp::unofficial0::ZERO_PAGE => dcp::interpret(ZeroPage, self, memory),
138 opcode::dcp::unofficial0::ABSOLUTE => dcp::interpret(Absolute, self, memory),
139 opcode::dcp::unofficial0::INDIRECT_Y_INDEXED => {
140 dcp::interpret(IndirectYIndexed, self, memory)
141 }
142 opcode::dcp::unofficial0::ZERO_PAGE_X_INDEXED => {
143 dcp::interpret(ZeroPageXIndexed, self, memory)
144 }
145 opcode::dcp::unofficial0::ABSOLUTE_X_INDEXED => {
146 dcp::interpret(AbsoluteXIndexed, self, memory)
147 }
148 opcode::dcp::unofficial0::ABSOLUTE_Y_INDEXED => {
149 dcp::interpret(AbsoluteYIndexed, self, memory)
150 }
151 opcode::dec::ABSOLUTE => dec::interpret(Absolute, self, memory),
152 opcode::dec::ABSOLUTE_X_INDEXED => dec::interpret(AbsoluteXIndexed, self, memory),
153 opcode::dec::ZERO_PAGE => dec::interpret(ZeroPage, self, memory),
154 opcode::dec::ZERO_PAGE_X_INDEXED => dec::interpret(ZeroPageXIndexed, self, memory),
155 opcode::dex::IMPLIED => dex::interpret(self),
156 opcode::dey::IMPLIED => dey::interpret(self),
157 opcode::eor::ABSOLUTE => eor::interpret(Absolute, self, memory),
158 opcode::eor::ABSOLUTE_X_INDEXED => eor::interpret(AbsoluteXIndexed, self, memory),
159 opcode::eor::ABSOLUTE_Y_INDEXED => eor::interpret(AbsoluteYIndexed, self, memory),
160 opcode::eor::IMMEDIATE => eor::interpret(Immediate, self, memory),
161 opcode::eor::INDIRECT_Y_INDEXED => eor::interpret(IndirectYIndexed, self, memory),
162 opcode::eor::X_INDEXED_INDIRECT => eor::interpret(XIndexedIndirect, self, memory),
163 opcode::eor::ZERO_PAGE => eor::interpret(ZeroPage, self, memory),
164 opcode::eor::ZERO_PAGE_X_INDEXED => eor::interpret(ZeroPageXIndexed, self, memory),
165 opcode::ign::unofficial0::ABSOLUTE => ign::interpret(Absolute, self, memory),
166 opcode::ign::unofficial0::ABSOLUTE_X_INDEXED => {
167 ign::interpret(AbsoluteXIndexed, self, memory)
168 }
169 opcode::ign::unofficial0::ZERO_PAGE => ign::interpret(ZeroPage, self, memory),
170 opcode::ign::unofficial0::ZERO_PAGE_X_INDEXED => {
171 ign::interpret(ZeroPageXIndexed, self, memory)
172 }
173 opcode::ign::unofficial1::ABSOLUTE_X_INDEXED => {
174 ign::interpret(AbsoluteXIndexed, self, memory)
175 }
176 opcode::ign::unofficial1::ZERO_PAGE => ign::interpret(ZeroPage, self, memory),
177 opcode::ign::unofficial1::ZERO_PAGE_X_INDEXED => {
178 ign::interpret(ZeroPageXIndexed, self, memory)
179 }
180 opcode::ign::unofficial2::ABSOLUTE_X_INDEXED => {
181 ign::interpret(AbsoluteXIndexed, self, memory)
182 }
183 opcode::ign::unofficial2::ZERO_PAGE => ign::interpret(ZeroPage, self, memory),
184 opcode::ign::unofficial2::ZERO_PAGE_X_INDEXED => {
185 ign::interpret(ZeroPageXIndexed, self, memory)
186 }
187 opcode::ign::unofficial3::ABSOLUTE_X_INDEXED => {
188 ign::interpret(AbsoluteXIndexed, self, memory)
189 }
190 opcode::ign::unofficial3::ZERO_PAGE_X_INDEXED => {
191 ign::interpret(ZeroPageXIndexed, self, memory)
192 }
193 opcode::ign::unofficial4::ABSOLUTE_X_INDEXED => {
194 ign::interpret(AbsoluteXIndexed, self, memory)
195 }
196 opcode::ign::unofficial4::ZERO_PAGE_X_INDEXED => {
197 ign::interpret(ZeroPageXIndexed, self, memory)
198 }
199 opcode::ign::unofficial5::ABSOLUTE_X_INDEXED => {
200 ign::interpret(AbsoluteXIndexed, self, memory)
201 }
202 opcode::ign::unofficial5::ZERO_PAGE_X_INDEXED => {
203 ign::interpret(ZeroPageXIndexed, self, memory)
204 }
205 opcode::inc::ABSOLUTE => inc::interpret(Absolute, self, memory),
206 opcode::inc::ABSOLUTE_X_INDEXED => inc::interpret(AbsoluteXIndexed, self, memory),
207 opcode::inc::ZERO_PAGE => inc::interpret(ZeroPage, self, memory),
208 opcode::inc::ZERO_PAGE_X_INDEXED => inc::interpret(ZeroPageXIndexed, self, memory),
209 opcode::inx::IMPLIED => inx::interpret(self),
210 opcode::iny::IMPLIED => iny::interpret(self),
211 opcode::isc::unofficial0::X_INDEXED_INDIRECT => {
212 isc::interpret(XIndexedIndirect, self, memory)
213 }
214 opcode::isc::unofficial0::ZERO_PAGE => isc::interpret(ZeroPage, self, memory),
215 opcode::isc::unofficial0::ABSOLUTE => isc::interpret(Absolute, self, memory),
216 opcode::isc::unofficial0::INDIRECT_Y_INDEXED => {
217 isc::interpret(IndirectYIndexed, self, memory)
218 }
219 opcode::isc::unofficial0::ZERO_PAGE_X_INDEXED => {
220 isc::interpret(ZeroPageXIndexed, self, memory)
221 }
222 opcode::isc::unofficial0::ABSOLUTE_X_INDEXED => {
223 isc::interpret(AbsoluteXIndexed, self, memory)
224 }
225 opcode::isc::unofficial0::ABSOLUTE_Y_INDEXED => {
226 isc::interpret(AbsoluteYIndexed, self, memory)
227 }
228 opcode::jmp::ABSOLUTE => jmp::interpret(Absolute, self, memory),
229 opcode::jmp::INDIRECT => jmp::interpret(Indirect, self, memory),
230 opcode::jsr::ABSOLUTE => jsr::interpret(Absolute, self, memory),
231 opcode::lax::unofficial0::ABSOLUTE => lax::interpret(Absolute, self, memory),
232 opcode::lax::unofficial0::ABSOLUTE_Y_INDEXED => {
233 lax::interpret(AbsoluteYIndexed, self, memory)
234 }
235 opcode::lax::unofficial0::IMMEDIATE => lax::interpret(Immediate, self, memory),
236 opcode::lax::unofficial0::X_INDEXED_INDIRECT => {
237 lax::interpret(XIndexedIndirect, self, memory)
238 }
239 opcode::lax::unofficial0::INDIRECT_Y_INDEXED => {
240 lax::interpret(IndirectYIndexed, self, memory)
241 }
242 opcode::lax::unofficial0::ZERO_PAGE => lax::interpret(ZeroPage, self, memory),
243 opcode::lax::unofficial0::ZERO_PAGE_Y_INDEXED => {
244 lax::interpret(ZeroPageYIndexed, self, memory)
245 }
246 opcode::lda::ABSOLUTE => lda::interpret(Absolute, self, memory),
247 opcode::lda::ABSOLUTE_X_INDEXED => lda::interpret(AbsoluteXIndexed, self, memory),
248 opcode::lda::ABSOLUTE_Y_INDEXED => lda::interpret(AbsoluteYIndexed, self, memory),
249 opcode::lda::IMMEDIATE => lda::interpret(Immediate, self, memory),
250 opcode::lda::INDIRECT_Y_INDEXED => lda::interpret(IndirectYIndexed, self, memory),
251 opcode::lda::X_INDEXED_INDIRECT => lda::interpret(XIndexedIndirect, self, memory),
252 opcode::lda::ZERO_PAGE => lda::interpret(ZeroPage, self, memory),
253 opcode::lda::ZERO_PAGE_X_INDEXED => lda::interpret(ZeroPageXIndexed, self, memory),
254 opcode::ldx::ABSOLUTE => ldx::interpret(Absolute, self, memory),
255 opcode::ldx::ABSOLUTE_Y_INDEXED => ldx::interpret(AbsoluteYIndexed, self, memory),
256 opcode::ldx::IMMEDIATE => ldx::interpret(Immediate, self, memory),
257 opcode::ldx::ZERO_PAGE => ldx::interpret(ZeroPage, self, memory),
258 opcode::ldx::ZERO_PAGE_Y_INDEXED => ldx::interpret(ZeroPageYIndexed, self, memory),
259 opcode::ldy::ABSOLUTE => ldy::interpret(Absolute, self, memory),
260 opcode::ldy::ABSOLUTE_X_INDEXED => ldy::interpret(AbsoluteXIndexed, self, memory),
261 opcode::ldy::IMMEDIATE => ldy::interpret(Immediate, self, memory),
262 opcode::ldy::ZERO_PAGE => ldy::interpret(ZeroPage, self, memory),
263 opcode::ldy::ZERO_PAGE_X_INDEXED => ldy::interpret(ZeroPageXIndexed, self, memory),
264 opcode::lsr::ABSOLUTE => lsr::interpret(Absolute, self, memory),
265 opcode::lsr::ABSOLUTE_X_INDEXED => lsr::interpret(AbsoluteXIndexed, self, memory),
266 opcode::lsr::ACCUMULATOR => lsr::interpret_acc(self),
267 opcode::lsr::ZERO_PAGE => lsr::interpret(ZeroPage, self, memory),
268 opcode::lsr::ZERO_PAGE_X_INDEXED => lsr::interpret(ZeroPageXIndexed, self, memory),
269 opcode::nop::IMPLIED => nop::interpret(self),
270 opcode::nop::unofficial0::IMPLIED => nop::interpret(self),
271 opcode::nop::unofficial1::IMPLIED => nop::interpret(self),
272 opcode::nop::unofficial2::IMPLIED => nop::interpret(self),
273 opcode::nop::unofficial3::IMPLIED => nop::interpret(self),
274 opcode::nop::unofficial4::IMPLIED => nop::interpret(self),
275 opcode::nop::unofficial5::IMPLIED => nop::interpret(self),
276 opcode::ora::ABSOLUTE => ora::interpret(Absolute, self, memory),
277 opcode::ora::ABSOLUTE_X_INDEXED => ora::interpret(AbsoluteXIndexed, self, memory),
278 opcode::ora::ABSOLUTE_Y_INDEXED => ora::interpret(AbsoluteYIndexed, self, memory),
279 opcode::ora::IMMEDIATE => ora::interpret(Immediate, self, memory),
280 opcode::ora::INDIRECT_Y_INDEXED => ora::interpret(IndirectYIndexed, self, memory),
281 opcode::ora::X_INDEXED_INDIRECT => ora::interpret(XIndexedIndirect, self, memory),
282 opcode::ora::ZERO_PAGE => ora::interpret(ZeroPage, self, memory),
283 opcode::ora::ZERO_PAGE_X_INDEXED => ora::interpret(ZeroPageXIndexed, self, memory),
284 opcode::pha::IMPLIED => pha::interpret(self, memory),
285 opcode::php::IMPLIED => php::interpret(self, memory),
286 opcode::pla::IMPLIED => pla::interpret(self, memory),
287 opcode::plp::IMPLIED => plp::interpret(self, memory),
288 opcode::rla::unofficial0::X_INDEXED_INDIRECT => {
289 rla::interpret(XIndexedIndirect, self, memory)
290 }
291 opcode::rla::unofficial0::ZERO_PAGE => rla::interpret(ZeroPage, self, memory),
292 opcode::rla::unofficial0::ABSOLUTE => rla::interpret(Absolute, self, memory),
293 opcode::rla::unofficial0::INDIRECT_Y_INDEXED => {
294 rla::interpret(IndirectYIndexed, self, memory)
295 }
296 opcode::rla::unofficial0::ZERO_PAGE_X_INDEXED => {
297 rla::interpret(ZeroPageXIndexed, self, memory)
298 }
299 opcode::rla::unofficial0::ABSOLUTE_X_INDEXED => {
300 rla::interpret(AbsoluteXIndexed, self, memory)
301 }
302 opcode::rla::unofficial0::ABSOLUTE_Y_INDEXED => {
303 rla::interpret(AbsoluteYIndexed, self, memory)
304 }
305 opcode::rol::ABSOLUTE => rol::interpret(Absolute, self, memory),
306 opcode::rol::ABSOLUTE_X_INDEXED => rol::interpret(AbsoluteXIndexed, self, memory),
307 opcode::rol::ACCUMULATOR => rol::interpret_acc(self),
308 opcode::rol::ZERO_PAGE => rol::interpret(ZeroPage, self, memory),
309 opcode::rol::ZERO_PAGE_X_INDEXED => rol::interpret(ZeroPageXIndexed, self, memory),
310 opcode::ror::ABSOLUTE => ror::interpret(Absolute, self, memory),
311 opcode::ror::ABSOLUTE_X_INDEXED => ror::interpret(AbsoluteXIndexed, self, memory),
312 opcode::ror::ACCUMULATOR => ror::interpret_acc(self),
313 opcode::ror::ZERO_PAGE => ror::interpret(ZeroPage, self, memory),
314 opcode::ror::ZERO_PAGE_X_INDEXED => ror::interpret(ZeroPageXIndexed, self, memory),
315 opcode::rra::unofficial0::X_INDEXED_INDIRECT => {
316 rra::interpret(XIndexedIndirect, self, memory)
317 }
318 opcode::rra::unofficial0::ZERO_PAGE => rra::interpret(ZeroPage, self, memory),
319 opcode::rra::unofficial0::ABSOLUTE => rra::interpret(Absolute, self, memory),
320 opcode::rra::unofficial0::INDIRECT_Y_INDEXED => {
321 rra::interpret(IndirectYIndexed, self, memory)
322 }
323 opcode::rra::unofficial0::ZERO_PAGE_X_INDEXED => {
324 rra::interpret(ZeroPageXIndexed, self, memory)
325 }
326 opcode::rra::unofficial0::ABSOLUTE_X_INDEXED => {
327 rra::interpret(AbsoluteXIndexed, self, memory)
328 }
329 opcode::rra::unofficial0::ABSOLUTE_Y_INDEXED => {
330 rra::interpret(AbsoluteYIndexed, self, memory)
331 }
332 opcode::rti::IMPLIED => rti::interpret(self, memory),
333 opcode::rts::IMPLIED => rts::interpret(self, memory),
334 opcode::sax::unofficial0::X_INDEXED_INDIRECT => {
335 sax::interpret(XIndexedIndirect, self, memory)
336 }
337 opcode::sax::unofficial0::ZERO_PAGE => sax::interpret(ZeroPage, self, memory),
338 opcode::sax::unofficial0::ABSOLUTE => sax::interpret(Absolute, self, memory),
339 opcode::sax::unofficial0::ZERO_PAGE_Y_INDEXED => {
340 sax::interpret(ZeroPageYIndexed, self, memory)
341 }
342 opcode::sbc::ABSOLUTE => sbc::interpret(Absolute, self, memory),
343 opcode::sbc::ABSOLUTE_X_INDEXED => sbc::interpret(AbsoluteXIndexed, self, memory),
344 opcode::sbc::ABSOLUTE_Y_INDEXED => sbc::interpret(AbsoluteYIndexed, self, memory),
345 opcode::sbc::IMMEDIATE => sbc::interpret(Immediate, self, memory),
346 opcode::sbc::INDIRECT_Y_INDEXED => sbc::interpret(IndirectYIndexed, self, memory),
347 opcode::sbc::X_INDEXED_INDIRECT => sbc::interpret(XIndexedIndirect, self, memory),
348 opcode::sbc::ZERO_PAGE => sbc::interpret(ZeroPage, self, memory),
349 opcode::sbc::ZERO_PAGE_X_INDEXED => sbc::interpret(ZeroPageXIndexed, self, memory),
350 opcode::sbc::unofficial0::IMMEDIATE => sbc::interpret(Immediate, self, memory),
351 opcode::sec::IMPLIED => sec::interpret(self),
352 opcode::sed::IMPLIED => sed::interpret(self),
353 opcode::sei::IMPLIED => sei::interpret(self),
354 opcode::skb::unofficial0::IMMEDIATE => skb::interpret(self, memory),
355 opcode::skb::unofficial1::IMMEDIATE => skb::interpret(self, memory),
356 opcode::skb::unofficial2::IMMEDIATE => skb::interpret(self, memory),
357 opcode::skb::unofficial3::IMMEDIATE => skb::interpret(self, memory),
358 opcode::skb::unofficial4::IMMEDIATE => skb::interpret(self, memory),
359 opcode::slo::unofficial0::X_INDEXED_INDIRECT => {
360 slo::interpret(XIndexedIndirect, self, memory)
361 }
362 opcode::slo::unofficial0::ZERO_PAGE => slo::interpret(ZeroPage, self, memory),
363 opcode::slo::unofficial0::ABSOLUTE => slo::interpret(Absolute, self, memory),
364 opcode::slo::unofficial0::INDIRECT_Y_INDEXED => {
365 slo::interpret(IndirectYIndexed, self, memory)
366 }
367 opcode::slo::unofficial0::ZERO_PAGE_X_INDEXED => {
368 slo::interpret(ZeroPageXIndexed, self, memory)
369 }
370 opcode::slo::unofficial0::ABSOLUTE_X_INDEXED => {
371 slo::interpret(AbsoluteXIndexed, self, memory)
372 }
373 opcode::slo::unofficial0::ABSOLUTE_Y_INDEXED => {
374 slo::interpret(AbsoluteYIndexed, self, memory)
375 }
376 opcode::sre::unofficial0::X_INDEXED_INDIRECT => {
377 sre::interpret(XIndexedIndirect, self, memory)
378 }
379 opcode::sre::unofficial0::ZERO_PAGE => sre::interpret(ZeroPage, self, memory),
380 opcode::sre::unofficial0::ABSOLUTE => sre::interpret(Absolute, self, memory),
381 opcode::sre::unofficial0::INDIRECT_Y_INDEXED => {
382 sre::interpret(IndirectYIndexed, self, memory)
383 }
384 opcode::sre::unofficial0::ZERO_PAGE_X_INDEXED => {
385 sre::interpret(ZeroPageXIndexed, self, memory)
386 }
387 opcode::sre::unofficial0::ABSOLUTE_X_INDEXED => {
388 sre::interpret(AbsoluteXIndexed, self, memory)
389 }
390 opcode::sre::unofficial0::ABSOLUTE_Y_INDEXED => {
391 sre::interpret(AbsoluteYIndexed, self, memory)
392 }
393 opcode::sta::ABSOLUTE => sta::interpret(Absolute, self, memory),
394 opcode::sta::ABSOLUTE_X_INDEXED => sta::interpret(AbsoluteXIndexed, self, memory),
395 opcode::sta::ABSOLUTE_Y_INDEXED => sta::interpret(AbsoluteYIndexed, self, memory),
396 opcode::sta::INDIRECT_Y_INDEXED => sta::interpret(IndirectYIndexed, self, memory),
397 opcode::sta::X_INDEXED_INDIRECT => sta::interpret(XIndexedIndirect, self, memory),
398 opcode::sta::ZERO_PAGE => sta::interpret(ZeroPage, self, memory),
399 opcode::sta::ZERO_PAGE_X_INDEXED => sta::interpret(ZeroPageXIndexed, self, memory),
400 opcode::stx::ABSOLUTE => stx::interpret(Absolute, self, memory),
401 opcode::stx::ZERO_PAGE => stx::interpret(ZeroPage, self, memory),
402 opcode::stx::ZERO_PAGE_Y_INDEXED => stx::interpret(ZeroPageYIndexed, self, memory),
403 opcode::sty::ABSOLUTE => sty::interpret(Absolute, self, memory),
404 opcode::sty::ZERO_PAGE => sty::interpret(ZeroPage, self, memory),
405 opcode::sty::ZERO_PAGE_X_INDEXED => sty::interpret(ZeroPageXIndexed, self, memory),
406 opcode::sxa::unofficial0::ABSOLUTE_Y_INDEXED => sxa::interpret(self, memory),
407 opcode::sya::unofficial0::ABSOLUTE_X_INDEXED => sya::interpret(self, memory),
408 opcode::tax::IMPLIED => tax::interpret(self),
409 opcode::tay::IMPLIED => tay::interpret(self),
410 opcode::tsx::IMPLIED => tsx::interpret(self),
411 opcode::txa::IMPLIED => txa::interpret(self),
412 opcode::txs::IMPLIED => txs::interpret(self),
413 opcode::tya::IMPLIED => tya::interpret(self),
414 _ => return Err(UnknownOpcode(opcode)),
415 };
416 Ok(cycles)
417 }
418}
419
420const STACK_ADDRESS_HI: u8 = 0x01;
421pub trait Memory {
422 fn read_u8(&mut self, address: Address) -> u8;
423 fn read_u16_le(&mut self, address: Address) -> u16 {
424 let lo = self.read_u8(address);
425 let hi = self.read_u8(address.wrapping_add(1));
426 ((hi as u16) << 8) | lo as u16
427 }
428 fn read_u8_zero_page(&mut self, address: u8) -> u8 {
429 self.read_u8(address as Address)
430 }
431 fn read_u16_le_zero_page(&mut self, address: u8) -> u16 {
432 let lo = self.read_u8_zero_page(address);
433 let hi = self.read_u8_zero_page(address.wrapping_add(1));
434 ((hi as u16) << 8) | lo as u16
435 }
436 fn read_u8_stack(&mut self, stack_pointer: u8) -> u8 {
437 self.read_u8(address::from_u8_lo_hi(stack_pointer, STACK_ADDRESS_HI))
438 }
439 fn write_u8(&mut self, address: Address, data: u8);
440 fn write_u8_zero_page(&mut self, address: u8, data: u8) {
441 self.write_u8(address as Address, data);
442 }
443 fn write_u8_stack(&mut self, stack_pointer: u8, data: u8) {
444 self.write_u8(
445 address::from_u8_lo_hi(stack_pointer, STACK_ADDRESS_HI),
446 data,
447 );
448 }
449}
450
451pub trait MemoryReadOnly {
453 fn read_u8_read_only(&self, address: Address) -> u8;
454 fn read_u16_le_read_only(&self, address: Address) -> u16 {
455 let lo = self.read_u8_read_only(address);
456 let hi = self.read_u8_read_only(address + 1);
457 ((hi as u16) << 8) | lo as u16
458 }
459 fn read_u8_stack_read_only(&self, stack_pointer: u8) -> u8 {
460 self.read_u8_read_only(address::from_u8_lo_hi(stack_pointer, STACK_ADDRESS_HI))
461 }
462}
463
464pub use status::Register as StatusRegister;