261 lines
6.9 KiB
C#
261 lines
6.9 KiB
C#
using static OptimeGBA.Bits;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace OptimeGBA
|
|
{
|
|
public enum BackgroundMode
|
|
{
|
|
Char,
|
|
Display3D,
|
|
Affine,
|
|
Extended,
|
|
Large,
|
|
|
|
// Extended
|
|
Affine16BitBgMapEntries,
|
|
Affine256ColorBitmap,
|
|
AffineFullColorBitmap,
|
|
}
|
|
public sealed class Background
|
|
{
|
|
bool Nds;
|
|
|
|
public Background(bool nds, byte id)
|
|
{
|
|
Nds = nds;
|
|
Id = id;
|
|
}
|
|
|
|
byte[] BGCNTValue = new byte[2];
|
|
|
|
// BGCNT
|
|
public byte Priority = 0;
|
|
public uint CharBaseBlock = 0;
|
|
public bool EnableMosaic = false;
|
|
public bool Use8BitColor = false;
|
|
public uint MapBaseBlock = 0;
|
|
public bool OverflowWrap = false;
|
|
public uint ScreenSize = 0;
|
|
|
|
// BGCNT NDS
|
|
public bool AffineBitmap;
|
|
public bool AffineBitmapFullColor;
|
|
|
|
// BGH/VOFS
|
|
public uint HorizontalOffset;
|
|
public uint VerticalOffset;
|
|
|
|
public byte Id;
|
|
|
|
public uint RefPointX;
|
|
public uint RefPointY;
|
|
|
|
public short AffineA;
|
|
public short AffineB;
|
|
public short AffineC;
|
|
public short AffineD;
|
|
|
|
public int AffinePosX;
|
|
public int AffinePosY;
|
|
|
|
// Set by PrepareBackgroundAndWindow() and used by RenderBgModes()
|
|
public BackgroundMode Mode;
|
|
|
|
public byte ReadBGCNT(uint addr)
|
|
{
|
|
switch (addr)
|
|
{
|
|
case 0x00: // BGCNT B0
|
|
return BGCNTValue[0];
|
|
case 0x01: // BGCNT B1
|
|
return BGCNTValue[1];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
public void WriteBGCNT(uint addr, byte val)
|
|
{
|
|
switch (addr)
|
|
{
|
|
case 0x00: // BGCNT B0
|
|
Priority = (byte)((val >> 0) & 0b11);
|
|
|
|
// These bits overlay other bits on NDS
|
|
AffineBitmap = BitTest(val, 7);
|
|
AffineBitmapFullColor = BitTest(val, 2);
|
|
|
|
EnableMosaic = BitTest(val, 6);
|
|
if (!Nds)
|
|
{
|
|
CharBaseBlock = (uint)(val >> 2) & 0b11;
|
|
}
|
|
else
|
|
{
|
|
CharBaseBlock = (uint)(val >> 2) & 0b1111;
|
|
}
|
|
EnableMosaic = BitTest(val, 6);
|
|
Use8BitColor = BitTest(val, 7);
|
|
|
|
BGCNTValue[0] = val;
|
|
break;
|
|
case 0x01: // BGCNT B1
|
|
MapBaseBlock = (uint)(val >> 0) & 0b11111;
|
|
OverflowWrap = BitTest(val, 5);
|
|
ScreenSize = (uint)(val >> 6) & 0b11;
|
|
|
|
BGCNTValue[1] = val;
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void WriteBGOFS(uint addr, byte val)
|
|
{
|
|
switch (addr)
|
|
{
|
|
case 0x0: // BGHOFS B0
|
|
HorizontalOffset &= ~0x0FFu;
|
|
HorizontalOffset |= (uint)((val << 0) & 0x0FFu);
|
|
break;
|
|
case 0x1: // BGHOFS B1
|
|
HorizontalOffset &= ~0x100u;
|
|
HorizontalOffset |= (uint)((val << 8) & 0x100u);
|
|
break;
|
|
|
|
case 0x2: // BGVOFS B0
|
|
VerticalOffset &= ~0x0FFu;
|
|
VerticalOffset |= (uint)((val << 0) & 0x0FFu);
|
|
break;
|
|
case 0x3: // BGVOFS B1
|
|
VerticalOffset &= ~0x100u;
|
|
VerticalOffset |= (uint)((val << 8) & 0x100u);
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void WriteBGXY(uint addr, byte val)
|
|
{
|
|
byte offset = (byte)((addr & 3) * 8);
|
|
switch (addr)
|
|
{
|
|
case 0x0: // BGX_L
|
|
case 0x1: // BGX_L
|
|
case 0x2: // BGX_H
|
|
case 0x3: // BGX_H
|
|
RefPointX &= ~(0xFFu << offset);
|
|
RefPointX |= (uint)(val << offset);
|
|
break;
|
|
|
|
case 0x4: // BGY_L
|
|
case 0x5: // BGY_L
|
|
case 0x6: // BGY_H
|
|
case 0x7: // BGY_H
|
|
RefPointY &= ~(0xFFu << offset);
|
|
RefPointY |= (uint)(val << offset);
|
|
break;
|
|
}
|
|
|
|
CopyAffineParams();
|
|
}
|
|
|
|
public void CopyAffineParams()
|
|
{
|
|
// also sign extend
|
|
AffinePosX = ((int)RefPointX << 4) >> 4;
|
|
AffinePosY = ((int)RefPointY << 4) >> 4;
|
|
}
|
|
|
|
public void WriteBGPX(uint addr, byte val)
|
|
{
|
|
byte offset = (byte)((addr & 1) * 8);
|
|
switch (addr)
|
|
{
|
|
case 0x0: // BGPA B0
|
|
case 0x1: // BGPA B1
|
|
AffineA &= (short)~(0xFFu << offset);
|
|
AffineA |= (short)(val << offset);
|
|
break;
|
|
case 0x2: // BGPB B0
|
|
case 0x3: // BGPB B1
|
|
AffineB &= (short)~(0xFFu << offset);
|
|
AffineB |= (short)(val << offset);
|
|
break;
|
|
|
|
case 0x4: // BGPC B0
|
|
case 0x5: // BGPC B1
|
|
AffineC &= (short)~(0xFFu << offset);
|
|
AffineC |= (short)(val << offset);
|
|
break;
|
|
case 0x6: // BGPD B0
|
|
case 0x7: // BGPD B1
|
|
AffineD &= (short)~(0xFFu << offset);
|
|
AffineD |= (short)(val << offset);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Metadata used for rendering
|
|
public ushort GetMeta()
|
|
{
|
|
return (ushort)((Priority << 8) | (1 << Id));
|
|
}
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Size = 4)]
|
|
public struct ObjPixel
|
|
{
|
|
public ushort Color;
|
|
public byte PaletteIndex;
|
|
public byte Priority;
|
|
public ObjMode Mode;
|
|
|
|
public ObjPixel(ushort color, byte paletteIndex, byte priority, ObjMode transparent)
|
|
{
|
|
Color = color;
|
|
PaletteIndex = paletteIndex;
|
|
Priority = priority;
|
|
Mode = transparent;
|
|
}
|
|
}
|
|
|
|
public enum ObjShape
|
|
{
|
|
Square = 0,
|
|
Horizontal = 1,
|
|
Vertical = 2,
|
|
}
|
|
|
|
public enum ObjMode : byte
|
|
{
|
|
Normal = 0,
|
|
Translucent = 1,
|
|
ObjWindow = 2,
|
|
}
|
|
|
|
public enum BlendEffect
|
|
{
|
|
None = 0,
|
|
Blend = 1,
|
|
Lighten = 2,
|
|
Darken = 3,
|
|
}
|
|
|
|
public enum BlendFlag : byte
|
|
{
|
|
Bg0 = 1 << 0,
|
|
Bg1 = 1 << 1,
|
|
Bg2 = 1 << 2,
|
|
Bg3 = 1 << 3,
|
|
Obj = 1 << 4,
|
|
Backdrop = 1 << 5,
|
|
}
|
|
|
|
public enum WindowFlag : byte
|
|
{
|
|
Bg0 = 1 << 0,
|
|
Bg1 = 1 << 1,
|
|
Bg2 = 1 << 2,
|
|
Bg3 = 1 << 3,
|
|
Obj = 1 << 4,
|
|
ColorMath = 1 << 5,
|
|
}
|
|
} |