GBA.Unity/Assets/emulator/HwControlNds.cs

150 lines
4.2 KiB
C#

using System;
using static OptimeGBA.Bits;
namespace OptimeGBA
{
public enum InterruptNds
{
VBlank = 0,
HBlank = 1,
VCounterMatch = 2,
Timer0Overflow = 3,
Timer1Overflow = 4,
Timer2Overflow = 5,
Timer3Overflow = 6,
Rtc = 7,
Dma0 = 8,
Dma1 = 9,
Dma2 = 10,
Dma3 = 11,
Keypad = 12,
GamePak = 13,
// 14, 15, unused
IpcSync = 16,
IpcSendFifoEmpty = 17,
IpcRecvFifoPending = 18,
Slot1DataTransferComplete = 19,
Slot1rq = 20,
GeometryFifo = 21, // ARM9 only
ScreenUnfold = 22, // ARM7 only
SpiBus = 23, // ARM7 only
Wifi = 24, // ARM7 only
}
public sealed class HwControlNds : HwControl
{
Arm7 Cpu;
public HwControlNds(Arm7 cpu)
{
Cpu = cpu;
}
public byte Postflg; // POSTFLG
public byte ReadHwio8(uint addr)
{
byte val = 0;
switch (addr)
{
case 0x4000208: // IME
if (IME) val = BitSet(val, 0);
break;
case 0x4000210: // IE B0
return (byte)(IE >> 0);
case 0x4000211: // IE B1
return (byte)(IE >> 8);
case 0x4000212: // IE B2
return (byte)(IE >> 16);
case 0x4000213: // IE B3
return (byte)(IE >> 24);
case 0x4000214: // IF B0
return (byte)(IF >> 0);
case 0x4000215: // IF B1
return (byte)(IF >> 8);
case 0x4000216: // IF B2
return (byte)(IF >> 16);
case 0x4000217: // IF B3
return (byte)(IF >> 24);
}
return val;
}
public void WriteHwio8(uint addr, byte val)
{
switch (addr)
{
case 0x4000208: // IME
IME = BitTest(val, 0);
CheckAndFireInterrupts();
break;
case 0x4000210: // IE B0
IE &= 0xFFFFFF00;
IE |= (uint)((uint)val << 0);
CheckAndFireInterrupts();
break;
case 0x4000211: // IE B1
IE &= 0xFFFF00FF;
IE |= (uint)((uint)val << 8);
CheckAndFireInterrupts();
break;
case 0x4000212: // IE B2
IE &= 0xFF00FFFF;
IE |= (uint)((uint)val << 16);
CheckAndFireInterrupts();
break;
case 0x4000213: // IE B3
IE &= 0x00FFFFFF;
IE |= (uint)((uint)val << 24);
CheckAndFireInterrupts();
break;
case 0x4000214: // IF B0
IF &= ~(uint)((uint)val << 0);
CheckAndFireInterrupts();
break;
case 0x4000215: // IF B1
IF &= ~(uint)((uint)val << 8);
CheckAndFireInterrupts();
break;
case 0x4000216: // IF B2
IF &= ~(uint)((uint)val << 16);
CheckAndFireInterrupts();
break;
case 0x4000217: // IF B3
IF &= ~(uint)((uint)val << 24);
CheckAndFireInterrupts();
break;
}
}
public override void FlagInterrupt(uint i)
{
IF |= (uint)(1 << (int)i);
CheckAndFireInterrupts();
}
public void CheckAndFireInterrupts()
{
Available = (IE & IF & 0xFFFFFFFF) != 0;
Cpu.FlagInterrupt = Available && IME;
if (Cpu.Armv5)
{
if (Available && IME)
{
Cpu.Halted = false;
}
}
else
{
if (Available)
{
Cpu.Halted = false;
}
}
}
}
}