Start implementing W65C02 as a derived MOS6502 core.

This commit is contained in:
Adrian Conlon
2024-07-22 11:18:36 +01:00
parent c8055d65c3
commit bc8352f96a
3 changed files with 149 additions and 35 deletions

View File

@@ -145,6 +145,43 @@ namespace EightBit
#endregion
#region Bus/Memory Access
protected override void ModifyWrite(byte data)
{
// The read will have already taken place...
this.MemoryWrite(); // Modify cycle
this.MemoryWrite(data); // Write cycle
}
#endregion
#region Addressing modes
protected override void IndirectAddress()
{
this.AbsoluteAddress();
this.GetAddressPaged();
}
#region Address page fixup
protected override void Fixup()
{
this.MemoryRead();
this.Bus.Address.High = this.FixedPage;
}
protected override void FixupBranch(sbyte relative)
{
this.NoteFixedAddress(this.PC.Word + relative);
this.MaybeFixup();
}
#endregion
#endregion
#region Instruction implementations
#region Undocumented instructions

View File

@@ -1,10 +1,10 @@
// <copyright file="M6502.cs" company="Adrian Conlon">
// <copyright file="M6502Core.cs" company="Adrian Conlon">
// Copyright (c) Adrian Conlon. All rights reserved.
// </copyright>
namespace EightBit
{
public class M6502Core(Bus bus) : LittleEndianProcessor(bus)
public abstract class M6502Core(Bus bus) : LittleEndianProcessor(bus)
{
#region Instruction execution events
@@ -215,11 +215,11 @@ namespace EightBit
private const byte RSTvector = 0xfc; // RST vector
private const byte NMIvector = 0xfa; // NMI vector
enum InterruptSource { hardware, software };
protected enum InterruptSource { hardware, software };
enum InterruptType { reset, non_reset };
protected enum InterruptType { reset, non_reset };
private void Interrupt(byte vector, InterruptSource source = InterruptSource.hardware, InterruptType type = InterruptType.non_reset)
protected virtual void Interrupt(byte vector, InterruptSource source = InterruptSource.hardware, InterruptType type = InterruptType.non_reset)
{
if (type == InterruptType.reset)
{
@@ -615,12 +615,7 @@ namespace EightBit
base.BusWrite();
}
protected void ModifyWrite(byte data)
{
// The read will have already taken place...
this.MemoryWrite();
this.MemoryWrite(data);
}
protected abstract void ModifyWrite(byte data);
#endregion
@@ -659,19 +654,12 @@ namespace EightBit
#region Address page fixup
private byte unfixedPage;
private byte fixedPage;
public byte UnfixedPage
{
get => this.unfixedPage;
private set => this.unfixedPage = value;
}
public byte FixedPage
{
get => this.fixedPage;
private set => this.fixedPage = value;
protected set => this.fixedPage = value;
}
protected void MaybeFixup()
@@ -682,12 +670,7 @@ namespace EightBit
}
}
protected void Fixup()
{
this.MemoryRead();
this.UnfixedPage = this.Bus.Address.High;
this.Bus.Address.High = this.FixedPage;
}
protected abstract void Fixup();
protected void MaybeFixupRead()
{
@@ -705,19 +688,19 @@ namespace EightBit
#region Address resolution
private void NoteFixedAddress(int address)
protected void NoteFixedAddress(int address)
{
this.NoteFixedAddress((ushort)address);
}
private void NoteFixedAddress(ushort address)
protected void NoteFixedAddress(ushort address)
{
this.Intermediate.Word = address;
this.FixedPage = this.Intermediate.High;
this.Bus.Address.Low = this.Intermediate.Low;
}
private void GetAddressPaged()
protected void GetAddressPaged()
{
this.GetWordPaged();
this.Bus.Address.Assign(this.Intermediate);
@@ -742,11 +725,7 @@ namespace EightBit
this.GetAddressPaged();
}
protected void IndirectAddress()
{
this.AbsoluteAddress();
this.GetAddressPaged();
}
protected abstract void IndirectAddress();
protected void ZeroPageWithIndexAddress(byte index)
{
@@ -855,12 +834,13 @@ namespace EightBit
{
var relative = (sbyte)this.Bus.Data;
this.SwallowRead();
this.NoteFixedAddress(this.PC.Word + relative);
this.MaybeFixup();
this.FixupBranch(relative);
this.Jump(this.Bus.Address);
}
}
protected abstract void FixupBranch(sbyte relative);
#endregion
#region Data flag adjustment

97
M6502/W65C02.cs Normal file
View File

@@ -0,0 +1,97 @@
// <copyright file="W65C02.cs" company="Adrian Conlon">
// Copyright (c) Adrian Conlon. All rights reserved.
// </copyright>
namespace EightBit
{
public class W65C02(Bus bus) : M6502Core(bus)
{
#region Interrupts
protected override void Interrupt(byte vector, InterruptSource source, InterruptType type)
{
base.Interrupt(vector, source, type);
this.ResetFlag(StatusBits.DF); // Disable decimal mode (Change from M6502)
}
#endregion
#region Core instruction dispatching
protected override bool MaybeExecute()
{
if (base.MaybeExecute())
{
return true;
}
return false;
}
#endregion
#region Bus/Memory Access
protected override void ModifyWrite(byte data)
{
// The read will have already taken place...
this.MemoryRead(); // Modify cycle (Change from M6502)
this.MemoryWrite(data); // Write cycle
}
#endregion
#region Addressing modes
#region Address page fixup
private readonly Register16 lastFetchAddress = new();
protected override byte FetchByte()
{
this.lastFetchAddress.Assign(this.PC);
return base.FetchByte();
}
protected override void Fixup()
{
var fixingLow = this.Bus.Address.Low;
this.MemoryRead(this.lastFetchAddress);
this.Bus.Address.Assign(fixingLow, this.FixedPage);
}
protected override void FixupBranch(sbyte relative)
{
this.NoteFixedAddress(this.PC.Word + relative);
this.lastFetchAddress.Assign(this.Bus.Address); // Effectively negate the use of "lastFetchAddress" for branch fixup usages
this.MaybeFixup();
}
#endregion
#region Address resolution
protected void GetAddress()
{
this.GetWordPaged();
if (this.Bus.Address.Low == 0)
{
this.Bus.Address.High++;
}
this.Bus.Address.High = this.MemoryRead();
this.Bus.Address.Low = this.Intermediate.Low;
}
protected override void IndirectAddress()
{
this.AbsoluteAddress();
this.GetAddress();
}
#endregion
#endregion
}
}