mirror of
https://github.com/MoleskiCoder/EightBitNet.git
synced 2026-10-23 23:02:16 +00:00
Needs tidying a little by full cycle accuracy for 6502 / 65c02
This commit is contained in:
1 parent
8f59e79959
commit
6d4d2f22e2
3 files changed
+243
-184
No files matched your search
+29
-20
@@ -14,6 +14,8 @@ namespace M6502
|
||||
this.RaisedPOWER += this.Core_RaisedPOWER;
|
||||
}
|
||||
|
||||
protected bool ImmediateInstruction { get; private set; }
|
||||
|
||||
#region Pin controls
|
||||
|
||||
#region NMI pin
|
||||
@@ -259,7 +261,7 @@ namespace M6502
|
||||
#region Processor state helpers
|
||||
|
||||
protected int InterruptMasked => this.P & (byte)StatusBits.IF;
|
||||
protected int DecimalMasked => this.P & (byte)StatusBits.DF;
|
||||
protected int Denary => this.P & (byte)StatusBits.DF;
|
||||
protected int Negative => NegativeTest(this.P);
|
||||
protected int Zero => ZeroTest(this.P);
|
||||
protected int Overflow => OverflowTest(this.P);
|
||||
@@ -340,7 +342,6 @@ namespace M6502
|
||||
case 0x18: this.SwallowRead(); this.CLC(); break; // CLC (implied)
|
||||
case 0x19: this.AbsoluteY(); this.ORA(); break; // ORA (absolute, Y)
|
||||
case 0x1d: this.AbsoluteX(); this.ORA(); break; // ORA (absolute, X)
|
||||
case 0x1e: this.AbsoluteXAddress(); this.FixupRead(); this.ASL(); break; // ASL (absolute, X)
|
||||
|
||||
case 0x20: this.JSR(); break; // JSR (absolute)
|
||||
case 0x21: this.IndexedIndirectX(); this.AND(); break; // AND (indexed indirect X)
|
||||
@@ -361,7 +362,6 @@ namespace M6502
|
||||
case 0x38: this.SwallowRead(); this.SEC(); break; // SEC (implied)
|
||||
case 0x39: this.AbsoluteY(); this.AND(); break; // AND (absolute, Y)
|
||||
case 0x3d: this.AbsoluteX(); this.AND(); break; // AND (absolute, X)
|
||||
case 0x3e: this.AbsoluteXAddress(); this.FixupRead(); this.ROL(); break; // ROL (absolute, X)
|
||||
|
||||
case 0x40: this.SwallowRead(); this.RTI(); break; // RTI (implied)
|
||||
case 0x41: this.IndexedIndirectX(); this.EOR(); break; // EOR (indexed indirect X)
|
||||
@@ -383,7 +383,6 @@ namespace M6502
|
||||
case 0x58: this.SwallowRead(); this.CLI(); break; // CLI (implied)
|
||||
case 0x59: this.AbsoluteY(); this.EOR(); break; // EOR (absolute, Y)
|
||||
case 0x5d: this.AbsoluteX(); this.EOR(); break; // EOR (absolute, X)
|
||||
case 0x5e: this.AbsoluteXAddress(); this.FixupRead(); this.LSR(); break; // LSR (absolute, X)
|
||||
|
||||
case 0x60: this.SwallowRead(); this.RTS(); break; // RTS (implied)
|
||||
case 0x61: this.IndexedIndirectX(); this.ADC(); break; // ADC (indexed indirect X)
|
||||
@@ -403,7 +402,6 @@ namespace M6502
|
||||
case 0x78: this.SwallowRead(); this.SEI(); break; // SEI (implied)
|
||||
case 0x79: this.AbsoluteY(); this.ADC(); break; // ADC (absolute, Y)
|
||||
case 0x7d: this.AbsoluteX(); this.ADC(); break; // ADC (absolute, X)
|
||||
case 0x7e: this.AbsoluteXAddress(); this.FixupRead(); this.ROR(); break; // ROR (absolute, X)
|
||||
|
||||
case 0x81: this.IndexedIndirectXAddress(); this.STA(); break; // STA (indexed indirect X)
|
||||
case 0x82: this.Immediate(); NOP(); break; // *NOP (immediate)
|
||||
@@ -514,6 +512,7 @@ namespace M6502
|
||||
|
||||
if (this.RDY.Raised())
|
||||
{
|
||||
this.ImmediateInstruction = false;
|
||||
this.OpCode = this.FetchInstruction();
|
||||
if (this.RESET.Lowered())
|
||||
{
|
||||
@@ -709,7 +708,11 @@ namespace M6502
|
||||
|
||||
#region Address and read
|
||||
|
||||
protected void Immediate() => this.FetchByte();
|
||||
protected void Immediate()
|
||||
{
|
||||
this.ImmediateInstruction = true;
|
||||
this.FetchByte();
|
||||
}
|
||||
|
||||
protected void Absolute()
|
||||
{
|
||||
@@ -908,26 +911,26 @@ namespace M6502
|
||||
this.SetFlag(StatusBits.VF, NegativeTest((byte)((operand ^ data) & (operand ^ intermediate))));
|
||||
}
|
||||
|
||||
protected void SBC()
|
||||
protected virtual void SBC()
|
||||
{
|
||||
var operand = this.A;
|
||||
this.A = this.SUB(operand, CarryTest((byte)~this.P));
|
||||
|
||||
this.AdjustOverflowSubtract(operand);
|
||||
this.AdjustNZ(this.Intermediate.Low);
|
||||
this.ResetFlag(StatusBits.CF, this.Intermediate.High);
|
||||
this.PostSUB(operand);
|
||||
//this.AdjustOverflowSubtract(operand);
|
||||
//this.ResetFlag(StatusBits.CF, this.Intermediate.High);
|
||||
}
|
||||
|
||||
private byte SUB(byte operand, int borrow) => this.DecimalMasked != 0 ? this.DecimalSUB(operand, borrow) : this.BinarySUB(operand, borrow);
|
||||
private byte SUB(byte operand, int borrow) => this.Denary != 0 ? this.DecimalSUB(operand, borrow) : this.BinarySUB(operand, borrow);
|
||||
|
||||
protected byte BinarySUB(byte operand, int borrow = 0)
|
||||
protected virtual byte BinarySUB(byte operand, int borrow = 0)
|
||||
{
|
||||
var data = this.Bus.Data;
|
||||
this.Intermediate.Word = (ushort)(operand - data - borrow);
|
||||
return this.Intermediate.Low;
|
||||
}
|
||||
|
||||
private byte DecimalSUB(byte operand, int borrow)
|
||||
protected virtual byte DecimalSUB(byte operand, int borrow)
|
||||
{
|
||||
this.BinarySUB(operand, borrow);
|
||||
|
||||
@@ -949,6 +952,12 @@ namespace M6502
|
||||
return (byte)(PromoteNibble(high) | LowNibble(low));
|
||||
}
|
||||
|
||||
protected virtual void PostSUB(byte operand)
|
||||
{
|
||||
this.AdjustOverflowSubtract(operand);
|
||||
this.ResetFlag(StatusBits.CF, this.Intermediate.High);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Addition
|
||||
@@ -960,11 +969,11 @@ namespace M6502
|
||||
this.SetFlag(StatusBits.VF, NegativeTest((byte)(~(operand ^ data) & (operand ^ intermediate))));
|
||||
}
|
||||
|
||||
protected void ADC() => this.ADC(this.Bus.Data);
|
||||
protected virtual void ADC() => this.ADC(this.Bus.Data);
|
||||
|
||||
protected void ADC(byte data) => this.A = this.DecimalMasked != 0 ? this.DecimalADC(data) : this.BinaryADC(data);
|
||||
protected void ADC(byte data) => this.A = this.Denary != 0 ? this.DecimalADC(data) : this.BinaryADC(data);
|
||||
|
||||
private byte BinaryADC(byte data)
|
||||
protected virtual byte BinaryADC(byte data)
|
||||
{
|
||||
var operand = this.A;
|
||||
this.Intermediate.Word = (ushort)(operand + data + this.Carry);
|
||||
@@ -972,12 +981,10 @@ namespace M6502
|
||||
this.AdjustOverflowAdd(operand);
|
||||
this.SetFlag(StatusBits.CF, CarryTest(this.Intermediate.High));
|
||||
|
||||
this.AdjustNZ(this.Intermediate.Low);
|
||||
|
||||
return this.Intermediate.Low;
|
||||
}
|
||||
|
||||
private byte DecimalADC(byte data)
|
||||
protected virtual byte DecimalADC(byte data)
|
||||
{
|
||||
var operand = this.A;
|
||||
|
||||
@@ -1025,11 +1032,13 @@ namespace M6502
|
||||
|
||||
protected void EOR(byte data) => this.A = this.Through(this.A ^ data);
|
||||
|
||||
protected void BitSet(byte mask) => this.AdjustZero((byte)(this.A & mask));
|
||||
|
||||
protected void BIT()
|
||||
{
|
||||
var data = this.Bus.Data;
|
||||
this.SetFlag(StatusBits.VF, OverflowTest(data));
|
||||
this.AdjustZero((byte)(this.A & data));
|
||||
this.BitSet(data);
|
||||
this.AdjustNegative(data);
|
||||
}
|
||||
|
||||
|
||||
+31
-1
@@ -35,6 +35,7 @@ namespace M6502
|
||||
case 0x1a: this.SwallowRead(); NOP(); break; // *NOP (implied)
|
||||
case 0x1b: this.AbsoluteYAddress(); this.FixupRead(); this.SLO(); break; // *SLO (absolute, Y)
|
||||
case 0x1c: this.AbsoluteXAddress(); this.MaybeFixupRead(); NOP(); break; // *NOP (absolute, X)
|
||||
case 0x1e: this.AbsoluteXAddress(); this.FixupRead(); this.ASL(); break; // ASL (absolute, X)
|
||||
case 0x1f: this.AbsoluteXAddress(); this.FixupRead(); this.SLO(); break; // *SLO (absolute, X)
|
||||
|
||||
case 0x22: this.SwallowRead(); this.JAM(); break; // *JAM
|
||||
@@ -50,6 +51,7 @@ namespace M6502
|
||||
case 0x3a: this.SwallowRead(); NOP(); break; // *NOP (implied)
|
||||
case 0x3b: this.AbsoluteYAddress(); this.FixupRead(); this.RLA(); break; // *RLA (absolute, Y)
|
||||
case 0x3c: this.AbsoluteXAddress(); this.MaybeFixupRead(); NOP(); break; // *NOP (absolute, X)
|
||||
case 0x3e: this.AbsoluteXAddress(); this.FixupRead(); this.ROL(); break; // ROL (absolute, X)
|
||||
case 0x3f: this.AbsoluteXAddress(); this.FixupRead(); this.RLA(); break; // *RLA (absolute, X)
|
||||
|
||||
case 0x42: this.SwallowRead(); this.JAM(); break; // *JAM
|
||||
@@ -64,6 +66,7 @@ namespace M6502
|
||||
case 0x5a: this.SwallowRead(); NOP(); break; // *NOP (implied)
|
||||
case 0x5b: this.AbsoluteYAddress(); this.FixupRead(); this.SRE(); break; // *SRE (absolute, Y)
|
||||
case 0x5c: this.AbsoluteXAddress(); this.MaybeFixupRead(); NOP(); break; // *NOP (absolute, X)
|
||||
case 0x5e: this.AbsoluteXAddress(); this.FixupRead(); this.LSR(); break; // LSR (absolute, X)
|
||||
case 0x5f: this.AbsoluteXAddress(); this.FixupRead(); this.SRE(); break; // *SRE (absolute, X)
|
||||
|
||||
case 0x62: this.SwallowRead(); this.JAM(); break; // *JAM
|
||||
@@ -80,6 +83,7 @@ namespace M6502
|
||||
case 0x7a: this.SwallowRead(); NOP(); break; // *NOP (implied)
|
||||
case 0x7b: this.AbsoluteYAddress(); this.FixupRead(); this.RRA(); break; // *RRA (absolute, Y)
|
||||
case 0x7c: this.AbsoluteXAddress(); this.MaybeFixupRead(); NOP(); break; // *NOP (absolute, X)
|
||||
case 0x7e: this.AbsoluteXAddress(); this.FixupRead(); this.ROR(); break; // ROR (absolute, X)
|
||||
case 0x7f: this.AbsoluteXAddress(); this.FixupRead(); this.RRA(); break; // *RRA (absolute, X)
|
||||
|
||||
case 0x80: this.FetchByte(); NOP(); break; // *NOP (immediate)
|
||||
@@ -186,7 +190,7 @@ namespace M6502
|
||||
private void ARR()
|
||||
{
|
||||
var value = this.Bus.Data;
|
||||
if (this.DecimalMasked != 0)
|
||||
if (this.Denary != 0)
|
||||
this.ARR_d(value);
|
||||
else
|
||||
this.ARR_b(value);
|
||||
@@ -335,6 +339,32 @@ namespace M6502
|
||||
|
||||
#endregion
|
||||
|
||||
#region Processor variations
|
||||
|
||||
protected override byte BinaryADC(byte data)
|
||||
{
|
||||
var returned = base.BinaryADC(data);
|
||||
this.AdjustNZ(returned);
|
||||
return returned;
|
||||
}
|
||||
|
||||
protected override byte BinarySUB(byte operand, int borrow = 0)
|
||||
{
|
||||
var returned = base.BinarySUB(operand, borrow);
|
||||
this.AdjustNZ(this.Intermediate.Low);
|
||||
return returned;
|
||||
|
||||
}
|
||||
|
||||
protected override byte DecimalSUB(byte operand, int borrow)
|
||||
{
|
||||
var returned = base.DecimalSUB(operand, borrow);
|
||||
this.AdjustNZ(this.Intermediate.Low);
|
||||
return returned;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
+183
-163
@@ -1,4 +1,4 @@
|
||||
// <copyright file="WDC65C02.cs" company="Adrian Conlon">
|
||||
// <copyright file="WDC65C02.cs" company="Adrian Conlon">
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
@@ -41,6 +41,20 @@ namespace M6502
|
||||
|
||||
#endregion
|
||||
|
||||
#region Cycle wastage
|
||||
|
||||
private void SwallowFixup() => this.MemoryRead(this.lastFetchAddress);
|
||||
|
||||
private void SwallowSpin(int ticks = 1)
|
||||
{
|
||||
for (int i = 0; i < ticks; i++)
|
||||
{
|
||||
this.MemoryRead();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Core instruction dispatching
|
||||
|
||||
protected override bool MaybeExecute()
|
||||
@@ -53,125 +67,96 @@ namespace M6502
|
||||
var cycles = this.Cycles;
|
||||
switch (this.OpCode)
|
||||
{
|
||||
case 0x02: this.SwallowFetch(); break; // NOP
|
||||
case 0x03: break; // null
|
||||
case 0x04: this.ZeroPage(); this.TSB(); break; // TSB zp
|
||||
case 0x07: this.ZeroPage(); this.RMB0(); break; // RMB0 zp
|
||||
case 0x0b: break; // null
|
||||
case 0x0c: this.Absolute(); this.TSB(); break; // TSB a
|
||||
case 0x0f: this.ZeroPage(); this.BBR0(); break; // BBR0 r
|
||||
case 0x02: this.SwallowFetch(); NOP(); break; // NOP (implied)
|
||||
case 0x04: this.ZeroPage(); this.TSB(); break; // TSB (zero page)
|
||||
case 0x07: this.ZeroPage(); this.RMB0(); break; // RMB0 (zero page)
|
||||
case 0x0c: this.Absolute(); this.TSB(); break; // TSB (absolute)
|
||||
case 0x0f: this.ZeroPage(); this.BBR0(); break; // BBR0 (zero page)
|
||||
|
||||
case 0x12: this.ZeroPageIndirect(); this.ORA(); break; // ORA (zp),y
|
||||
case 0x13: break; // null
|
||||
case 0x14: this.ZeroPage(); this.TRB(); break; // TRB zp
|
||||
case 0x17: this.ZeroPage(); this.RMB1(); break; // RMB1 zp
|
||||
case 0x1a: this.INCA(); break; // INC A
|
||||
case 0x1b: break; // null
|
||||
case 0x1c: this.Absolute(); this.TRB(); break; // TRB a
|
||||
//case 0x1e: this.AbsoluteX(); this.ASL(); break; // ???
|
||||
case 0x1f: this.ZeroPage(); this.BBR1(); break; // BBR1 r
|
||||
case 0x12: this.ZeroPageIndirect(); this.ORA(); break; // ORA (zero page indirect)
|
||||
case 0x14: this.ZeroPage(); this.TRB(); break; // TRB (zero page)
|
||||
case 0x17: this.ZeroPage(); this.RMB1(); break; // RMB1 (zero page)
|
||||
case 0x1a: this.SwallowRead(); this.INCA(); break; // INC A (implied)
|
||||
case 0x1c: this.Absolute(); this.TRB(); break; // TRB (absolute)
|
||||
case 0x1e: this.AbsoluteX(); this.ASL(); break; // ASL (absolute, X)
|
||||
case 0x1f: this.ZeroPage(); this.BBR1(); break; // BBR1 (zero page)
|
||||
|
||||
case 0x22: this.SwallowFetch(); break; // NOP
|
||||
case 0x23: break; // null
|
||||
case 0x27: this.ZeroPage(); this.RMB2(); break; // RMB2 zp
|
||||
case 0x2b: break; // null
|
||||
case 0x2f: this.ZeroPage(); this.BBR2(); break; // BBR2 r
|
||||
case 0x22: this.SwallowFetch(); NOP(); break; // NOP (implied)
|
||||
case 0x27: this.ZeroPage(); this.RMB2(); break; // RMB2 (zero page)
|
||||
case 0x2f: this.ZeroPage(); this.BBR2(); break; // BBR2 (zero page)
|
||||
|
||||
case 0x32: this.ZeroPageIndirect(); this.AND(); break; // AND (zp)
|
||||
case 0x33: break; // null
|
||||
case 0x34: ZeroPageX(); this.BIT(); break; // BIT zp,x
|
||||
case 0x37: this.ZeroPage(); this.RMB3(); break; // RMB3 zp
|
||||
case 0x3a: this.DECA(); break; // DEC A
|
||||
case 0x3b: break; // null
|
||||
case 0x3c: AbsoluteX(); BIT(); break; // BIT abs,x
|
||||
//case 0x3e: break;// ????
|
||||
case 0x3f: this.ZeroPage(); this.BBR3(); break; // BBR3 r
|
||||
case 0x32: this.ZeroPageIndirect(); this.AND(); break; // AND (zero page indirect)
|
||||
case 0x34: this.ZeroPageX(); this.BIT(); break; // BIT (zero page, X)
|
||||
case 0x37: this.ZeroPage(); this.RMB3(); break; // RMB3 (zero page)
|
||||
case 0x3a: this.SwallowRead(); this.DECA(); break; // DEC A (implied)
|
||||
case 0x3c: this.AbsoluteX(); this.BIT(); break; // BIT (absolute, X)
|
||||
case 0x3e: this.AbsoluteX(); this.ROL(); break; // ROL (absolute, X)
|
||||
case 0x3f: this.ZeroPage(); this.BBR3(); break; // BBR3 (zero page)
|
||||
|
||||
case 0x42: this.SwallowFetch(); break; // NOP
|
||||
case 0x43: break; // null
|
||||
case 0x47: this.ZeroPage(); this.RMB4(); break; // RMB4 zp
|
||||
case 0x4b: break; // null
|
||||
case 0x4f: this.ZeroPage(); this.BBR4(); break; // BBR4 r
|
||||
case 0x42: this.SwallowFetch(); NOP(); break; // NOP (implied)
|
||||
case 0x47: this.ZeroPage(); this.RMB4(); break; // RMB4 (zero page)
|
||||
case 0x4f: this.ZeroPage(); this.BBR4(); break; // BBR4 (zero page)
|
||||
|
||||
case 0x52: this.ZeroPageIndirect(); this.EOR(); break; // EOR (zp)
|
||||
case 0x53: break; // null
|
||||
case 0x54: this.ZeroPageX(); break; // zp,x NOP
|
||||
case 0x57: this.ZeroPage(); this.RMB5(); break; // RMB5 zp
|
||||
case 0x5a: this.PHY(); break; // PHY s
|
||||
case 0x5b: break; // null
|
||||
case 0x5c: this.SwallowFetch(); this.SwallowRead(); this.SwallowFetch(); break; // ???
|
||||
//case 0x5e: break;// ????
|
||||
case 0x5f: this.ZeroPage(); this.BBR5(); break; // BBR5 r
|
||||
case 0x52: this.ZeroPageIndirect(); this.EOR(); break; // EOR (zero page indirect)
|
||||
case 0x54: this.ZeroPageX(); NOP(); break; // NOP (zero page, X)
|
||||
case 0x57: this.ZeroPage(); this.RMB5(); break; // RMB5 (zero page)
|
||||
case 0x5a: this.SwallowRead(); this.PHY(); break; // PHY (implied)
|
||||
case 0x5c: this.AbsoluteAddress(); this.SwallowFixup(); NOP(); break; // NOP (absolute)
|
||||
case 0x5e: this.AbsoluteX(); this.LSR(); break; // LSR (absolute, X)
|
||||
case 0x5f: this.ZeroPage(); this.BBR5(); break; // BBR5 (zero page)
|
||||
|
||||
case 0x62: this.SwallowFetch(); break; // *NOP
|
||||
case 0x63: break; // null
|
||||
case 0x64: this.ZeroPageAddress(); this.STZ(); break; // STZ zp
|
||||
case 0x67: this.ZeroPage(); this.RMB6(); break; // RMB6 zp
|
||||
case 0x6b: break; // null
|
||||
case 0x6f: this.ZeroPage(); this.BBR6(); break; // BBR6 r
|
||||
case 0x62: this.SwallowFetch(); NOP(); break; // NOP (implied)
|
||||
case 0x64: this.ZeroPageAddress(); this.STZ(); break; // STZ (zero page)
|
||||
case 0x67: this.ZeroPage(); this.RMB6(); break; // RMB6 (zero page)
|
||||
case 0x6f: this.ZeroPage(); this.BBR6(); break; // BBR6 (zero page)
|
||||
|
||||
case 0x72: this.ZeroPageIndirect(); this.ADC(); break; // ADC (zp)
|
||||
case 0x73: break; // null
|
||||
case 0x74: this.ZeroPageXAddress(); this.STZ(); break; // STZ zp,x
|
||||
case 0x77: this.ZeroPage(); this.RMB7(); break; // RMB7 zp
|
||||
case 0x7a: this.PLY(); break; // PLY s
|
||||
case 0x7b: break; // null
|
||||
case 0x7c: this.AbsoluteXAddress(); this.JumpIndirect(); break; // JMP (a,x)
|
||||
case 0x7f: this.ZeroPage(); this.BBR7(); break; // BBR7 r
|
||||
case 0x72: this.ZeroPageIndirect(); this.ADC(); break; // ADC (zero page indirect)
|
||||
case 0x74: this.ZeroPageXAddress(); this.STZ(); break; // STZ (zero page, X)
|
||||
case 0x77: this.ZeroPage(); this.RMB7(); break; // RMB7 (zero page)
|
||||
case 0x7a: this.SwallowRead(); this.PLY(); break; // PLY (implied)
|
||||
case 0x7c: this.AbsoluteXIndirectAddress(); JMP(); break; // JMP (absolute, X indirect)
|
||||
case 0x7e: this.AbsoluteX(); this.ROR(); break; // ROR (absolute, X)
|
||||
case 0x7f: this.ZeroPage(); this.BBR7(); break; // BBR7 (zero page)
|
||||
|
||||
case 0x80: this.BRA(); break; // BRA r
|
||||
case 0x83: break; // null
|
||||
case 0x87: this.ZeroPage(); this.SMB0(); break; // SMB0 zp
|
||||
case 0x89: this.Immediate(); this.BIT_immediate(); break; // BIT # (TBC)
|
||||
case 0x8b: break; // null
|
||||
case 0x8f: this.ZeroPage(); this.BBS0(); break; // BBS0 r
|
||||
case 0x80: this.Immediate(); this.BRA(); break; // BRA (immediate)
|
||||
case 0x87: this.ZeroPage(); this.SMB0(); break; // SMB0 (zero page)
|
||||
case 0x89: this.Immediate(); this.BIT_immediate(); break; // BIT (immediate)
|
||||
case 0x8f: this.ZeroPage(); this.BBS0(); break; // BBS0 (zero page)
|
||||
|
||||
case 0x92: this.ZeroPageIndirectAddress(); this.STA(); break; // STA (zp)
|
||||
case 0x93: break; // null
|
||||
case 0x97: this.ZeroPage(); this.SMB1(); break; // SMB1 zp
|
||||
case 0x9b: break; // null
|
||||
case 0x9c: this.AbsoluteAddress(); this.STZ(); break; // STZ a
|
||||
case 0x9e: this.AbsoluteXAddress(); this.Fixup(); this.STZ(); break; // STZ a,x
|
||||
case 0x9f: this.ZeroPage(); this.BBS1(); break; // BBS1 r
|
||||
case 0x92: this.ZeroPageIndirectAddress(); this.STA(); break; // STA (zero page indirect)
|
||||
case 0x97: this.ZeroPage(); this.SMB1(); break; // SMB1 (zero page)
|
||||
case 0x9c: this.AbsoluteAddress(); this.STZ(); break; // STZ (absolute)
|
||||
case 0x9e: this.AbsoluteXAddress(); this.Fixup(); this.STZ(); break; // STZ (absolute, X)
|
||||
case 0x9f: this.ZeroPage(); this.BBS1(); break; // BBS1 (zero page)
|
||||
|
||||
case 0xa3: break; // null
|
||||
case 0xa7: this.ZeroPage(); this.SMB2(); break; // SMB2 zp
|
||||
case 0xab: break; // null
|
||||
case 0xaf: this.ZeroPage(); this.BBS2(); break; // BBS2 r
|
||||
case 0xa7: this.ZeroPage(); this.SMB2(); break; // SMB2 (zero page)
|
||||
case 0xaf: this.ZeroPage(); this.BBS2(); break; // BBS2 (zero page)
|
||||
|
||||
case 0xb2: this.ZeroPageIndirect(); this.LDA(); break; // LDA (zp)
|
||||
case 0xb3: break; // null
|
||||
case 0xb7: this.ZeroPage(); this.SMB3(); break; // SMB3 zp
|
||||
case 0xbb: break; // null
|
||||
case 0xbf: this.ZeroPage(); this.BBS3(); break; // BBS3 r
|
||||
case 0xb2: this.ZeroPageIndirect(); this.LDA(); break; // LDA (zero page indirect)
|
||||
case 0xb7: this.ZeroPage(); this.SMB3(); break; // SMB3 (zero page)
|
||||
case 0xbf: this.ZeroPage(); this.BBS3(); break; // BBS3 (zero page)
|
||||
|
||||
case 0xc3: break; // null
|
||||
case 0xc7: this.ZeroPage(); this.SMB4(); break; // SMB4 zp
|
||||
case 0xcb: this.WAI(); break; // WAI i
|
||||
case 0xcf: this.ZeroPage(); this.BBS4(); break; // BBS4 r
|
||||
case 0xc7: this.ZeroPage(); this.SMB4(); break; // SMB4 (zero page)
|
||||
case 0xcb: this.SwallowRead(); this.WAI(); break; // WAI (implied)
|
||||
case 0xcf: this.ZeroPage(); this.BBS4(); break; // BBS4 (zero page)
|
||||
|
||||
case 0xd2: this.ZeroPageIndirect(); this.CMP(); break; // CMP (zp)
|
||||
case 0xd3: break; // null
|
||||
case 0xd4: this.ZeroPageX(); break; // zp,x NOP
|
||||
case 0xd7: this.ZeroPage(); this.SMB5(); break; // SMB5 zp
|
||||
case 0xda: this.PHX(); break; // PHX s
|
||||
case 0xdb: this.STP(); break; // STP i
|
||||
case 0xdc: this.Absolute(); break; // null
|
||||
case 0xdf: this.ZeroPage(); this.BBS5(); break; // BBS5 r
|
||||
case 0xd2: this.ZeroPageIndirect(); this.CMP(); break; // CMP (zero page indirect)
|
||||
case 0xd4: this.ZeroPageX(); NOP(); break; // NOP (zero page, X)
|
||||
case 0xd7: this.ZeroPage(); this.SMB5(); break; // SMB5 (zero page)
|
||||
case 0xda: this.SwallowRead(); this.PHX(); break; // PHX (implied)
|
||||
case 0xdb: this.SwallowRead(); this.STP(); break; // STP (implied)
|
||||
case 0xdc: this.AbsoluteAddress(); this.SwallowFixup(); NOP(); break; // NOP (absolute)
|
||||
case 0xdf: this.ZeroPage(); this.BBS5(); break; // BBS5 (zero page)
|
||||
|
||||
case 0xe3: break; // null
|
||||
case 0xe7: this.ZeroPage(); this.SMB6(); break; // SMB6 zp
|
||||
case 0xeb: break; // null
|
||||
case 0xef: this.ZeroPage(); this.BBS6(); break; // BBS6 r
|
||||
case 0xe7: this.ZeroPage(); this.SMB6(); break; // SMB6 (zero page)
|
||||
case 0xef: this.ZeroPage(); this.BBS6(); break; // BBS6 (zero page)
|
||||
|
||||
case 0xf2: this.ZeroPageIndirect(); this.SBC(); break; // SBC (zp)
|
||||
case 0xf3: break; // null
|
||||
case 0xf4: this.ZeroPageX(); break; // zp,x NOP
|
||||
case 0xf7: this.ZeroPage(); this.SMB7(); break; // SMB7 zp
|
||||
case 0xfa: this.PLX(); break; // PLX s
|
||||
case 0xfb: break; // null
|
||||
case 0xfc: break; // null
|
||||
case 0xff: this.ZeroPage(); this.BBS7(); break; // BBS7 r
|
||||
case 0xf2: this.ZeroPageIndirect(); this.SBC(); break; // SBC (zero page indirect)
|
||||
case 0xf4: this.ZeroPageX(); NOP(); break; // NOP (zero page, X)
|
||||
case 0xf7: this.ZeroPage(); this.SMB7(); break; // SMB7 (zero page)
|
||||
case 0xfa: this.SwallowRead(); this.PLX(); break; // PLX (implied)
|
||||
case 0xfc: this.AbsoluteAddress(); this.SwallowFixup(); NOP(); break; // NOP (absolute)
|
||||
case 0xff: this.ZeroPage(); this.BBS7(); break; // BBS7 (zero page)
|
||||
}
|
||||
|
||||
return cycles != this.Cycles;
|
||||
@@ -207,7 +192,7 @@ namespace M6502
|
||||
protected override void ModifyWrite(byte data)
|
||||
{
|
||||
// The read will have already taken place...
|
||||
this.MemoryRead(); // Modify cycle (Change from MOS6502)
|
||||
this.SwallowSpin(); // Modify cycle (Change from MOS6502)
|
||||
this.MemoryWrite(data); // Write cycle
|
||||
}
|
||||
|
||||
@@ -228,7 +213,7 @@ namespace M6502
|
||||
protected override void Fixup()
|
||||
{
|
||||
var fixingLow = this.Bus.Address.Low;
|
||||
this.MemoryRead(this.lastFetchAddress);
|
||||
this.SwallowFixup();
|
||||
this.Bus.Address.Assign(fixingLow, this.FixedPage);
|
||||
}
|
||||
|
||||
@@ -262,6 +247,17 @@ namespace M6502
|
||||
this.GetAddress();
|
||||
}
|
||||
|
||||
private void AbsoluteXIndirectAddress()
|
||||
{
|
||||
var current = this.PC.Word;
|
||||
this.AbsoluteXAddress();
|
||||
this.Bus.Address.Word = current;
|
||||
this.SwallowSpin();
|
||||
this.Bus.Address.Assign(this.Intermediate);
|
||||
this.GetInto(this.Intermediate);
|
||||
this.Bus.Address.Assign(this.Intermediate);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Address and read
|
||||
@@ -276,91 +272,122 @@ namespace M6502
|
||||
|
||||
#endregion
|
||||
|
||||
private void BIT_immediate()
|
||||
#region Processor variations
|
||||
|
||||
protected override byte BinaryADC(byte data)
|
||||
{
|
||||
this.AdjustZero((byte)(this.A & this.Bus.Data));
|
||||
var returned = base.BinaryADC(data);
|
||||
this.AdjustNZ(returned);
|
||||
return returned;
|
||||
}
|
||||
|
||||
private void INCA()
|
||||
protected override byte DecimalADC(byte data)
|
||||
{
|
||||
this.SwallowRead();
|
||||
this.A = this.INC(this.A);
|
||||
var returned = base.DecimalADC(data);
|
||||
this.AdjustNZ(returned);
|
||||
if (this.ImmediateInstruction)
|
||||
{
|
||||
this.MemoryRead(0x7f, 0x00);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.SwallowSpin();
|
||||
}
|
||||
return returned;
|
||||
}
|
||||
|
||||
private void DECA()
|
||||
protected override void SBC()
|
||||
{
|
||||
this.SwallowRead();
|
||||
this.A = this.DEC(this.A);
|
||||
base.SBC();
|
||||
if (this.Denary != 0)
|
||||
{
|
||||
this.AdjustNZ(this.A);
|
||||
if (this.ImmediateInstruction)
|
||||
this.MemoryRead(0x00, 0x00);
|
||||
else
|
||||
this.SwallowSpin();
|
||||
}
|
||||
}
|
||||
|
||||
private void PHX()
|
||||
protected override byte BinarySUB(byte operand, int borrow = 0)
|
||||
{
|
||||
this.SwallowRead();
|
||||
this.Push(this.X);
|
||||
var returned = base.BinarySUB(operand, borrow);
|
||||
this.AdjustNZ(this.Intermediate.Low);
|
||||
return returned;
|
||||
}
|
||||
|
||||
protected override byte DecimalSUB(byte operand, int borrow)
|
||||
{
|
||||
base.BinarySUB(operand, borrow);
|
||||
|
||||
var data = this.Bus.Data;
|
||||
var result = this.Intermediate.Low;
|
||||
|
||||
var loBorrow = (LowNibble(operand) < LowNibble(data) + borrow) ? 1 : 0;
|
||||
if (loBorrow != 0)
|
||||
{
|
||||
result -= 6;
|
||||
}
|
||||
|
||||
if (HighNibble(operand) < HighNibble(data) + loBorrow)
|
||||
{
|
||||
result -= 0x60;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void BIT_immediate() => this.BitSet(this.Bus.Data);
|
||||
|
||||
private void INCA() => this.A = this.INC(this.A);
|
||||
|
||||
private void DECA() => this.A = this.DEC(this.A);
|
||||
|
||||
private void PHX() => this.Push(this.X);
|
||||
|
||||
private void PLX()
|
||||
{
|
||||
this.SwallowRead();
|
||||
this.SwallowPop();
|
||||
this.X = this.Through(this.Pop());
|
||||
}
|
||||
|
||||
private void PHY()
|
||||
{
|
||||
this.SwallowRead();
|
||||
this.Push(this.Y);
|
||||
}
|
||||
private void PHY() => this.Push(this.Y);
|
||||
|
||||
private void PLY()
|
||||
{
|
||||
this.SwallowRead();
|
||||
this.SwallowPop();
|
||||
this.Y = this.Through(this.Pop());
|
||||
}
|
||||
|
||||
private void JumpIndirect()
|
||||
{
|
||||
this.Bus.Address.Assign(this.Intermediate);
|
||||
this.GetAddressPaged();
|
||||
this.JMP();
|
||||
}
|
||||
|
||||
private void BRA() => this.Branch(true);
|
||||
|
||||
private void WAI()
|
||||
{
|
||||
this.SwallowRead();
|
||||
this.Waiting = true;
|
||||
}
|
||||
private void WAI() => this.Waiting = true;
|
||||
|
||||
private void STP()
|
||||
{
|
||||
this.SwallowRead();
|
||||
this.Stopped = true;
|
||||
}
|
||||
private void STP() => this.Stopped = true;
|
||||
|
||||
private void STZ() => this.MemoryWrite(0);
|
||||
|
||||
private void RMB0() => this.RMB(Bit(0));
|
||||
|
||||
|
||||
private void RMB1() => this.RMB(Bit(1));
|
||||
|
||||
|
||||
private void RMB2() => this.RMB(Bit(2));
|
||||
|
||||
|
||||
private void RMB3() => this.RMB(Bit(3));
|
||||
|
||||
|
||||
private void RMB4() => this.RMB(Bit(4));
|
||||
|
||||
|
||||
private void RMB5() => this.RMB(Bit(5));
|
||||
|
||||
|
||||
private void RMB6() => this.RMB(Bit(6));
|
||||
|
||||
|
||||
private void RMB7() => this.RMB(Bit(7));
|
||||
|
||||
private void RMB(byte flag)
|
||||
{
|
||||
this.MemoryRead();
|
||||
this.SwallowSpin();
|
||||
this.Bus.Data &= (byte)~flag;
|
||||
this.MemoryWrite();
|
||||
}
|
||||
@@ -383,13 +410,14 @@ namespace M6502
|
||||
|
||||
private void SMB(byte flag)
|
||||
{
|
||||
this.MemoryRead();
|
||||
this.SwallowSpin();
|
||||
this.Bus.Data |= flag;
|
||||
this.MemoryWrite();
|
||||
}
|
||||
|
||||
private void BranchBit(bool condition)
|
||||
{
|
||||
this.SwallowSpin();
|
||||
this.FetchByte();
|
||||
if (condition)
|
||||
{
|
||||
@@ -420,11 +448,7 @@ namespace M6502
|
||||
|
||||
private void BBS7() => this.BBS(Bit(7));
|
||||
|
||||
private void BBS(byte flag)
|
||||
{
|
||||
this.MemoryRead();
|
||||
this.BranchBit((this.Bus.Data & flag) != 0);
|
||||
}
|
||||
private void BBS(byte flag) => this.BranchBit((this.Bus.Data & flag) != 0);
|
||||
|
||||
private void BBR0() => this.BBR(Bit(0));
|
||||
private void BBR1() => this.BBR(Bit(1));
|
||||
@@ -435,21 +459,17 @@ namespace M6502
|
||||
private void BBR6() => this.BBR(Bit(6));
|
||||
private void BBR7() => this.BBR(Bit(7));
|
||||
|
||||
private void BBR(byte flag)
|
||||
{
|
||||
this.MemoryRead();
|
||||
this.BranchBit((this.Bus.Data & flag) == 0);
|
||||
}
|
||||
private void BBR(byte flag) => this.BranchBit((this.Bus.Data & flag) == 0);
|
||||
|
||||
private void TSB()
|
||||
{
|
||||
this.AdjustZero((byte)(this.A & this.Bus.Data));
|
||||
this.BitSet(this.Bus.Data);
|
||||
this.ModifyWrite((byte)(this.A | this.Bus.Data));
|
||||
}
|
||||
|
||||
private void TRB()
|
||||
{
|
||||
this.AdjustZero((byte)(this.A & this.Bus.Data));
|
||||
this.BitSet(this.Bus.Data);
|
||||
this.ModifyWrite((byte)(~this.A & this.Bus.Data));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user