mirror of
https://github.com/MoleskiCoder/EightBitNet.git
synced 2026-01-22 16:16:17 +00:00
.net 9 gb analysis changes
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
// </copyright>
|
||||
namespace EightBit.GameBoy
|
||||
{
|
||||
using LR35902;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -15,13 +16,13 @@ namespace EightBit.GameBoy
|
||||
public const int CyclesPerLine = CyclesPerFrame / TotalLineCount;
|
||||
public const int RomPageSize = 0x4000;
|
||||
|
||||
private readonly Rom bootRom = new Rom(0x100); // 0x0000 - 0x00ff
|
||||
private readonly List<Rom> gameRomBanks = new List<Rom>(); // 0x0000 - 0x3fff, 0x4000 - 0x7fff (switchable)
|
||||
private readonly List<Ram> ramBanks = new List<Ram>(); // 0xa000 - 0xbfff (switchable)
|
||||
private readonly UnusedMemory unmapped2000 = new UnusedMemory(0x2000, 0xff); // 0xa000 - 0xbfff
|
||||
private readonly Ram lowInternalRam = new Ram(0x2000); // 0xc000 - 0xdfff (mirrored at 0xe000)
|
||||
private readonly UnusedMemory unmapped60 = new UnusedMemory(0x60, 0xff); // 0xfea0 - 0xfeff
|
||||
private readonly Ram highInternalRam = new Ram(0x80); // 0xff80 - 0xffff
|
||||
private readonly Rom bootRom = new(0x100); // 0x0000 - 0x00ff
|
||||
private readonly List<Rom> gameRomBanks = new(); // 0x0000 - 0x3fff, 0x4000 - 0x7fff (switchable)
|
||||
private readonly List<Ram> ramBanks = new(); // 0xa000 - 0xbfff (switchable)
|
||||
private readonly UnusedMemory unmapped2000 = new(0x2000, 0xff); // 0xa000 - 0xbfff
|
||||
private readonly Ram lowInternalRam = new(0x2000); // 0xc000 - 0xdfff (mirrored at 0xe000)
|
||||
private readonly UnusedMemory unmapped60 = new(0x60, 0xff); // 0xfea0 - 0xfeff
|
||||
private readonly Ram highInternalRam = new(0x80); // 0xff80 - 0xffff
|
||||
|
||||
private bool enabledLCD = false;
|
||||
|
||||
@@ -240,20 +241,20 @@ namespace EightBit.GameBoy
|
||||
// ROM type
|
||||
switch (this.gameRomBanks[0].Peek(0x147))
|
||||
{
|
||||
case (byte)CartridgeType.ROM:
|
||||
this.rom = true;
|
||||
break;
|
||||
case (byte)CartridgeType.ROM_MBC1:
|
||||
this.rom = this.banked = true;
|
||||
break;
|
||||
case (byte)CartridgeType.ROM_MBC1_RAM:
|
||||
this.rom = this.banked = this.ram = true;
|
||||
break;
|
||||
case (byte)CartridgeType.ROM_MBC1_RAM_BATTERY:
|
||||
this.rom = this.banked = this.ram = this.battery = true;
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException("Unhandled cartridge ROM type");
|
||||
case (byte)CartridgeType.ROM:
|
||||
this.rom = true;
|
||||
break;
|
||||
case (byte)CartridgeType.ROM_MBC1:
|
||||
this.rom = this.banked = true;
|
||||
break;
|
||||
case (byte)CartridgeType.ROM_MBC1_RAM:
|
||||
this.rom = this.banked = this.ram = true;
|
||||
break;
|
||||
case (byte)CartridgeType.ROM_MBC1_RAM_BATTERY:
|
||||
this.rom = this.banked = this.ram = this.battery = true;
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException("Unhandled cartridge ROM type");
|
||||
}
|
||||
|
||||
// ROM size
|
||||
@@ -262,28 +263,28 @@ namespace EightBit.GameBoy
|
||||
var romSizeSpecification = this.Peek(0x148);
|
||||
switch (romSizeSpecification)
|
||||
{
|
||||
case 0x52:
|
||||
gameRomBanks = 72;
|
||||
break;
|
||||
case 0x53:
|
||||
gameRomBanks = 80;
|
||||
break;
|
||||
case 0x54:
|
||||
gameRomBanks = 96;
|
||||
break;
|
||||
default:
|
||||
if (romSizeSpecification > 6)
|
||||
{
|
||||
throw new InvalidOperationException("Invalid ROM size specification");
|
||||
}
|
||||
case 0x52:
|
||||
gameRomBanks = 72;
|
||||
break;
|
||||
case 0x53:
|
||||
gameRomBanks = 80;
|
||||
break;
|
||||
case 0x54:
|
||||
gameRomBanks = 96;
|
||||
break;
|
||||
default:
|
||||
if (romSizeSpecification > 6)
|
||||
{
|
||||
throw new InvalidOperationException("Invalid ROM size specification");
|
||||
}
|
||||
|
||||
gameRomBanks = 1 << (romSizeSpecification + 1);
|
||||
if (gameRomBanks != this.gameRomBanks.Count)
|
||||
{
|
||||
throw new InvalidOperationException("ROM size specification mismatch");
|
||||
}
|
||||
gameRomBanks = 1 << (romSizeSpecification + 1);
|
||||
if (gameRomBanks != this.gameRomBanks.Count)
|
||||
{
|
||||
throw new InvalidOperationException("ROM size specification mismatch");
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
// RAM size
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
namespace EightBit.GameBoy
|
||||
{
|
||||
using LR35902;
|
||||
|
||||
public enum IoRegister
|
||||
{
|
||||
Abbreviated, // FF00 + dd
|
||||
|
||||
@@ -15,5 +15,5 @@ namespace EightBit.GameBoy
|
||||
public const int RasterHeight = 144;
|
||||
|
||||
public const int PixelCount = RasterWidth * RasterHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,8 +68,8 @@ namespace EightBit.GameBoy
|
||||
public const int BOOT_DISABLE = 0x50;
|
||||
|
||||
private readonly Bus bus;
|
||||
private readonly Register16 divCounter = new Register16(0xab, 0xcc);
|
||||
private readonly Register16 dmaAddress = new Register16();
|
||||
private readonly Register16 divCounter = new(0xab, 0xcc);
|
||||
private readonly Register16 dmaAddress = new();
|
||||
|
||||
private int timerCounter = 0;
|
||||
|
||||
@@ -288,7 +288,7 @@ namespace EightBit.GameBoy
|
||||
|
||||
private void TriggerKeypadInterrupt() => this.TriggerInterrupt(Interrupts.KeypadPressed);
|
||||
|
||||
private void Bus_WrittenByte(object sender, System.EventArgs e)
|
||||
private void Bus_WrittenByte(object? sender, System.EventArgs e)
|
||||
{
|
||||
var address = this.bus.Address.Word;
|
||||
var value = this.bus.Data;
|
||||
@@ -296,55 +296,55 @@ namespace EightBit.GameBoy
|
||||
|
||||
switch (port)
|
||||
{
|
||||
case P1:
|
||||
this.scanP14 = (value & (byte)Bits.Bit4) == 0;
|
||||
this.scanP15 = (value & (byte)Bits.Bit5) == 0;
|
||||
break;
|
||||
case P1:
|
||||
this.scanP14 = (value & (byte)Bits.Bit4) == 0;
|
||||
this.scanP15 = (value & (byte)Bits.Bit5) == 0;
|
||||
break;
|
||||
|
||||
case SB: // R/W
|
||||
case SC: // R/W
|
||||
break;
|
||||
case SB: // R/W
|
||||
case SC: // R/W
|
||||
break;
|
||||
|
||||
case DIV: // R/W
|
||||
this.Poke(port, 0);
|
||||
this.timerCounter = this.divCounter.Word = 0;
|
||||
break;
|
||||
case TIMA: // R/W
|
||||
break;
|
||||
case TMA: // R/W
|
||||
break;
|
||||
case TAC: // R/W
|
||||
break;
|
||||
case DIV: // R/W
|
||||
this.Poke(port, 0);
|
||||
this.timerCounter = this.divCounter.Word = 0;
|
||||
break;
|
||||
case TIMA: // R/W
|
||||
break;
|
||||
case TMA: // R/W
|
||||
break;
|
||||
case TAC: // R/W
|
||||
break;
|
||||
|
||||
case IF: // R/W
|
||||
break;
|
||||
case IF: // R/W
|
||||
break;
|
||||
|
||||
case LCDC:
|
||||
case STAT:
|
||||
case SCY:
|
||||
case SCX:
|
||||
break;
|
||||
case DMA:
|
||||
this.dmaAddress.Word = Chip.PromoteByte(value);
|
||||
this.dmaTransferActive = true;
|
||||
break;
|
||||
case LY: // R/O
|
||||
this.Poke(port, 0);
|
||||
break;
|
||||
case BGP:
|
||||
case OBP0:
|
||||
case OBP1:
|
||||
case WY:
|
||||
case WX:
|
||||
break;
|
||||
case LCDC:
|
||||
case STAT:
|
||||
case SCY:
|
||||
case SCX:
|
||||
break;
|
||||
case DMA:
|
||||
this.dmaAddress.Word = Chip.PromoteByte(value);
|
||||
this.dmaTransferActive = true;
|
||||
break;
|
||||
case LY: // R/O
|
||||
this.Poke(port, 0);
|
||||
break;
|
||||
case BGP:
|
||||
case OBP0:
|
||||
case OBP1:
|
||||
case WY:
|
||||
case WX:
|
||||
break;
|
||||
|
||||
case BOOT_DISABLE:
|
||||
this.BootRomDisabled = value != 0;
|
||||
break;
|
||||
case BOOT_DISABLE:
|
||||
this.BootRomDisabled = value != 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void Bus_ReadingByte(object sender, System.EventArgs e)
|
||||
private void Bus_ReadingByte(object? sender, System.EventArgs e)
|
||||
{
|
||||
var address = this.bus.Address.Word;
|
||||
var io = (address >= BASE) && (address < 0xff80);
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace LR35902.BlarggTest
|
||||
{
|
||||
using System;
|
||||
|
||||
public class Board : EightBit.GameBoy.Bus
|
||||
internal class Board : EightBit.GameBoy.Bus
|
||||
{
|
||||
private readonly Configuration configuration;
|
||||
private readonly EightBit.GameBoy.Disassembler disassembler;
|
||||
@@ -30,17 +30,19 @@ namespace LR35902.BlarggTest
|
||||
|
||||
public void Plug(string path) => this.LoadGameRom(this.configuration.RomDirectory + "/" + path);
|
||||
|
||||
private void Board_WrittenByte(object sender, System.EventArgs e)
|
||||
private void Board_WrittenByte(object? sender, System.EventArgs e)
|
||||
{
|
||||
switch (this.Address.Word)
|
||||
{
|
||||
case EightBit.GameBoy.IoRegisters.BASE + EightBit.GameBoy.IoRegisters.SB:
|
||||
System.Console.Out.Write(Convert.ToChar(this.Data));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void CPU_ExecutingInstruction_Debug(object sender, System.EventArgs e)
|
||||
private void CPU_ExecutingInstruction_Debug(object? sender, System.EventArgs e)
|
||||
{
|
||||
if (this.IO.BootRomDisabled)
|
||||
{
|
||||
|
||||
@@ -4,11 +4,9 @@
|
||||
|
||||
namespace LR35902.BlarggTest
|
||||
{
|
||||
public class Computer
|
||||
internal class Computer(Configuration configuration)
|
||||
{
|
||||
private readonly Board board;
|
||||
|
||||
public Computer(Configuration configuration) => this.board = new Board(configuration);
|
||||
private readonly Board board = new(configuration);
|
||||
|
||||
public void Run()
|
||||
{
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
namespace LR35902.BlarggTest
|
||||
{
|
||||
public class Configuration
|
||||
internal class Configuration
|
||||
{
|
||||
public bool DebugMode { get; set; } = false;
|
||||
public bool DebugMode { get; set; }
|
||||
|
||||
public string RomDirectory { get; set; } = "roms";
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<GenerateDocumentationFile>False</GenerateDocumentationFile>
|
||||
<SignAssembly>False</SignAssembly>
|
||||
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
|
||||
<AnalysisLevel>latest</AnalysisLevel>
|
||||
<AnalysisLevel>latest-all</AnalysisLevel>
|
||||
<OutputType>Exe</OutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
namespace LR35902.BlarggTest
|
||||
{
|
||||
public static class Program
|
||||
internal static class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
@@ -17,7 +17,7 @@ namespace LR35902.BlarggTest
|
||||
|
||||
var computer = new Computer(configuration);
|
||||
|
||||
computer.Plug("blargg/cpu_instrs.gb"); // Passed
|
||||
//computer.Plug("blargg/cpu_instrs.gb"); // Passed
|
||||
////computer.Plug("blargg/01-special.gb"); // Passed
|
||||
////computer.Plug("blargg/02-interrupts.gb"); // Passed
|
||||
////computer.Plug("blargg/03-op sp,hl.gb"); // Passed
|
||||
@@ -30,8 +30,8 @@ namespace LR35902.BlarggTest
|
||||
////computer.Plug("blargg/10-bit ops.gb"); // Passed
|
||||
////computer.Plug("blargg/11-op a,(hl).gb"); // Passed
|
||||
|
||||
////computer.Plug("blargg/instr_timing.gb"); // Failed #255
|
||||
////computer.Plug("blargg/interrupt_time.gb"); // Failed
|
||||
computer.Plug("blargg/instr_timing.gb"); // Failed #255
|
||||
//computer.Plug("blargg/interrupt_time.gb"); // Failed
|
||||
|
||||
computer.RaisePOWER();
|
||||
computer.Run();
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Fuse
|
||||
{
|
||||
private readonly Test<T> test;
|
||||
private readonly Result<T> result;
|
||||
private readonly EightBit.Ram ram = new EightBit.Ram(0x10000);
|
||||
private readonly EightBit.Ram ram = new(0x10000);
|
||||
|
||||
public TestRunner(Test<T> test, Result<T> result)
|
||||
{
|
||||
@@ -31,7 +31,7 @@ namespace Fuse
|
||||
|
||||
public bool Unimplemented { get; private set; } = false;
|
||||
|
||||
public override EightBit.MemoryMapping Mapping(ushort address) => new EightBit.MemoryMapping(this.ram, 0, EightBit.Mask.Sixteen, EightBit.AccessLevel.ReadWrite);
|
||||
public override EightBit.MemoryMapping Mapping(ushort address) => new(this.ram, 0, EightBit.Mask.Sixteen, EightBit.AccessLevel.ReadWrite);
|
||||
|
||||
public void Run()
|
||||
{
|
||||
|
||||
@@ -2,19 +2,18 @@
|
||||
// Copyright (c) Adrian Conlon. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace EightBit.GameBoy
|
||||
namespace LR35902
|
||||
{
|
||||
using System;
|
||||
using EightBit;
|
||||
using EightBit.GameBoy;
|
||||
using Bus = EightBit.GameBoy.Bus;
|
||||
|
||||
public class LR35902 : IntelProcessor
|
||||
public sealed class LR35902(Bus bus) : IntelProcessor(bus)
|
||||
{
|
||||
private readonly Bus bus;
|
||||
private readonly Register16 af = new Register16((int)Mask.Sixteen);
|
||||
private readonly Bus bus = bus;
|
||||
private readonly Register16 af = new((int)Mask.Sixteen);
|
||||
private bool prefixCB = false;
|
||||
|
||||
public LR35902(Bus bus)
|
||||
: base(bus) => this.bus = bus;
|
||||
|
||||
public int ClockCycles => this.Cycles * 4;
|
||||
|
||||
public override Register16 AF
|
||||
@@ -73,7 +72,7 @@ namespace EightBit.GameBoy
|
||||
{
|
||||
this.bus.IO.Poke(IoRegisters.IF, 0);
|
||||
this.LowerINT();
|
||||
var index = Chip.FindFirstSet(masked);
|
||||
var index = FindFirstSet(masked);
|
||||
this.Bus.Data = (byte)(0x38 + (index << 3));
|
||||
}
|
||||
else
|
||||
@@ -148,30 +147,18 @@ namespace EightBit.GameBoy
|
||||
|
||||
private void Start() => this.Stopped = false;
|
||||
|
||||
private byte R(int r)
|
||||
private byte R(int r) => r switch
|
||||
{
|
||||
switch (r)
|
||||
{
|
||||
case 0:
|
||||
return this.B;
|
||||
case 1:
|
||||
return this.C;
|
||||
case 2:
|
||||
return this.D;
|
||||
case 3:
|
||||
return this.E;
|
||||
case 4:
|
||||
return this.H;
|
||||
case 5:
|
||||
return this.L;
|
||||
case 6:
|
||||
return this.MemoryRead(this.HL.Word);
|
||||
case 7:
|
||||
return this.A;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(r));
|
||||
}
|
||||
}
|
||||
0 => this.B,
|
||||
1 => this.C,
|
||||
2 => this.D,
|
||||
3 => this.E,
|
||||
4 => this.H,
|
||||
5 => this.L,
|
||||
6 => this.MemoryRead(this.HL.Word),
|
||||
7 => this.A,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(r)),
|
||||
};
|
||||
|
||||
private void R(int r, byte value)
|
||||
{
|
||||
@@ -206,87 +193,53 @@ namespace EightBit.GameBoy
|
||||
}
|
||||
}
|
||||
|
||||
private Register16 RP(int rp)
|
||||
private Register16 RP(int rp) => rp switch
|
||||
{
|
||||
switch (rp)
|
||||
{
|
||||
case 0:
|
||||
return this.BC;
|
||||
case 1:
|
||||
return this.DE;
|
||||
case 2:
|
||||
return this.HL;
|
||||
case 3:
|
||||
return this.SP;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(rp));
|
||||
}
|
||||
}
|
||||
0 => this.BC,
|
||||
1 => this.DE,
|
||||
2 => this.HL,
|
||||
3 => this.SP,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rp)),
|
||||
};
|
||||
|
||||
private Register16 RP2(int rp)
|
||||
private Register16 RP2(int rp) => rp switch
|
||||
{
|
||||
switch (rp)
|
||||
{
|
||||
case 0:
|
||||
return this.BC;
|
||||
case 1:
|
||||
return this.DE;
|
||||
case 2:
|
||||
return this.HL;
|
||||
case 3:
|
||||
return this.AF;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(rp));
|
||||
}
|
||||
}
|
||||
0 => this.BC,
|
||||
1 => this.DE,
|
||||
2 => this.HL,
|
||||
3 => this.AF,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rp)),
|
||||
};
|
||||
|
||||
private void ExecuteCB(int x, int y, int z)
|
||||
{
|
||||
switch (x)
|
||||
{
|
||||
case 0: // rot[y] r[z]
|
||||
{
|
||||
var operand = this.R(z);
|
||||
switch (y)
|
||||
{
|
||||
case 0:
|
||||
operand = this.RLC(operand);
|
||||
break;
|
||||
case 1:
|
||||
operand = this.RRC(operand);
|
||||
break;
|
||||
case 2:
|
||||
operand = this.RL(operand);
|
||||
break;
|
||||
case 3:
|
||||
operand = this.RR(operand);
|
||||
break;
|
||||
case 4:
|
||||
operand = this.SLA(operand);
|
||||
break;
|
||||
case 5:
|
||||
operand = this.SRA(operand);
|
||||
break;
|
||||
case 6: // GB: SWAP r
|
||||
operand = this.Swap(operand);
|
||||
break;
|
||||
case 7:
|
||||
operand = this.SRL(operand);
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException("Unreachable code block reached");
|
||||
}
|
||||
|
||||
this.Tick(2);
|
||||
this.R(z, operand);
|
||||
this.F = AdjustZero(this.F, operand);
|
||||
if (z == 6)
|
||||
{
|
||||
var operand = this.R(z);
|
||||
operand = y switch
|
||||
{
|
||||
0 => this.RLC(operand),
|
||||
1 => this.RRC(operand),
|
||||
2 => this.RL(operand),
|
||||
3 => this.RR(operand),
|
||||
4 => this.SLA(operand),
|
||||
5 => this.SRA(operand),
|
||||
6 => this.Swap(operand), // GB: SWAP r
|
||||
7 => this.SRL(operand),
|
||||
_ => throw new InvalidOperationException("Unreachable code block reached"),
|
||||
};
|
||||
this.Tick(2);
|
||||
}
|
||||
this.R(z, operand);
|
||||
this.F = AdjustZero(this.F, operand);
|
||||
if (z == 6)
|
||||
{
|
||||
this.Tick(2);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 1: // BIT y, r[z]
|
||||
this.Bit(y, this.R(z));
|
||||
@@ -543,7 +496,7 @@ namespace EightBit.GameBoy
|
||||
else
|
||||
{
|
||||
this.R(y, this.R(z));
|
||||
if ((y == 6) || (z == 6))
|
||||
if (y == 6 || z == 6)
|
||||
{
|
||||
this.Tick(); // M operations
|
||||
}
|
||||
@@ -847,73 +800,41 @@ namespace EightBit.GameBoy
|
||||
return operand;
|
||||
}
|
||||
|
||||
private bool JumpConditionalFlag(int flag)
|
||||
private bool JumpConditionalFlag(int flag) => flag switch
|
||||
{
|
||||
switch (flag)
|
||||
{
|
||||
case 0: // NZ
|
||||
return this.JumpConditional((this.F & (byte)StatusBits.ZF) == 0);
|
||||
case 1: // Z
|
||||
return this.JumpConditional((this.F & (byte)StatusBits.ZF) != 0);
|
||||
case 2: // NC
|
||||
return this.JumpConditional((this.F & (byte)StatusBits.CF) == 0);
|
||||
case 3: // C
|
||||
return this.JumpConditional((this.F & (byte)StatusBits.CF) != 0);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(flag));
|
||||
}
|
||||
}
|
||||
0 => this.JumpConditional((this.F & (byte)StatusBits.ZF) == 0), // NZ
|
||||
1 => this.JumpConditional((this.F & (byte)StatusBits.ZF) != 0), // Z
|
||||
2 => this.JumpConditional((this.F & (byte)StatusBits.CF) == 0), // NC
|
||||
3 => this.JumpConditional((this.F & (byte)StatusBits.CF) != 0), // C
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(flag)),
|
||||
};
|
||||
|
||||
private bool JumpRelativeConditionalFlag(int flag)
|
||||
private bool JumpRelativeConditionalFlag(int flag) => flag switch
|
||||
{
|
||||
switch (flag)
|
||||
{
|
||||
case 0: // NZ
|
||||
return this.JumpRelativeConditional((this.F & (byte)StatusBits.ZF) == 0);
|
||||
case 1: // Z
|
||||
return this.JumpRelativeConditional((this.F & (byte)StatusBits.ZF) != 0);
|
||||
case 2: // NC
|
||||
return this.JumpRelativeConditional((this.F & (byte)StatusBits.CF) == 0);
|
||||
case 3: // C
|
||||
return this.JumpRelativeConditional((this.F & (byte)StatusBits.CF) != 0);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(flag));
|
||||
}
|
||||
}
|
||||
0 => this.JumpRelativeConditional((this.F & (byte)StatusBits.ZF) == 0), // NZ
|
||||
1 => this.JumpRelativeConditional((this.F & (byte)StatusBits.ZF) != 0), // Z
|
||||
2 => this.JumpRelativeConditional((this.F & (byte)StatusBits.CF) == 0), // NC
|
||||
3 => this.JumpRelativeConditional((this.F & (byte)StatusBits.CF) != 0), // C
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(flag)),
|
||||
};
|
||||
|
||||
private bool ReturnConditionalFlag(int flag)
|
||||
private bool ReturnConditionalFlag(int flag) => flag switch
|
||||
{
|
||||
switch (flag)
|
||||
{
|
||||
case 0: // NZ
|
||||
return this.ReturnConditional((this.F & (byte)StatusBits.ZF) == 0);
|
||||
case 1: // Z
|
||||
return this.ReturnConditional((this.F & (byte)StatusBits.ZF) != 0);
|
||||
case 2: // NC
|
||||
return this.ReturnConditional((this.F & (byte)StatusBits.CF) == 0);
|
||||
case 3: // C
|
||||
return this.ReturnConditional((this.F & (byte)StatusBits.CF) != 0);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(flag));
|
||||
}
|
||||
}
|
||||
0 => this.ReturnConditional((this.F & (byte)StatusBits.ZF) == 0), // NZ
|
||||
1 => this.ReturnConditional((this.F & (byte)StatusBits.ZF) != 0), // Z
|
||||
2 => this.ReturnConditional((this.F & (byte)StatusBits.CF) == 0), // NC
|
||||
3 => this.ReturnConditional((this.F & (byte)StatusBits.CF) != 0), // C
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(flag)),
|
||||
};
|
||||
|
||||
private bool CallConditionalFlag(int flag)
|
||||
private bool CallConditionalFlag(int flag) => flag switch
|
||||
{
|
||||
switch (flag)
|
||||
{
|
||||
case 0: // NZ
|
||||
return this.CallConditional((this.F & (byte)StatusBits.ZF) == 0);
|
||||
case 1: // Z
|
||||
return this.CallConditional((this.F & (byte)StatusBits.ZF) != 0);
|
||||
case 2: // NC
|
||||
return this.CallConditional((this.F & (byte)StatusBits.CF) == 0);
|
||||
case 3: // C
|
||||
return this.CallConditional((this.F & (byte)StatusBits.CF) != 0);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(flag));
|
||||
}
|
||||
}
|
||||
0 => this.CallConditional((this.F & (byte)StatusBits.ZF) == 0), // NZ
|
||||
1 => this.CallConditional((this.F & (byte)StatusBits.ZF) != 0), // Z
|
||||
2 => this.CallConditional((this.F & (byte)StatusBits.CF) == 0), // NC
|
||||
3 => this.CallConditional((this.F & (byte)StatusBits.CF) != 0), // C
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(flag)),
|
||||
};
|
||||
|
||||
private void Add(Register16 operand, Register16 value)
|
||||
{
|
||||
@@ -1054,7 +975,7 @@ namespace EightBit.GameBoy
|
||||
private void Bit(int n, byte operand)
|
||||
{
|
||||
var carry = this.F & (byte)StatusBits.CF;
|
||||
this.AndR(operand, Bit(n));
|
||||
_ = this.AndR(operand, Bit(n));
|
||||
this.F = SetBit(this.F, StatusBits.CF, carry);
|
||||
}
|
||||
|
||||
@@ -1076,19 +997,19 @@ namespace EightBit.GameBoy
|
||||
}
|
||||
else
|
||||
{
|
||||
if (((this.F & (byte)StatusBits.HC) != 0) || LowNibble((byte)updated) > 9)
|
||||
if ((this.F & (byte)StatusBits.HC) != 0 || LowNibble((byte)updated) > 9)
|
||||
{
|
||||
updated += 6;
|
||||
}
|
||||
|
||||
if (((this.F & (byte)StatusBits.CF) != 0) || updated > 0x9F)
|
||||
if ((this.F & (byte)StatusBits.CF) != 0 || updated > 0x9F)
|
||||
{
|
||||
updated += 0x60;
|
||||
}
|
||||
}
|
||||
|
||||
this.F = ClearBit(this.F, (byte)StatusBits.HC | (byte)StatusBits.ZF);
|
||||
this.F = SetBit(this.F, StatusBits.CF, ((this.F & (byte)StatusBits.CF) != 0) || ((updated & (int)Bits.Bit8) != 0));
|
||||
this.F = SetBit(this.F, StatusBits.CF, (this.F & (byte)StatusBits.CF) != 0 || (updated & (int)Bits.Bit8) != 0);
|
||||
this.A = LowByte(updated);
|
||||
|
||||
this.F = AdjustZero(this.F, this.A);
|
||||
|
||||
Reference in New Issue
Block a user