use super::*; impl Cpu6502 { pub(super) fn fetch(&mut self, bus: &mut B) -> u8 { let value = bus.read(self.pc); self.pc = self.pc.wrapping_add(1); value } pub(super) fn fetch_u16(&mut self, bus: &mut B) -> u16 { let lo = self.fetch(bus) as u16; let hi = self.fetch(bus) as u16; (hi << 8) | lo } pub(super) fn read_u16(&mut self, bus: &mut B, addr: u16) -> u16 { let lo = bus.read(addr) as u16; let hi = bus.read(addr.wrapping_add(1)) as u16; (hi << 8) | lo } pub(super) fn read_u16_bug(&mut self, bus: &mut B, addr: u16) -> u16 { let lo = bus.read(addr) as u16; let hi_addr = (addr & 0xFF00) | (addr.wrapping_add(1) & 0x00FF); let hi = bus.read(hi_addr) as u16; (hi << 8) | lo } pub(super) fn addr_zp(&mut self, bus: &mut B) -> u16 { self.fetch(bus) as u16 } pub(super) fn addr_zpx(&mut self, bus: &mut B) -> u16 { self.fetch(bus).wrapping_add(self.x) as u16 } pub(super) fn addr_zpy(&mut self, bus: &mut B) -> u16 { self.fetch(bus).wrapping_add(self.y) as u16 } pub(super) fn addr_abs(&mut self, bus: &mut B) -> u16 { self.fetch_u16(bus) } pub(super) fn addr_abx(&mut self, bus: &mut B) -> u16 { self.addr_abx_cross(bus).0 } pub(super) fn addr_aby(&mut self, bus: &mut B) -> u16 { self.addr_aby_cross(bus).0 } pub(super) fn addr_indx(&mut self, bus: &mut B) -> u16 { let ptr = self.fetch(bus).wrapping_add(self.x); let lo = bus.read(ptr as u16) as u16; let hi = bus.read(ptr.wrapping_add(1) as u16) as u16; (hi << 8) | lo } pub(super) fn addr_indy(&mut self, bus: &mut B) -> u16 { self.addr_indy_cross(bus).0 } pub(super) fn addr_abx_cross(&mut self, bus: &mut B) -> (u16, bool) { let base = self.fetch_u16(bus); let addr = base.wrapping_add(self.x as u16); (addr, (base & 0xFF00) != (addr & 0xFF00)) } pub(super) fn addr_aby_cross(&mut self, bus: &mut B) -> (u16, bool) { let base = self.fetch_u16(bus); let addr = base.wrapping_add(self.y as u16); (addr, (base & 0xFF00) != (addr & 0xFF00)) } pub(super) fn addr_indy_cross(&mut self, bus: &mut B) -> (u16, bool) { let ptr = self.fetch(bus); let lo = bus.read(ptr as u16) as u16; let hi = bus.read(ptr.wrapping_add(1) as u16) as u16; let base = (hi << 8) | lo; let addr = base.wrapping_add(self.y as u16); (addr, (base & 0xFF00) != (addr & 0xFF00)) } pub(super) fn read_zp(&mut self, bus: &mut B) -> u8 { let addr = self.addr_zp(bus); bus.read(addr) } pub(super) fn read_zpx(&mut self, bus: &mut B) -> u8 { let addr = self.addr_zpx(bus); bus.read(addr) } pub(super) fn read_zpy(&mut self, bus: &mut B) -> u8 { let addr = self.addr_zpy(bus); bus.read(addr) } pub(super) fn read_abs(&mut self, bus: &mut B) -> u8 { let addr = self.addr_abs(bus); bus.read(addr) } pub(super) fn read_abx_cross(&mut self, bus: &mut B) -> (u8, bool) { let (addr, crossed) = self.addr_abx_cross(bus); (bus.read(addr), crossed) } pub(super) fn read_aby_cross(&mut self, bus: &mut B) -> (u8, bool) { let (addr, crossed) = self.addr_aby_cross(bus); (bus.read(addr), crossed) } pub(super) fn read_indx(&mut self, bus: &mut B) -> u8 { let addr = self.addr_indx(bus); bus.read(addr) } pub(super) fn read_indy_cross(&mut self, bus: &mut B) -> (u8, bool) { let (addr, crossed) = self.addr_indy_cross(bus); (bus.read(addr), crossed) } pub(super) fn push(&mut self, bus: &mut B, value: u8) { let addr = 0x0100 | self.sp as u16; bus.write(addr, value); self.sp = self.sp.wrapping_sub(1); } pub(super) fn pop(&mut self, bus: &mut B) -> u8 { self.sp = self.sp.wrapping_add(1); let addr = 0x0100 | self.sp as u16; bus.read(addr) } pub(super) fn set_zn(&mut self, value: u8) { if value == 0 { self.p |= FLAG_ZERO; } else { self.p &= !FLAG_ZERO; } if (value & 0x80) != 0 { self.p |= FLAG_NEGATIVE; } else { self.p &= !FLAG_NEGATIVE; } } pub(super) fn set_flag(&mut self, mask: u8, enabled: bool) { if enabled { self.p |= mask; } else { self.p &= !mask; } } pub(super) fn compare(&mut self, lhs: u8, rhs: u8) { let result = lhs.wrapping_sub(rhs); self.set_flag(FLAG_CARRY, lhs >= rhs); self.set_zn(result); } pub(super) fn bit(&mut self, value: u8) { self.set_flag(FLAG_ZERO, (self.a & value) == 0); self.set_flag(FLAG_OVERFLOW, (value & 0x40) != 0); self.set_flag(FLAG_NEGATIVE, (value & 0x80) != 0); } pub(super) fn adc(&mut self, value: u8) { let carry = u16::from((self.p & FLAG_CARRY) != 0); let a = self.a as u16; let b = value as u16; let sum = a + b + carry; let result = sum as u8; self.set_flag(FLAG_CARRY, sum > 0xFF); let overflow = ((self.a ^ result) & (value ^ result) & 0x80) != 0; self.set_flag(FLAG_OVERFLOW, overflow); self.a = result; self.set_zn(self.a); } pub(super) fn asl(&mut self, value: u8) -> u8 { self.set_flag(FLAG_CARRY, (value & 0x80) != 0); let out = value << 1; self.set_zn(out); out } pub(super) fn lsr(&mut self, value: u8) -> u8 { self.set_flag(FLAG_CARRY, (value & 0x01) != 0); let out = value >> 1; self.set_zn(out); out } pub(super) fn rol(&mut self, value: u8) -> u8 { let carry_in = u8::from((self.p & FLAG_CARRY) != 0); self.set_flag(FLAG_CARRY, (value & 0x80) != 0); let out = (value << 1) | carry_in; self.set_zn(out); out } pub(super) fn ror(&mut self, value: u8) -> u8 { let carry_in = if (self.p & FLAG_CARRY) != 0 { 0x80 } else { 0 }; self.set_flag(FLAG_CARRY, (value & 0x01) != 0); let out = (value >> 1) | carry_in; self.set_zn(out); out } pub(super) fn branch(&mut self, bus: &mut B, condition: bool) -> u8 { let offset = self.fetch(bus) as i8; if !condition { return 2; } let old_pc = self.pc; self.pc = self.pc.wrapping_add_signed(offset as i16); if (old_pc & 0xFF00) != (self.pc & 0xFF00) { 4 } else { 3 } } pub(super) fn service_interrupt( &mut self, bus: &mut B, vector_addr: u16, break_flag: bool, ) { self.push(bus, (self.pc >> 8) as u8); self.push(bus, self.pc as u8); let mut status = (self.p | FLAG_UNUSED) & !FLAG_BREAK; if break_flag { status |= FLAG_BREAK; } self.push(bus, status); self.p = (self.p | FLAG_IRQ_DISABLE | FLAG_UNUSED) & !FLAG_BREAK; self.pc = self.read_u16(bus, vector_addr); } }