mirror of
https://github.com/MoleskiCoder/EightBitNet.git
synced 2026-01-23 08:16:25 +00:00
Start implementing W65C02 as a derived MOS6502 core.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
97
M6502/W65C02.cs
Normal 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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user