Cosmos/source2/Users/Orvid/Orvid.Graphics.Cosmos/Drivers/VGADriver.cs
blah38621_cp 92dcac4a51 Made a few improvements to the speed of the ILScanner, including caching the resolved plugs.
Added the possibility for an optimization step in the IL2CPU MSBuild task. Currently commented out, but should work fine with a few modifications to the optimizer.
Moved classes that are dependent on Cosmos from the Orvid.Graphics, into the Orvid.Graphics.Cosmos assembly. 
Re-factored the font mechanism, added partially working .fnt Font support. 
Added a Rectangle class, and a Vec2d class, which is the same as Vec2, except with doubles for the X and Y values.
Made a small aesthetic improvement to the output of the File2ByteArray Converter.
2011-09-03 21:05:46 +00:00

400 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
namespace Orvid.Graphics.Drivers
{
/// <summary>
/// The default implementation of a VGA driver.
/// </summary>
public class VGADriver : GraphicsDriver
{
private readonly Cosmos.Core.IOGroup.VGA mIO = new Cosmos.Core.IOGroup.VGA();
private GraphicsMode curMode;
/// <summary>
/// The name of the driver.
/// </summary>
public override string Name
{
get
{
return "Standard VGA Driver";
}
}
/// <summary>
/// The version of the driver.
/// </summary>
public override string Version
{
get
{
return "v 1.0";
}
}
/// <summary>
/// The company responsible for the driver.
/// </summary>
public override string Company
{
get
{
return "The Cosmos Community";
}
}
/// <summary>
/// The Author of the driver.
/// </summary>
public override string Author
{
get
{
return "Orvid King";
}
}
/// <summary>
/// The current GraphicsMode.
/// </summary>
public override GraphicsMode Mode
{
get
{
return curMode;
}
}
private uint GetForColorizer(Pixel p)
{
byte r = getForPallet(p.R);
byte g = getForPallet(p.G);
byte b = getForPallet(p.B);
return (uint)(Math.Floor((double)(r / 42)) * Math.Floor((double)(g / 42)) * Math.Floor((double)(b / 42)));
}
private uint[] Colorize(Image i)
{
uint[] arr = new uint[i.Height * i.Width];
int indx = 0;
for (int y = 0; y < i.Height; y++)
{
for (int x = 0; x < i.Width; x++)
{
arr[indx] = GetForColorizer(i.Data[indx]);
indx++;
}
}
return arr;
}
public override void Update(Image i)
{
// TODO: Switch to an delegate based draw mechanism,
// it would be much faster than switch, case like statements.
uint[] data = Colorize(i);
for (uint i2 = 0; i2 < 64000 /* 320 Times 200 is 64,000 so we need to loop 64k times. */; i2++)
{
mIO.VGAMemoryBlock[i2] = (byte)(data[i2] & 0xFF);
}
}
public override List<GraphicsMode> GetSupportedModes()
{
List<GraphicsMode> modes = new List<GraphicsMode>();
modes.Add(new GraphicsMode(Resolution.Size320x200, ColorDepth.Bit8));
return modes;
}
public override void SetMode(GraphicsMode mode)
{
if (SupportsMode(mode))
{
curMode = mode;
}
}
public override bool Supported()
{
return true;
}
private byte getForPallet(byte i)
{
if (i > 210)
{
return 255;
}
else
{
return i;
}
}
public override void Initialize()
{
curMode = new GraphicsMode(Resolution.Size320x200, ColorDepth.Bit8);
SetMode320x200x8();
SetPaletteEntry(0, 0, 0, 0);
SetPaletteEntry(1, 255, 255, 255);
int i = 2;
for (int r = 0; r < 6; r++)
{
for (int g = 0; g < 6; g++)
{
SetPaletteEntry(i, getForPallet((byte)(r * 42)), getForPallet((byte)(g * 42)), 0);
i++;
SetPaletteEntry(i, getForPallet((byte)(r * 42)), getForPallet((byte)(g * 42)), 42);
i++;
SetPaletteEntry(i, getForPallet((byte)(r * 42)), getForPallet((byte)(g * 42)), 84);
i++;
SetPaletteEntry(i, getForPallet((byte)(r * 42)), getForPallet((byte)(g * 42)), 126);
i++;
SetPaletteEntry(i, getForPallet((byte)(r * 42)), getForPallet((byte)(g * 42)), 168);
i++;
SetPaletteEntry(i, getForPallet((byte)(r * 42)), getForPallet((byte)(g * 42)), 210);
i++;
if (i < 256)
{
SetPaletteEntry(i, getForPallet((byte)(r * 42)), getForPallet((byte)(g * 42)), 255);
i++;
}
}
}
}
private const byte NumSeqRegs = 5;
private const byte NumCRTCRegs = 25;
private const byte NumGCRegs = 9;
private const byte NumACRegs = 21;
#region WriteVGARegisters
private void WriteVGARegisters(byte[] registers)
{
int xIdx = 0;
byte i;
/* write MISCELLANEOUS reg */
mIO.MiscellaneousOutput_Write.Byte = registers[xIdx];
xIdx++;
/* write SEQUENCER regs */
for (i = 0; i < NumSeqRegs; i++)
{
mIO.Sequencer_Index.Byte = i;
mIO.Sequencer_Data.Byte = registers[xIdx];
xIdx++;
}
/* unlock CRTC registers */
mIO.CRTController_Index.Byte = 0x03;
mIO.CRTController_Data.Byte = (byte)(mIO.CRTController_Data.Byte | 0x80);
mIO.CRTController_Index.Byte = 0x11;
mIO.CRTController_Data.Byte = (byte)(mIO.CRTController_Data.Byte & 0x7F);
/* make sure they remain unlocked */
registers[0x03] |= 0x80;
registers[0x11] &= 0x7f;
/* write CRTC regs */
for (i = 0; i < NumCRTCRegs; i++)
{
mIO.CRTController_Index.Byte = i;
mIO.CRTController_Data.Byte = registers[xIdx];
xIdx++;
}
/* write GRAPHICS CONTROLLER regs */
for (i = 0; i < NumGCRegs; i++)
{
mIO.GraphicsController_Index.Byte = i;
mIO.GraphicsController_Data.Byte = registers[xIdx];
xIdx++;
}
/* write ATTRIBUTE CONTROLLER regs */
for (i = 0; i < NumACRegs; i++)
{
var xDoSomething = mIO.Instat_Read.Byte;
mIO.AttributeController_Index.Byte = i;
mIO.AttributeController_Write.Byte = registers[xIdx];
xIdx++;
}
/* lock 16-color palette and unblank display */
var xNothing = mIO.Instat_Read.Byte;
mIO.AttributeController_Index.Byte = 0x20;
}
#endregion
#region 300x200x4
/*
private static byte[] g_320x200x4 = new byte[]
{
/* MISC *
0x63,
/* SEQ *
0x03, 0x09, 0x03, 0x00, 0x02,
/* CRTC *
0x2D, 0x27, 0x28, 0x90, 0x2B, 0x80, 0xBF, 0x1F,
0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x9C, 0x0E, 0x8F, 0x14, 0x00, 0x96, 0xB9, 0xA3,
0xFF,
/* GC *
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x02, 0x00,
0xFF,
/* AC *
0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x01, 0x00, 0x03, 0x00, 0x00
};
*/
#endregion
#region 320x200x8
public void SetMode320x200x8()
{
WriteVGARegisters(g_320x200x256);
}
private static byte[] g_320x200x256 = new byte[]
{
/* MISC */
0x63,
/* SEQ */
0x03, 0x01, 0x0F, 0x00, 0x0E,
/* CRTC */
0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F,
0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x9C, 0x0E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3,
0xFF,
/* GC */
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,
0xFF,
/* AC */
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x41, 0x00, 0x0F, 0x00, 0x00
};
#endregion
#region 640x480x2
/*
private static byte[] g_640x480x2 = new byte[]
{
/* MISC *
0xE3,
/* SEQ *
0x03, 0x01, 0x0F, 0x00, 0x06,
/* CRTC *
0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E,
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xEA, 0x0C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xE3,
0xFF,
/* GC *
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0F,
0xFF,
/* AC *
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
0x01, 0x00, 0x0F, 0x00, 0x00
};
*/
#endregion
#region 640x480x16
/*
public void SetPixel640x480x16(uint width, uint height, uint c)
{
var xSegment = GetFramebufferSegment();
var xOffset = (height * 32) + width >> 1;
c = c & 0xf;
if ((width & 1) == 0)
{
xSegment[xOffset] = (byte)((xSegment[xOffset] & 0xf) | (c << 4));
}
else
{
xSegment[xOffset] = (byte)((xSegment[xOffset] & 0xf0) | c);
}
}
private static byte[] g_640x480x16 = new byte[]
{
/* MISC *
0xE3,
/* SEQ *
0x03, 0x01, 0x08, 0x00, 0x06,
/* CRTC *
0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E,
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xEA, 0x0C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xE3,
0xFF,
/* GC *
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x0F,
0xFF,
/* AC *
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
0x01, 0x00, 0x0F, 0x00, 0x00
};
*/
#endregion
#region 720x480x16
/*
private static byte[] g_720x480x16 = new byte[]
{
/* MISC *
0xE7,
/* SEQ *
0x03, 0x01, 0x08, 0x00, 0x06,
/* CRTC *
0x6B, 0x59, 0x5A, 0x82, 0x60, 0x8D, 0x0B, 0x3E,
0x00, 0x40, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
0xEA, 0x0C, 0xDF, 0x2D, 0x08, 0xE8, 0x05, 0xE3,
0xFF,
/* GC *
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x0F,
0xFF,
/* AC *
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x01, 0x00, 0x0F, 0x00, 0x00,
};
*/
#endregion
#region Palette Operations
public void SetPaletteEntry(int index, System.Drawing.Color color)
{
SetPaletteEntry(index, color.R, color.G, color.B);
}
public void SetPalette(int index, byte[] pallete)
{
mIO.DACIndex_Write.Byte = (byte)index;
for (int i = 0; i < pallete.Length; i++)
mIO.DAC_Data.Byte = (byte)(pallete[i] >> 2);
}
public void SetPaletteEntry(int index, byte r, byte g, byte b)
{
mIO.DACIndex_Write.Byte = (byte)index;
mIO.DAC_Data.Byte = (byte)(r >> 2);
mIO.DAC_Data.Byte = (byte)(g >> 2);
mIO.DAC_Data.Byte = (byte)(b >> 2);
}
#endregion
public override void Shutdown()
{
}
}
}