package cpu const ( vectorNMI uint16 = 0xFFFA vectorReset uint16 = 0xFFFC vectorIRQ uint16 = 0xFFFE stackBase uint16 = 0x0100 ) type CPU struct { A, X, Y uint8 SP uint8 // stack pointer PC uint16 // program counter Status uint8 // status flags Bus Bus Cycles uint64 extraCycles int } func NewCPU(bus Bus) *CPU { return &CPU{Bus: bus} } func (c *CPU) read(addr uint16) uint8 { return c.Bus.Read(addr) } func (c *CPU) write(addr uint16, v uint8) { c.Bus.Write(addr, v) } func (c *CPU) read16(addr uint16) uint16 { lo := uint16(c.read(addr)) hi := uint16(c.read(addr + 1)) return hi<<8 | lo } func (c *CPU) push(v uint8) { c.write(stackBase+uint16(c.SP), v) c.SP-- } func (c *CPU) pop() uint8 { c.SP++ return c.read(stackBase + uint16(c.SP)) } func (c *CPU) push16(v uint16) { c.push(uint8(v >> 8)) c.push(uint8(v)) } func (c *CPU) pop16() uint16 { lo := uint16(c.pop()) hi := uint16(c.pop()) return hi<<8 | lo } func (c *CPU) Reset() { c.A, c.X, c.Y = 0, 0, 0 c.SP = 0xFD c.Status = FlagU | FlagI c.PC = c.read16(vectorReset) c.Cycles = 7 } func (c *CPU) IRQ() { if c.flag(FlagI) { return } c.interrupt(vectorIRQ, false) c.Cycles += 7 } func (c *CPU) NMI() { c.interrupt(vectorNMI, false) c.Cycles += 7 } func (c *CPU) interrupt(vector uint16, brk bool) { c.push16(c.PC) status := c.Status | FlagU if brk { status |= FlagB } else { status &^= FlagB } c.push(status) c.setFlag(FlagI, true) c.PC = c.read16(vector) } func (c *CPU) Step() int { before := c.Cycles opcode := c.read(c.PC) c.PC++ entry := opcodeTable[opcode] op := c.resolveOperand(entry.mode) c.extraCycles = 0 entry.exec(c, op) cycles := entry.cycles if entry.pageCrossPenalty && op.pageCrossed { cycles++ } cycles += c.extraCycles c.Cycles += uint64(cycles) return int(c.Cycles - before) }