GEN: Preliminary sprite rendering. hook up MemoryDomains.
This commit is contained in:
parent
a95957dcf6
commit
f8564bf8a7
|
@ -8,6 +8,7 @@ namespace BizHawk.Emulation.Consoles.Sega
|
||||||
public Func<int, short> DmaReadFrom68000; // TODO make ushort
|
public Func<int, short> DmaReadFrom68000; // TODO make ushort
|
||||||
|
|
||||||
public int DmaLength { get { return Registers[19] | (Registers[20] << 8); } }
|
public int DmaLength { get { return Registers[19] | (Registers[20] << 8); } }
|
||||||
|
public int DmaMode { get { return (Registers[23] >> 6) & 3; } }
|
||||||
|
|
||||||
public int DmaSource
|
public int DmaSource
|
||||||
{
|
{
|
||||||
|
@ -21,28 +22,26 @@ namespace BizHawk.Emulation.Consoles.Sega
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool DmaFillModePending;
|
bool DmaFillModePending;
|
||||||
|
|
||||||
void ExecuteDmaFill(ushort data)
|
void ExecuteDmaFill(ushort data)
|
||||||
{
|
{
|
||||||
Console.WriteLine("DMA FILL REQD, WRITE {0:X4}, {1:X4} times, at {2:X4}", data, DmaLength, VdpDataAddr);
|
Log.Note("VDP","DMA FILL REQD, WRITE {0:X4}, {1:X4} times, at {2:X4}", data, DmaLength, VdpDataAddr);
|
||||||
|
|
||||||
// TODO: Is the address really VdpDataAddr and not DMA source? I guess that makes sense.
|
|
||||||
// TODO: It should spread this out, not do it all at once.
|
// TODO: It should spread this out, not do it all at once.
|
||||||
// TODO: DMA can go to places besides just VRAM (eg CRAM, VSRAM)
|
// TODO: DMA can go to places besides just VRAM (eg CRAM, VSRAM) ??? can it?
|
||||||
// TODO: Does DMA fill really use the actual increment register value?
|
// TODO: what is this genvdp.txt comment about accurate vdp fill emulation writing some other byte first?
|
||||||
|
|
||||||
int length = DmaLength;
|
int length = DmaLength;
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
length = 0x10000; // Really necessary?
|
length = 0x10000;
|
||||||
|
|
||||||
byte fillByte = (byte)(data >> 8);
|
byte fillByte = (byte)(data >> 8);
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
VRAM[VdpDataAddr & 0xFFFF] = fillByte;
|
VRAM[VdpDataAddr] = fillByte;
|
||||||
UpdatePatternBuffer(VdpDataAddr & 0xFFFF);
|
UpdatePatternBuffer(VdpDataAddr);
|
||||||
VdpDataAddr += Registers[15];
|
VdpDataAddr += Registers[15];
|
||||||
} while (--length > 0);
|
} while (--length > 0);
|
||||||
|
|
||||||
|
@ -51,7 +50,7 @@ namespace BizHawk.Emulation.Consoles.Sega
|
||||||
|
|
||||||
void Execute68000VramCopy()
|
void Execute68000VramCopy()
|
||||||
{
|
{
|
||||||
Console.WriteLine("DMA 68000 -> VRAM COPY REQ'D. LENGTH {0:X4}, SOURCE {1:X4}", DmaLength, DmaSource);
|
Log.Note("VDP", "DMA 68000 -> VRAM COPY REQ'D. LENGTH {0:X4}, SOURCE {1:X4}", DmaLength, DmaSource);
|
||||||
|
|
||||||
int length = DmaLength;
|
int length = DmaLength;
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
|
|
|
@ -8,15 +8,14 @@ namespace BizHawk.Emulation.Consoles.Sega
|
||||||
{
|
{
|
||||||
if (ScanLine == 0)
|
if (ScanLine == 0)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < FrameBuffer.Length; i++)
|
Array.Clear(FrameBuffer, 0, FrameBuffer.Length);
|
||||||
FrameBuffer[i] = 0;
|
|
||||||
|
|
||||||
//RenderPatterns();
|
//RenderPatterns();
|
||||||
RenderPalette();
|
RenderPalette();
|
||||||
RenderScrollA();
|
RenderScrollA();
|
||||||
RenderScrollB();
|
RenderScrollB();
|
||||||
RenderSprites();
|
|
||||||
}
|
}
|
||||||
|
RenderSprites();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderPalette()
|
void RenderPalette()
|
||||||
|
@ -76,33 +75,68 @@ namespace BizHawk.Emulation.Consoles.Sega
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static readonly int[] SpriteSizeTable = { 8, 16, 24, 32 };
|
||||||
|
Sprite sprite;
|
||||||
|
|
||||||
void RenderSprites()
|
void RenderSprites()
|
||||||
{
|
{
|
||||||
Sprite sprite = FetchSprite(0);
|
int scanLineBase = ScanLine * FrameWidth;
|
||||||
/*if (sprite.X > 0)
|
int processedSprites = 0;
|
||||||
Console.WriteLine("doot");*/
|
|
||||||
|
FetchSprite(0);
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (sprite.Y > ScanLine || sprite.Y+sprite.HeightPixels <= ScanLine)
|
||||||
|
goto nextSprite;
|
||||||
|
if (sprite.X + sprite.WidthPixels <= 0)
|
||||||
|
goto nextSprite;
|
||||||
|
|
||||||
|
if (sprite.HeightCells == 2)
|
||||||
|
sprite.HeightCells = 2;
|
||||||
|
|
||||||
|
int yline = ScanLine - sprite.Y;
|
||||||
|
int paletteBase = sprite.Palette * 16;
|
||||||
|
int pattern = sprite.PatternIndex + ((yline / 8));
|
||||||
|
int x = sprite.X;
|
||||||
|
|
||||||
|
for (int xi = 0; xi < sprite.WidthPixels; xi++)
|
||||||
|
{
|
||||||
|
if (sprite.X + xi < 0 || sprite.X + xi > FrameWidth)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int pixel = PatternBuffer[((pattern+((xi/8)*sprite.HeightCells)) * 64) + ((yline & 7) * 8) + (xi & 7)];
|
||||||
|
if (pixel != 0)
|
||||||
|
FrameBuffer[scanLineBase + sprite.X + xi] = Palette[paletteBase + pixel];
|
||||||
|
}
|
||||||
|
|
||||||
|
nextSprite:
|
||||||
|
if (sprite.Link == 0)
|
||||||
|
break;
|
||||||
|
if (++processedSprites > 80)
|
||||||
|
break;
|
||||||
|
FetchSprite(sprite.Link);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Sprite FetchSprite(int spriteNo)
|
void FetchSprite(int spriteNo)
|
||||||
{
|
{
|
||||||
int satbase = SpriteAttributeTableAddr + (spriteNo*8);
|
int satbase = SpriteAttributeTableAddr + (spriteNo*8);
|
||||||
Sprite sprite = new Sprite();
|
sprite.Y = (VRAM[satbase + 0] | (VRAM[satbase + 1] << 8) & 0x3FF) - 128;
|
||||||
sprite.Y = (VRAM[satbase + 1] | (VRAM[satbase + 0] << 8) & 0x3FF) - 128;
|
sprite.X = (VRAM[satbase + 6] | (VRAM[satbase + 7] << 8) & 0x3FF) - 128;
|
||||||
sprite.X = (VRAM[satbase + 7] | (VRAM[satbase + 6] << 8) & 0x3FF) - 128;
|
sprite.WidthPixels = SpriteSizeTable[(VRAM[satbase + 3] >> 2) & 3];
|
||||||
sprite.Width = ((VRAM[satbase + 2] >> 2) & 3) + 1;
|
sprite.HeightPixels = SpriteSizeTable[VRAM[satbase + 3] & 3];
|
||||||
sprite.Height = (VRAM[satbase + 2] & 3) + 1;
|
sprite.WidthCells = ((VRAM[satbase + 3] >> 2) & 3) + 1;
|
||||||
sprite.Link = VRAM[satbase + 3] & 0x7F;
|
sprite.HeightCells = (VRAM[satbase + 3] & 3) + 1;
|
||||||
sprite.PatternIndex = VRAM[satbase + 5] | (VRAM[satbase + 6] << 8) & 0x7FF;
|
sprite.Link = VRAM[satbase + 2] & 0x7F;
|
||||||
|
sprite.PatternIndex = (VRAM[satbase + 4] | (VRAM[satbase + 5] << 8)) & 0x7FF;
|
||||||
sprite.Palette = (VRAM[satbase + 5] >> 5) & 3;
|
sprite.Palette = (VRAM[satbase + 5] >> 5) & 3;
|
||||||
return sprite;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct Sprite
|
struct Sprite
|
||||||
{
|
{
|
||||||
public int X, Y;
|
public int X, Y;
|
||||||
public int Width, Height;
|
public int WidthPixels, HeightPixels;
|
||||||
|
public int WidthCells, HeightCells;
|
||||||
public int Link;
|
public int Link;
|
||||||
public int Palette;
|
public int Palette;
|
||||||
public int PatternIndex;
|
public int PatternIndex;
|
||||||
|
|
|
@ -24,23 +24,23 @@ namespace BizHawk.Emulation.Consoles.Sega
|
||||||
public bool CellBasedVertScroll { get { return (Registers[11] & 0x08) != 0; } }
|
public bool CellBasedVertScroll { get { return (Registers[11] & 0x08) != 0; } }
|
||||||
public bool Display40Mode { get { return (Registers[12] & 0x81) != 0; } }
|
public bool Display40Mode { get { return (Registers[12] & 0x81) != 0; } }
|
||||||
|
|
||||||
private ushort NameTableAddrA;
|
ushort NameTableAddrA;
|
||||||
private ushort NameTableAddrB;
|
ushort NameTableAddrB;
|
||||||
private ushort NameTableAddrWindow;
|
ushort NameTableAddrWindow;
|
||||||
private ushort SpriteAttributeTableAddr;
|
ushort SpriteAttributeTableAddr;
|
||||||
private ushort HScrollTableAddr;
|
ushort HScrollTableAddr;
|
||||||
private byte NameTableWidth;
|
byte NameTableWidth;
|
||||||
private byte NameTableHeight;
|
byte NameTableHeight;
|
||||||
|
|
||||||
private bool ControlWordPending;
|
bool ControlWordPending;
|
||||||
private ushort VdpDataAddr;
|
ushort VdpDataAddr;
|
||||||
private byte VdpDataCode;
|
byte VdpDataCode;
|
||||||
|
|
||||||
private static readonly byte[] PalXlatTable = { 0, 0, 36, 36, 73, 73, 109, 109, 145, 145, 182, 182, 219, 219, 255, 255 };
|
static readonly byte[] PalXlatTable = { 0, 0, 36, 36, 73, 73, 109, 109, 145, 145, 182, 182, 219, 219, 255, 255 };
|
||||||
|
|
||||||
public void WriteVdpControl(ushort data)
|
public void WriteVdpControl(ushort data)
|
||||||
{
|
{
|
||||||
//Console.WriteLine("[PC = {0:X6}] VDP: Control Write {1:X4}", /*Genesis._MainCPU.PC*/0, data);
|
Log.Note("VDP", "VDP: Control Write {0:X4}", data);
|
||||||
|
|
||||||
if (ControlWordPending == false)
|
if (ControlWordPending == false)
|
||||||
{
|
{
|
||||||
|
@ -77,28 +77,28 @@ namespace BizHawk.Emulation.Consoles.Sega
|
||||||
// what type of DMA?
|
// what type of DMA?
|
||||||
switch (Registers[23] >> 6)
|
switch (Registers[23] >> 6)
|
||||||
{
|
{
|
||||||
case 2:
|
case 2:
|
||||||
Console.WriteLine("VRAM FILL");
|
Log.Note("VDP", "VRAM FILL");
|
||||||
DmaFillModePending = true;
|
DmaFillModePending = true;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
Console.WriteLine("VRAM COPY **** UNIMPLEMENTED ***");
|
Log.Note("VDP", "VRAM COPY **** UNIMPLEMENTED ***");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Console.WriteLine("68k->VRAM COPY **** UNIMPLEMENTED ***");
|
Log.Note("VDP", "68k->VRAM COPY");
|
||||||
Execute68000VramCopy();
|
Execute68000VramCopy();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Console.WriteLine("DMA LEN = "+DmaLength);
|
Log.Note("VDP", "DMA LEN = " + DmaLength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ushort ReadVdpControl()
|
public ushort ReadVdpControl()
|
||||||
{
|
{
|
||||||
//Console.WriteLine("VDP: Control Read");
|
|
||||||
ushort value = 0x3400; // fixed bits per genvdp.txt TODO test on everdrive, I guess.
|
ushort value = 0x3400; // fixed bits per genvdp.txt TODO test on everdrive, I guess.
|
||||||
value |= 0x0200; // Fifo empty
|
value |= 0x0200; // Fifo empty
|
||||||
|
Log.Note("VDP", "VDP: Control Read {0:X4}", value);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,40 +144,67 @@ namespace BizHawk.Emulation.Consoles.Sega
|
||||||
|
|
||||||
public ushort ReadVdpData()
|
public ushort ReadVdpData()
|
||||||
{
|
{
|
||||||
//Console.WriteLine("VDP: Data Read");
|
Console.WriteLine("VDP: Data Read");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteVdpRegister(int register, byte data)
|
public void WriteVdpRegister(int register, byte data)
|
||||||
{
|
{
|
||||||
//Console.WriteLine("Register {0}: {1:X2}", register, data);
|
Log.Note("VDP", "Register {0}: {1:X2}", register, data);
|
||||||
switch (register)
|
switch (register)
|
||||||
{
|
{
|
||||||
case 0x00:
|
case 0x00: // Mode Set Register 1
|
||||||
Registers[register] = data;
|
Registers[register] = data;
|
||||||
Console.WriteLine("HINT enabled: "+ HInterruptsEnabled);
|
//Log.Note("VDP", "HINT enabled: " + HInterruptsEnabled);
|
||||||
break;
|
break;
|
||||||
case 0x01:
|
|
||||||
|
case 0x01: // Mode Set Register 2
|
||||||
Registers[register] = data;
|
Registers[register] = data;
|
||||||
Console.WriteLine("DmaEnabled: "+DmaEnabled);
|
//Log.Note("VDP", "DisplayEnabled: " + DisplayEnabled);
|
||||||
Console.WriteLine("VINT enabled: " + VInterruptEnabled);
|
//Log.Note("VDP", "DmaEnabled: " + DmaEnabled);
|
||||||
|
//Log.Note("VDP", "VINT enabled: " + VInterruptEnabled);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x02: // Name Table Address for Layer A
|
case 0x02: // Name Table Address for Layer A
|
||||||
NameTableAddrA = (ushort) ((data & 0x38) << 10);
|
NameTableAddrA = (ushort) ((data & 0x38) << 10);
|
||||||
Console.WriteLine("SET NTa A = {0:X4}",NameTableAddrA);
|
//Log.Note("VDP", "SET NTa A = {0:X4}", NameTableAddrA);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x03: // Name Table Address for Window
|
case 0x03: // Name Table Address for Window
|
||||||
NameTableAddrWindow = (ushort) ((data & 0x3E) << 10);
|
NameTableAddrWindow = (ushort) ((data & 0x3E) << 10);
|
||||||
Console.WriteLine("SET NTa W = {0:X4}", NameTableAddrWindow);
|
//Log.Note("VDP", "SET NTa W = {0:X4}", NameTableAddrWindow);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x04: // Name Table Address for Layer B
|
case 0x04: // Name Table Address for Layer B
|
||||||
NameTableAddrB = (ushort) (data << 13);
|
NameTableAddrB = (ushort) (data << 13);
|
||||||
Console.WriteLine("SET NTa B = {0:X4}", NameTableAddrB);
|
//Log.Note("VDP", "SET NTa B = {0:X4}", NameTableAddrB);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x05: // Sprite Attribute Table Address
|
case 0x05: // Sprite Attribute Table Address
|
||||||
SpriteAttributeTableAddr = (ushort) (data << 9);
|
SpriteAttributeTableAddr = (ushort) (data << 9);
|
||||||
Console.WriteLine("SET SAT attr = {0:X4}", SpriteAttributeTableAddr);
|
//Log.Note("VDP", "SET SAT attr = {0:X4}", SpriteAttributeTableAddr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 0x0A: // H Interrupt Register
|
||||||
|
//Log.Note("VDP", "HInt occurs every {0} lines.", data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x0B: // VScroll/HScroll modes
|
||||||
|
/*if ((data & 4) != 0)
|
||||||
|
Log.Note("VDP", "VSCroll Every 2 Cells Enabled");
|
||||||
|
else
|
||||||
|
Log.Note("VDP", "Full Screen VScroll");*/
|
||||||
|
|
||||||
|
int hscrollmode = data & 3;
|
||||||
|
switch (hscrollmode)
|
||||||
|
{
|
||||||
|
//case 0: Log.Note("VDP", "Full Screen HScroll"); break;
|
||||||
|
//case 1: Log.Note("VDP", "Prohibited HSCROLL mode!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); break;
|
||||||
|
//case 2: Log.Note("VDP", "HScroll every 1 cell"); break;
|
||||||
|
//case 3: Log.Note("VDP", "HScroll every 2 cell"); break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x0C: // Mode Set #4
|
case 0x0C: // Mode Set #4
|
||||||
// TODO interlaced modes
|
// TODO interlaced modes
|
||||||
if ((data & 0x81) == 0)
|
if ((data & 0x81) == 0)
|
||||||
|
@ -187,7 +214,7 @@ namespace BizHawk.Emulation.Consoles.Sega
|
||||||
{
|
{
|
||||||
FrameBuffer = new int[256*224];
|
FrameBuffer = new int[256*224];
|
||||||
FrameWidth = 256;
|
FrameWidth = 256;
|
||||||
Console.WriteLine("SWITCH TO 32 CELL WIDE MODE");
|
//Log.Note("VDP", "SWITCH TO 32 CELL WIDE MODE");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Display is 40 cells wide
|
// Display is 40 cells wide
|
||||||
|
@ -195,18 +222,21 @@ namespace BizHawk.Emulation.Consoles.Sega
|
||||||
{
|
{
|
||||||
FrameBuffer = new int[320*224];
|
FrameBuffer = new int[320*224];
|
||||||
FrameWidth = 320;
|
FrameWidth = 320;
|
||||||
Console.WriteLine("SWITCH TO 40 CELL WIDE MODE");
|
//Log.Note("VDP", "SWITCH TO 40 CELL WIDE MODE");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0D: // H Scroll Table Address
|
case 0x0D: // H Scroll Table Address
|
||||||
HScrollTableAddr = (ushort) (data << 10);
|
HScrollTableAddr = (ushort) (data << 10);
|
||||||
Console.WriteLine("SET HScrollTab attr = {0:X4}", HScrollTableAddr);
|
//Log.Note("VDP", "SET HScrollTab attr = {0:X4}", HScrollTableAddr);
|
||||||
break;
|
break;
|
||||||
case 0x0F:
|
|
||||||
Console.WriteLine("Set Data Increment to "+data);
|
case 0x0F: // Auto Address Register Increment
|
||||||
|
//Log.Note("VDP", "Set Data Increment to " + data);
|
||||||
break;
|
break;
|
||||||
case 0x10:
|
|
||||||
|
case 0x10: // Nametable Dimensions
|
||||||
switch (data & 0x03)
|
switch (data & 0x03)
|
||||||
{
|
{
|
||||||
case 0: NameTableWidth = 32; break;
|
case 0: NameTableWidth = 32; break;
|
||||||
|
@ -221,13 +251,49 @@ namespace BizHawk.Emulation.Consoles.Sega
|
||||||
case 2: NameTableHeight = 32; break; // invalid setting
|
case 2: NameTableHeight = 32; break; // invalid setting
|
||||||
case 3: NameTableHeight = 128; break;
|
case 3: NameTableHeight = 128; break;
|
||||||
}
|
}
|
||||||
Console.WriteLine("Name Table Dimensions set to {0}x{1}", NameTableWidth, NameTableHeight);
|
//Log.Note("VDP", "Name Table Dimensions set to {0}x{1}", NameTableWidth, NameTableHeight);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 0x11: // Window H Position
|
||||||
|
int whp = data & 31;
|
||||||
|
bool fromright = (data & 0x80) != 0;
|
||||||
|
//Log.Note("VDP", "Window H is {0} units from {1}", whp, fromright ? "right" : "left");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x12: // Window V
|
||||||
|
whp = data & 31;
|
||||||
|
fromright = (data & 0x80) != 0;
|
||||||
|
//Log.Note("VDP", "Window V is {0} units from {1}", whp, fromright ? "lower" : "upper");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x13: // DMA Length Low
|
||||||
|
Registers[register] = data;
|
||||||
|
//Log.Note("VDP", "DMA Length = {0:X4}", DmaLength);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x14: // DMA Length High
|
||||||
|
Registers[register] = data;
|
||||||
|
//Log.Note("VDP", "DMA Length = {0:X4}", DmaLength);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x15: // DMA Source Low
|
||||||
|
Registers[register] = data;
|
||||||
|
//Log.Note("VDP", "DMA Source = {0:X6}", DmaSource);
|
||||||
|
break;
|
||||||
|
case 0x16: // DMA Source Mid
|
||||||
|
Registers[register] = data;
|
||||||
|
//Log.Note("VDP", "DMA Source = {0:X6}", DmaSource);
|
||||||
|
break;
|
||||||
|
case 0x17: // DMA Source High
|
||||||
|
Registers[register] = data;
|
||||||
|
//Log.Note("VDP", "DMA Source = {0:X6}", DmaSource);
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
Registers[register] = data;
|
Registers[register] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessPalette(int slot)
|
void ProcessPalette(int slot)
|
||||||
{
|
{
|
||||||
byte r = PalXlatTable[(CRAM[slot] & 0x000F) >> 0];
|
byte r = PalXlatTable[(CRAM[slot] & 0x000F) >> 0];
|
||||||
byte g = PalXlatTable[(CRAM[slot] & 0x00F0) >> 4];
|
byte g = PalXlatTable[(CRAM[slot] & 0x00F0) >> 4];
|
||||||
|
@ -235,7 +301,7 @@ namespace BizHawk.Emulation.Consoles.Sega
|
||||||
Palette[slot] = Colors.ARGB(r, g, b);
|
Palette[slot] = Colors.ARGB(r, g, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdatePatternBuffer(int addr)
|
void UpdatePatternBuffer(int addr)
|
||||||
{
|
{
|
||||||
PatternBuffer[(addr*2) + 1] = (byte) (VRAM[addr^1] & 0x0F);
|
PatternBuffer[(addr*2) + 1] = (byte) (VRAM[addr^1] & 0x0F);
|
||||||
PatternBuffer[(addr*2) + 0] = (byte) (VRAM[addr^1] >> 4);
|
PatternBuffer[(addr*2) + 0] = (byte) (VRAM[addr^1] >> 4);
|
||||||
|
|
|
@ -82,6 +82,7 @@ namespace BizHawk.Emulation.Consoles.Sega
|
||||||
for (int i = 0; i < rom.Length; i++)
|
for (int i = 0; i < rom.Length; i++)
|
||||||
RomData[i] = rom[i];
|
RomData[i] = rom[i];
|
||||||
|
|
||||||
|
SetupMemoryDomains();
|
||||||
MainCPU.Reset();
|
MainCPU.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +92,7 @@ namespace BizHawk.Emulation.Consoles.Sega
|
||||||
PSG.BeginFrame(SoundCPU.TotalExecutedCycles);
|
PSG.BeginFrame(SoundCPU.TotalExecutedCycles);
|
||||||
for (VDP.ScanLine = 0; VDP.ScanLine < 262; VDP.ScanLine++)
|
for (VDP.ScanLine = 0; VDP.ScanLine < 262; VDP.ScanLine++)
|
||||||
{
|
{
|
||||||
Log.Error("VDP","FRAME {0}, SCANLINE {1}", Frame, VDP.ScanLine);
|
//Log.Error("VDP","FRAME {0}, SCANLINE {1}", Frame, VDP.ScanLine);
|
||||||
|
|
||||||
if (VDP.ScanLine < 224)
|
if (VDP.ScanLine < 224)
|
||||||
VDP.RenderLine();
|
VDP.RenderLine();
|
||||||
|
@ -179,8 +180,30 @@ namespace BizHawk.Emulation.Consoles.Sega
|
||||||
return new byte[0];
|
return new byte[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public IList<MemoryDomain> MemoryDomains { get { throw new NotImplementedException(); } }
|
IList<MemoryDomain> memoryDomains;
|
||||||
public MemoryDomain MainMemory { get { throw new NotImplementedException(); } }
|
|
||||||
|
void SetupMemoryDomains()
|
||||||
|
{
|
||||||
|
var domains = new List<MemoryDomain>(3);
|
||||||
|
var MainMemoryDomain = new MemoryDomain("68000 RAM", Ram.Length, Endian.Big,
|
||||||
|
addr => Ram[addr & 0xFFFF],
|
||||||
|
(addr, value) => Ram[addr & 0xFFFF] = value);
|
||||||
|
var Z80Domain = new MemoryDomain("Z80 RAM", Z80Ram.Length, Endian.Little,
|
||||||
|
addr => Z80Ram[addr & 0x1FFF],
|
||||||
|
(addr, value) => { Z80Ram[addr & 0x1FFF] = value; });
|
||||||
|
|
||||||
|
var VRamDomain = new MemoryDomain("Video RAM", VDP.VRAM.Length, Endian.Big,
|
||||||
|
addr => VDP.VRAM[addr & 0xFFFF],
|
||||||
|
(addr, value) => VDP.VRAM[addr & 0xFFFF] = value);
|
||||||
|
|
||||||
|
domains.Add(MainMemoryDomain);
|
||||||
|
domains.Add(Z80Domain);
|
||||||
|
domains.Add(VRamDomain);
|
||||||
|
memoryDomains = domains.AsReadOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IList<MemoryDomain> MemoryDomains { get { return memoryDomains; } }
|
||||||
|
public MemoryDomain MainMemory { get { return memoryDomains[0]; } }
|
||||||
|
|
||||||
public void Dispose() { }
|
public void Dispose() { }
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
|
|
||||||
case 0x04: return IOPorts[0].Control;
|
case 0x04: return IOPorts[0].Control;
|
||||||
case 0x05: return IOPorts[1].Control;
|
case 0x05: return IOPorts[1].Control;
|
||||||
case 0x06: return 0xFF;// IOPorts[2].Control; TODO hack? returning FF fixes revenge of shinobi and strider. investigate later.
|
case 0x06: return 0xFF;// return IOPorts[2].Control; //TODO hack? returning FF fixes revenge of shinobi and strider. investigate later.
|
||||||
|
|
||||||
case 0x07: return IOPorts[0].TxData;
|
case 0x07: return IOPorts[0].TxData;
|
||||||
case 0x08: return IOPorts[0].RxData;
|
case 0x08: return IOPorts[0].RxData;
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace BizHawk.Emulation.Consoles.Sega
|
||||||
|
|
||||||
if (address == 0xA11100) // Z80 BUS status
|
if (address == 0xA11100) // Z80 BUS status
|
||||||
{
|
{
|
||||||
Console.WriteLine("QUERY z80 bus status. 68000 can access? " + (M68000HasZ80Bus && Z80Reset == false));
|
//Console.WriteLine("QUERY z80 bus status. 68000 can access? " + (M68000HasZ80Bus && Z80Reset == false));
|
||||||
return (sbyte) (M68000HasZ80Bus && Z80Reset == false ? 0 : 1);
|
return (sbyte) (M68000HasZ80Bus && Z80Reset == false ? 0 : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,13 +69,17 @@ namespace BizHawk.Emulation.Consoles.Sega
|
||||||
int maskedAddr;
|
int maskedAddr;
|
||||||
if (address < 0x400000) // Cartridge ROM
|
if (address < 0x400000) // Cartridge ROM
|
||||||
return (RomData[address] << 24) | (RomData[address + 1] << 16) | (RomData[address + 2] << 8) | RomData[address + 3];
|
return (RomData[address] << 24) | (RomData[address + 1] << 16) | (RomData[address + 2] << 8) | RomData[address + 3];
|
||||||
|
|
||||||
if (address >= 0xE00000) // Work RAM
|
if (address >= 0xE00000) // Work RAM
|
||||||
{
|
{
|
||||||
maskedAddr = address & 0xFFFF;
|
maskedAddr = address & 0xFFFF;
|
||||||
return (Ram[maskedAddr] << 24) | (Ram[maskedAddr + 1] << 16) | (Ram[maskedAddr + 2] << 8) | Ram[maskedAddr + 3];
|
return (Ram[maskedAddr] << 24) | (Ram[maskedAddr + 1] << 16) | (Ram[maskedAddr + 2] << 8) | Ram[maskedAddr + 3];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// try to handle certain things separate if they need to be separate? otherwise handle as 2x readwords?
|
||||||
|
{
|
||||||
|
return ((ushort)ReadWord(address) | (ushort)(ReadWord(address + 2) << 16));
|
||||||
|
}
|
||||||
if (address == 0xA10008) return 0; // FIXME HACK for tg-sync.
|
if (address == 0xA10008) return 0; // FIXME HACK for tg-sync.
|
||||||
|
|
||||||
Console.WriteLine("UNHANDLED READL {0:X6}", address);
|
Console.WriteLine("UNHANDLED READL {0:X6}", address);
|
||||||
|
@ -105,7 +109,7 @@ namespace BizHawk.Emulation.Consoles.Sega
|
||||||
if (address == 0xA11100)
|
if (address == 0xA11100)
|
||||||
{
|
{
|
||||||
M68000HasZ80Bus = (value & 1) != 0;
|
M68000HasZ80Bus = (value & 1) != 0;
|
||||||
Console.WriteLine("68000 has the z80 bus: " + M68000HasZ80Bus);
|
//Console.WriteLine("68000 has the z80 bus: " + M68000HasZ80Bus);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (address == 0xA11200) // Z80 RESET
|
if (address == 0xA11200) // Z80 RESET
|
||||||
|
@ -113,7 +117,7 @@ namespace BizHawk.Emulation.Consoles.Sega
|
||||||
Z80Reset = (value & 1) == 0;
|
Z80Reset = (value & 1) == 0;
|
||||||
if (Z80Reset)
|
if (Z80Reset)
|
||||||
SoundCPU.Reset();
|
SoundCPU.Reset();
|
||||||
Console.WriteLine("z80 reset: " + Z80Reset);
|
//Console.WriteLine("z80 reset: " + Z80Reset);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (address >= 0xC00000)
|
if (address >= 0xC00000)
|
||||||
|
@ -170,7 +174,7 @@ namespace BizHawk.Emulation.Consoles.Sega
|
||||||
if (address == 0xA11100) // Z80 BUSREQ
|
if (address == 0xA11100) // Z80 BUSREQ
|
||||||
{
|
{
|
||||||
M68000HasZ80Bus = (value & 0x100) != 0;
|
M68000HasZ80Bus = (value & 0x100) != 0;
|
||||||
Console.WriteLine("68000 has the z80 bus: " + M68000HasZ80Bus);
|
//Console.WriteLine("68000 has the z80 bus: " + M68000HasZ80Bus);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (address == 0xA11200) // Z80 RESET
|
if (address == 0xA11200) // Z80 RESET
|
||||||
|
@ -178,7 +182,7 @@ namespace BizHawk.Emulation.Consoles.Sega
|
||||||
Z80Reset = (value & 0x100) == 0;
|
Z80Reset = (value & 0x100) == 0;
|
||||||
if (Z80Reset)
|
if (Z80Reset)
|
||||||
SoundCPU.Reset();
|
SoundCPU.Reset();
|
||||||
Console.WriteLine("z80 reset: " + Z80Reset);
|
//Console.WriteLine("z80 reset: " + Z80Reset);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Console.WriteLine("UNHANDLED WRITEW {0:X6}:{1:X4}", address, value);
|
Console.WriteLine("UNHANDLED WRITEW {0:X6}:{1:X4}", address, value);
|
||||||
|
|
|
@ -16,13 +16,15 @@ namespace BizHawk.Emulation.Consoles.Sega
|
||||||
if (address >= 0x4000 && address < 0x6000)
|
if (address >= 0x4000 && address < 0x6000)
|
||||||
{
|
{
|
||||||
//Console.WriteLine(" === Z80 READS FM STATUS ===");
|
//Console.WriteLine(" === Z80 READS FM STATUS ===");
|
||||||
return YM2612.ReadStatus();
|
return YM2612.ReadStatus(); // TODO: more than 1 read port probably?
|
||||||
}
|
}
|
||||||
if (address >= 0x8000)
|
if (address >= 0x8000)
|
||||||
{
|
{
|
||||||
// 68000 Bank region
|
// 68000 Bank region
|
||||||
return (byte) ReadByte(BankRegion | (address & 0x7FFF));
|
return (byte) ReadByte(BankRegion | (address & 0x7FFF));
|
||||||
}
|
}
|
||||||
|
if (address <= 0x6100) // read from bank address register - returns FF
|
||||||
|
return 0xFF;
|
||||||
Console.WriteLine("UNHANDLED Z80 READ {0:X4}",address);
|
Console.WriteLine("UNHANDLED Z80 READ {0:X4}",address);
|
||||||
return 0xCD;
|
return 0xCD;
|
||||||
}
|
}
|
||||||
|
@ -37,18 +39,40 @@ namespace BizHawk.Emulation.Consoles.Sega
|
||||||
}
|
}
|
||||||
if (address >= 0x4000 && address < 0x6000)
|
if (address >= 0x4000 && address < 0x6000)
|
||||||
{
|
{
|
||||||
//Console.WriteLine(" === Z80 WRITES Z80 {0:X4}:{1:X2} ===",address, value);
|
//Console.WriteLine(" === Z80 WRITES YM2612 {0:X4}:{1:X2} ===",address, value);
|
||||||
YM2612.Write(address & 3, value);
|
YM2612.Write(address & 3, value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (address == 0x6000)
|
if (address < 0x6100)
|
||||||
{
|
{
|
||||||
BankRegion >>= 1;
|
BankRegion >>= 1;
|
||||||
BankRegion |= (value & 1) << 23;
|
BankRegion |= (value & 1) << 23;
|
||||||
BankRegion &= 0x00FF8000;
|
BankRegion &= 0x00FF8000;
|
||||||
Console.WriteLine("Bank pointing at {0:X8}",BankRegion);
|
//Console.WriteLine("Bank pointing at {0:X8}",BankRegion);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (address >= 0x7F00 && address < 0x7F20)
|
||||||
|
{
|
||||||
|
switch (address & 0x1F)
|
||||||
|
{
|
||||||
|
case 0x00:
|
||||||
|
case 0x02:
|
||||||
|
VDP.WriteVdpData((ushort) ((value<<8) | value));
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 0x04:
|
||||||
|
case 0x06:
|
||||||
|
VDP.WriteVdpControl((ushort)((value << 8) | value));
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 0x11:
|
||||||
|
case 0x13:
|
||||||
|
case 0x15:
|
||||||
|
case 0x17:
|
||||||
|
PSG.WritePsgData(value, SoundCPU.TotalExecutedCycles);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (address >= 0x8000)
|
if (address >= 0x8000)
|
||||||
{
|
{
|
||||||
WriteByte(BankRegion | (address & 0x7FFF), (sbyte) value);
|
WriteByte(BankRegion | (address & 0x7FFF), (sbyte) value);
|
||||||
|
|
Loading…
Reference in New Issue