From 8a0f7736ed4583c80642d2a3f1fe6872aafff99a Mon Sep 17 00:00:00 2001 From: Adrian Conlon <98398945+AdrianConlon@users.noreply.github.com> Date: Fri, 23 Aug 2024 15:04:56 +0100 Subject: [PATCH] More W65C02 instruction implementations --- M6502/M6502Core.cs | 10 +-- M6502/W65C02.cs | 210 ++++++++++++++++++++++++++------------------- 2 files changed, 129 insertions(+), 91 deletions(-) diff --git a/M6502/M6502Core.cs b/M6502/M6502Core.cs index 1fdfb82..a4542c7 100644 --- a/M6502/M6502Core.cs +++ b/M6502/M6502Core.cs @@ -394,7 +394,7 @@ namespace EightBit case 0x40: this.SwallowRead(); this.RTI(); break; // RTI (implied) case 0x41: this.IndexedIndirectXRead(); this.EorR(); break; // EOR (indexed indirect X) - case 0x44: this.ZeroPageRead(); break; // *NOP (zero page) + case 0x44: this.ZeroPageRead(); break; // *NOP (zero page) case 0x45: this.ZeroPageRead(); this.EorR(); break; // EOR (zero page) case 0x46: this.ZeroPageRead(); this.ModifyWrite(this.LSR()); break; // LSR (zero page) case 0x48: this.SwallowRead(); this.Push(this.A); break; // PHA (implied) @@ -813,11 +813,11 @@ namespace EightBit #region Branching - private void BranchNot(int condition) => this.Branch(condition == 0); + protected void BranchNot(int condition) => this.Branch(condition == 0); - private void Branch(int condition) => this.Branch(condition != 0); + protected void Branch(int condition) => this.Branch(condition != 0); - private void Branch(bool condition) + protected void Branch(bool condition) { this.ImmediateRead(); if (condition) @@ -984,7 +984,7 @@ namespace EightBit protected void EorR() => this.A = this.Through(this.A ^ this.Bus.Data); - private void BIT() + protected void BIT() { var data = this.Bus.Data; this.SetFlag(StatusBits.VF, OverflowTest(data)); diff --git a/M6502/W65C02.cs b/M6502/W65C02.cs index d2a4f9c..e5001be 100644 --- a/M6502/W65C02.cs +++ b/M6502/W65C02.cs @@ -43,119 +43,119 @@ namespace EightBit var cycles = this.Cycles; switch (this.OpCode) { - case 0x02: this.SwallowFetch(); break; // *NOP - case 0x03: break; // null - case 0x04: break; // TSB zp - case 0x07: break; // RMB0 zp - case 0x0b: break; // null - case 0x0c: break; // TSB a - case 0x0f: break; // BBR0 r + case 0x02: this.SwallowFetch(); break; // NOP + case 0x03: break; // null + case 0x04: this.ZeroPageRead(); this.TSB(); break; // TSB zp + case 0x07: this.ZeroPageRead(); this.RMB(Chip.Bit(0)); break; // RMB0 zp + case 0x0b: break; // null + case 0x0c: this.AbsoluteRead(); this.TSB(); break; // TSB a + case 0x0f: this.ZeroPageRead(); this.BBR(Chip.Bit(0)); break; // BBR0 r case 0x12: this.ZeroPageIndirectAddress(); this.OrR(); break; // ORA (zp),y - case 0x13: break; // null - case 0x14: break; // TRB zp - case 0x17: break; // RMB1 zp + case 0x13: break; // null + case 0x14: this.ZeroPageRead(); this.TRB(); break; // TRB zp + case 0x17: this.ZeroPageRead(); this.RMB(Chip.Bit(1)); break; // RMB1 zp case 0x1a: this.SwallowRead(); this.A = this.INC(this.A); break; // INC A - case 0x1b: break; // null - case 0x1c: break; // TRB a - case 0x1f: break; // BBR1 r + case 0x1b: break; // null + case 0x1c: this.AbsoluteRead(); this.TRB(); break; // TRB a + case 0x1f: this.ZeroPageRead(); this.BBR(Chip.Bit(1)); break; // BBR1 r - case 0x22: this.SwallowFetch(); break; // *NOP - case 0x23: break; // null - case 0x27: break; // RMB2 zp - case 0x2b: break; // null - case 0x2f: break; // BBR2 r + case 0x22: this.SwallowFetch(); break; // NOP + case 0x23: break; // null + case 0x27: this.ZeroPageRead(); this.RMB(Chip.Bit(2)); break; // RMB2 zp + case 0x2b: break; // null + case 0x2f: this.ZeroPageRead(); this.BBR(Chip.Bit(2)); break; // BBR2 r - case 0x32: this.ZeroPageIndirectRead(); this.AndR(); break; // AND (zp) - case 0x33: break; // null - case 0x34: break; // BIT zp,x - case 0x37: break; // RMB3 zp + case 0x32: this.ZeroPageIndirectRead(); this.AndR(); break; // AND (zp) + case 0x33: break; // null + case 0x34: break; // BIT zp,x + case 0x37: this.ZeroPageRead(); this.RMB(Chip.Bit(3)); break; // RMB3 zp case 0x3a: this.SwallowRead(); this.A = this.DEC(this.A); break; // DEC A - case 0x3b: break; // null - case 0x3c: break; // BIT a,x - case 0x3f: break; // BBR3 r + case 0x3b: break; // null + case 0x3c: break; // BIT a,x + case 0x3f: this.ZeroPageRead(); this.BBR(Chip.Bit(3)); break; // BBR3 r - case 0x42: this.SwallowFetch(); break; // *NOP - case 0x43: break; // null - case 0x47: break; // RMB4 zp - case 0x4b: break; // null - case 0x4f: break; // BBR4 r + case 0x42: this.SwallowFetch(); break; // NOP + case 0x43: break; // null + case 0x47: this.ZeroPageRead(); this.RMB(Chip.Bit(4)); break; // RMB4 zp + case 0x4b: break; // null + case 0x4f: this.ZeroPageRead(); this.BBR(Chip.Bit(4)); break; // BBR4 r - case 0x52: this.ZeroPageIndirectRead(); this.EorR(); break; // EOR (zp) - case 0x53: break; // null - case 0x57: break; // RMB5 zp + case 0x52: this.ZeroPageIndirectRead(); this.EorR(); break; // EOR (zp) + case 0x53: break; // null + case 0x57: this.ZeroPageRead(); this.RMB(Chip.Bit(5)); break; // RMB5 zp case 0x5a: this.SwallowRead(); this.Push(this.Y); break; // PHY s - case 0x5b: break; // null - case 0x5c: break; // null - case 0x5f: break; // BBR5 r + case 0x5b: break; // null + case 0x5c: break; // null + case 0x5f: this.ZeroPageRead(); this.BBR(Chip.Bit(5)); break; // BBR5 r case 0x62: this.SwallowFetch(); break; // *NOP - case 0x63: break; // null + case 0x63: break; // null case 0x64: this.ZeroPageAddress(); this.MemoryWrite(0); break; // STZ zp - case 0x67: break; // RMB6 zp - case 0x6b: break; // null - case 0x6f: break; // BBR6 r + case 0x67: this.ZeroPageRead(); this.RMB(Chip.Bit(6)); break; // RMB6 zp + case 0x6b: break; // null + case 0x6f: this.ZeroPageRead(); this.BBR(Chip.Bit(6)); break; // BBR6 r - case 0x72: this.ZeroPageIndirectRead(); this.ADC(); break; // ADC (zp) - case 0x73: break; // null + case 0x72: this.ZeroPageIndirectRead(); this.ADC(); break; // ADC (zp) + case 0x73: break; // null case 0x74: this.ZeroPageXAddress(); this.MemoryWrite(0); break; // STZ zp,x - case 0x77: break; // RMB7 zp + case 0x77: this.ZeroPageRead(); this.RMB(Chip.Bit(7)); break; // RMB7 zp case 0x7a: this.SwallowRead(); this.SwallowPop(); this.Y = this.Through(this.Pop()); break; // PLY s - case 0x7b: break; // null - case 0x7c: break; // JMP (a,x) - case 0x7f: break; // BBR7 r + case 0x7b: break; // null + case 0x7c: break; // JMP (a,x) + case 0x7f: this.ZeroPageRead(); this.BBR(Chip.Bit(7)); break; // BBR7 r - case 0x80: break; // BRA r - case 0x83: break; // null - case 0x87: break; // SMB0 zp - case 0x89: break; // BIT # (TBC) - case 0x8b: break; // null - case 0x8f: break; // BBS0 r + case 0x80: Branch(true); break; // BRA r + case 0x83: break; // null + case 0x87: this.ZeroPageRead(); this.SMB(Chip.Bit(0)); break; // SMB0 zp + case 0x89: break; // BIT # (TBC) + case 0x8b: break; // null + case 0x8f: this.ZeroPageRead(); this.BBS(Chip.Bit(0)); break; // BBS0 r - case 0x92: ZeroPageIndirectAddress(); this.MemoryWrite(this.A); break; // STA (zp) - case 0x93: break; // null - case 0x97: break; // SMB1 zp - case 0x9b: break; // null + case 0x92: ZeroPageIndirectAddress(); this.MemoryWrite(this.A); break; // STA (zp) + case 0x93: break; // null + case 0x97: this.ZeroPageRead(); this.SMB(Chip.Bit(1)); break; // SMB1 zp + case 0x9b: break; // null case 0x9c: this.AbsoluteAddress(); this.MemoryWrite(0); break; // STZ a case 0x9e: this.AbsoluteXAddress(); this.MemoryWrite(0); break; // STZ a,x - case 0x9f: break; // BBS1 r + case 0x9f: this.ZeroPageRead(); this.BBS(Chip.Bit(1)); break; // BBS1 r - case 0xa3: break; // null - case 0xa7: break; // SMB2 zp - case 0xab: break; // null - case 0xaf: break; // BBS2 r + case 0xa3: break; // null + case 0xa7: this.ZeroPageRead(); this.SMB(Chip.Bit(2)); break; // SMB2 zp + case 0xab: break; // null + case 0xaf: this.ZeroPageRead(); this.BBS(Chip.Bit(2)); break; // BBS2 r - case 0xb2: ZeroPageIndirectRead(); this.A = this.Through(); break; // LDA (zp) - case 0xb3: break; // null - case 0xb7: break; // SMB3 zp - case 0xbb: break; // null - case 0xbf: break; // BBS3 r + case 0xb2: ZeroPageIndirectRead(); this.A = this.Through(); break; // LDA (zp) + case 0xb3: break; // null + case 0xb7: this.ZeroPageRead(); this.SMB(Chip.Bit(3)); break; // SMB3 zp + case 0xbb: break; // null + case 0xbf: this.ZeroPageRead(); this.BBS(Chip.Bit(3)); break; // BBS3 r - case 0xc3: break; // null - case 0xc7: break; // SMB4 zp - case 0xcb: this.SwallowRead(); this.Waiting = true; break; // WAI i - case 0xcf: break; // BBS4 r + case 0xc3: break; // null + case 0xc7: this.ZeroPageRead(); this.SMB(Chip.Bit(4)); break; // SMB4 zp + case 0xcb: this.SwallowRead(); this.Waiting = true; break; // WAI i + case 0xcf: this.ZeroPageRead(); this.BBS(Chip.Bit(4)); break; // BBS4 r - case 0xd2: this.ZeroPageIndirectRead(); this.CMP(this.A); break; // CMP (zp) - case 0xd3: break; // null - case 0xd7: break; // SMB5 zp + case 0xd2: this.ZeroPageIndirectRead(); this.CMP(this.A); break; // CMP (zp) + case 0xd3: break; // null + case 0xd7: this.ZeroPageRead(); this.SMB(Chip.Bit(5)); break; // SMB5 zp case 0xda: this.SwallowRead(); this.Push(this.X); break; // PHX s - case 0xdb: this.SwallowRead(); this.Stopped = true; break; // STP i - case 0xdc: break; // null - case 0xdf: break; // BBS5 r + case 0xdb: this.SwallowRead(); this.Stopped = true; break; // STP i + case 0xdc: this.SwallowRead(); break; // null + case 0xdf: this.ZeroPageRead(); this.BBS(Chip.Bit(5)); break; // BBS5 r - case 0xe3: break; // null - case 0xe7: break; // SMB6 zp - case 0xeb: break; // null - case 0xef: break; // BBS6 r + case 0xe3: break; // null + case 0xe7: this.ZeroPageRead(); this.SMB(Chip.Bit(6)); break; // SMB6 zp + case 0xeb: break; // null + case 0xef: this.ZeroPageRead(); this.BBS(Chip.Bit(6)); break; // BBS6 r - case 0xf2: this.ZeroPageIndirectRead(); this.SBC(); break; // SBC (zp) - case 0xf3: break; // null - case 0xf7: break; // SMB7 zp + case 0xf2: this.ZeroPageIndirectRead(); this.SBC(); break; // SBC (zp) + case 0xf3: break; // null + case 0xf7: this.ZeroPageRead(); this.SMB(Chip.Bit(7)); break; // SMB7 zp case 0xfa: this.SwallowRead(); this.SwallowPop(); this.X = this.Through(this.Pop()); break; // PLX s - case 0xfb: break; // null - case 0xfc: break; // null - case 0xff: break; // BBS7 r + case 0xfb: break; // null + case 0xfc: break; // null + case 0xff: this.ZeroPageRead(); this.BBS(Chip.Bit(7)); break; // BBS7 r } return cycles != this.Cycles; @@ -261,5 +261,43 @@ namespace EightBit #endregion #endregion + + private void RMB(byte flag) + { + this.MemoryRead(); + this.Bus.Data &= (byte)~flag; + this.MemoryWrite(); + } + + private void SMB(byte flag) + { + this.MemoryRead(); + this.Bus.Data |= flag; + this.MemoryWrite(); + } + + private void BBS(byte flag) + { + this.MemoryRead(); + this.Branch(this.Bus.Data & flag); + } + + private void BBR(byte flag) + { + this.MemoryRead(); + this.BranchNot(this.Bus.Data & flag); + } + + private void TSB() + { + this.AdjustZero((byte)(this.A & this.Bus.Data)); + this.ModifyWrite((byte)(this.A | this.Bus.Data)); + } + + private void TRB() + { + this.AdjustZero((byte)(this.A & this.Bus.Data)); + this.ModifyWrite((byte)(~this.A & this.Bus.Data)); + } } } \ No newline at end of file