150 lines
4.2 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |