forked from sin365/AxibugEmuOnline
ppu lpScreen改为指针版本
This commit is contained in:
parent
3913595b18
commit
43e7ba8332
@ -51,7 +51,7 @@ namespace AxibugEmuOnline.Client
|
|||||||
NesCore = null;
|
NesCore = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Update()
|
private unsafe void Update()
|
||||||
{
|
{
|
||||||
if (m_bPause) return;
|
if (m_bPause) return;
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ namespace AxibugEmuOnline.Client
|
|||||||
|
|
||||||
var screenBuffer = NesCore.ppu.GetScreenPtr();
|
var screenBuffer = NesCore.ppu.GetScreenPtr();
|
||||||
var lineColorMode = NesCore.ppu.GetLineColorMode();
|
var lineColorMode = NesCore.ppu.GetLineColorMode();
|
||||||
VideoProvider.SetDrawData(screenBuffer, lineColorMode, 256, 240);
|
VideoProvider.SetDrawData(screenBuffer, lineColorMode, 277, 240);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,15 +24,15 @@ namespace AxibugEmuOnline.Client
|
|||||||
DrawCanvas.worldCamera = Camera.main;
|
DrawCanvas.worldCamera = Camera.main;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetDrawData(uint[] screenData, byte[] lineColorMode, int screenWidth, int screenHeight)
|
public unsafe void SetDrawData(byte* screenData, byte[] lineColorMode, int screenWidth, int screenHeight)
|
||||||
{
|
{
|
||||||
if (wrapTex == null)
|
if (wrapTex == null)
|
||||||
{
|
{
|
||||||
//wrapTex = new Texture2D(272, 240, TextureFormat.BGRA32, false);
|
//wrapTex = new Texture2D(272, 240, TextureFormat.BGRA32, false);
|
||||||
wrapTex = new Texture2D(272, 240, TextureFormat.RGBA32, false);
|
wrapTex = new Texture2D(272, 240, TextureFormat.RGBA32, false);
|
||||||
wrapTex.filterMode = FilterMode.Point;
|
wrapTex.filterMode = FilterMode.Point;
|
||||||
wrapTexBuffer = screenData;
|
|
||||||
|
|
||||||
|
wrapTexBuffer = new uint[screenWidth * screenHeight];
|
||||||
// 固定数组,防止垃圾回收器移动它
|
// 固定数组,防止垃圾回收器移动它
|
||||||
GCHandle handle = GCHandle.Alloc(wrapTexBuffer, GCHandleType.Pinned);
|
GCHandle handle = GCHandle.Alloc(wrapTexBuffer, GCHandleType.Pinned);
|
||||||
// 获取数组的指针
|
// 获取数组的指针
|
||||||
@ -44,7 +44,6 @@ namespace AxibugEmuOnline.Client
|
|||||||
TexBufferSize = wrapTexBuffer.Length * 4;
|
TexBufferSize = wrapTexBuffer.Length * 4;
|
||||||
|
|
||||||
var palRaw = PaletteDefine.m_cnPalette[0];
|
var palRaw = PaletteDefine.m_cnPalette[0];
|
||||||
//pPal = new Texture2D(palRaw.Length, 1, TextureFormat.BGRA32, 1, true);
|
|
||||||
pPal = new Texture2D(palRaw.Length, 1, TextureFormat.RGBA32, false);
|
pPal = new Texture2D(palRaw.Length, 1, TextureFormat.RGBA32, false);
|
||||||
pPal.filterMode = FilterMode.Point;
|
pPal.filterMode = FilterMode.Point;
|
||||||
for (int i = 0; i < palRaw.Length; i++)
|
for (int i = 0; i < palRaw.Length; i++)
|
||||||
@ -62,6 +61,11 @@ namespace AxibugEmuOnline.Client
|
|||||||
Image.material.SetTexture("_PalTex", pPal);
|
Image.material.SetTexture("_PalTex", pPal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < wrapTexBuffer.Length; i++)
|
||||||
|
{
|
||||||
|
wrapTexBuffer[i] = screenData[i];
|
||||||
|
}
|
||||||
|
|
||||||
wrapTex.LoadRawTextureData(wrapTexBufferPointer, TexBufferSize);
|
wrapTex.LoadRawTextureData(wrapTexBufferPointer, TexBufferSize);
|
||||||
wrapTex.Apply();
|
wrapTex.Apply();
|
||||||
}
|
}
|
||||||
|
@ -221,7 +221,7 @@ namespace VirtualNes.Core
|
|||||||
Debuger.Log("Allocating PPU...");
|
Debuger.Log("Allocating PPU...");
|
||||||
ppu = new PPU(this);
|
ppu = new PPU(this);
|
||||||
|
|
||||||
var screenBuffer = new uint[PPU.SCREEN_WIDTH * PPU.SCREEN_HEIGHT];
|
var screenBuffer = new byte[PPU.SCREEN_WIDTH * PPU.SCREEN_HEIGHT];
|
||||||
var colormode = new byte[PPU.SCREEN_HEIGHT];
|
var colormode = new byte[PPU.SCREEN_HEIGHT];
|
||||||
|
|
||||||
ppu.SetScreenPtr(screenBuffer, colormode);
|
ppu.SetScreenPtr(screenBuffer, colormode);
|
||||||
@ -840,7 +840,7 @@ namespace VirtualNes.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void DrawFont(int x, int y, byte chr, byte col)
|
internal unsafe void DrawFont(int x, int y, byte chr, byte col)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int pFnt;
|
int pFnt;
|
||||||
@ -866,7 +866,7 @@ namespace VirtualNes.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawBitmap(int x, int y, byte[] bitMap)
|
private unsafe void DrawBitmap(int x, int y, byte[] bitMap)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
int h, v;
|
int h, v;
|
||||||
|
@ -1,10 +1,24 @@
|
|||||||
namespace VirtualNes.Core
|
using Codice.CM.Client.Differences;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
|
namespace VirtualNes.Core
|
||||||
{
|
{
|
||||||
public class PPU
|
public unsafe class PPU
|
||||||
{
|
{
|
||||||
public const int SCREEN_WIDTH = 256 + 16;
|
public const int SCREEN_WIDTH = 272;
|
||||||
public const int SCREEN_HEIGHT = 240;
|
public const int SCREEN_HEIGHT = 240;
|
||||||
|
|
||||||
|
private GCHandle BGwriteGCH;
|
||||||
|
private GCHandle BGmonoGCH;
|
||||||
|
private GCHandle SPwriteGCH;
|
||||||
|
|
||||||
|
private byte* BGwrite;
|
||||||
|
private byte* BGmono;
|
||||||
|
private byte* SPwrite;
|
||||||
|
|
||||||
private static byte[][] CreateCOLORMAP()
|
private static byte[][] CreateCOLORMAP()
|
||||||
{
|
{
|
||||||
byte[][] res = new byte[5][];
|
byte[][] res = new byte[5][];
|
||||||
@ -104,9 +118,10 @@
|
|||||||
private ushort loopy_y;
|
private ushort loopy_y;
|
||||||
private ushort loopy_shift;
|
private ushort loopy_shift;
|
||||||
|
|
||||||
private uint[] lpScreen;
|
private GCHandle lpScreenGCH;
|
||||||
|
private byte* lpScreen;
|
||||||
/// <summary> 作为lpScreen数组的索引 </summary>
|
/// <summary> 作为lpScreen数组的索引 </summary>
|
||||||
private int lpScanline;
|
private byte* lpScanline;
|
||||||
private int ScanlineNo;
|
private int ScanlineNo;
|
||||||
private byte[] lpColormode;
|
private byte[] lpColormode;
|
||||||
|
|
||||||
@ -137,9 +152,22 @@
|
|||||||
}
|
}
|
||||||
Bit2Rev[i] = c;
|
Bit2Rev[i] = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BGwriteGCH = GCHandle.Alloc(new byte[33 + 1], GCHandleType.Pinned);
|
||||||
|
BGmonoGCH = GCHandle.Alloc(new byte[33 + 1], GCHandleType.Pinned);
|
||||||
|
SPwriteGCH = GCHandle.Alloc(new byte[33 + 1], GCHandleType.Pinned);
|
||||||
|
BGwrite = (byte*)BGwriteGCH.AddrOfPinnedObject();
|
||||||
|
BGmono = (byte*)BGmonoGCH.AddrOfPinnedObject();
|
||||||
|
SPwrite = (byte*)SPwriteGCH.AddrOfPinnedObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() { }
|
public void Dispose()
|
||||||
|
{
|
||||||
|
lpScreenGCH.Free();
|
||||||
|
BGwriteGCH.Free();
|
||||||
|
BGmonoGCH.Free();
|
||||||
|
SPwriteGCH.Free();
|
||||||
|
}
|
||||||
|
|
||||||
internal byte Read(ushort addr)
|
internal byte Read(ushort addr)
|
||||||
{
|
{
|
||||||
@ -199,7 +227,7 @@
|
|||||||
ScanlineNo = scanline;
|
ScanlineNo = scanline;
|
||||||
if (scanline < 240)
|
if (scanline < 240)
|
||||||
{
|
{
|
||||||
lpScanline = (SCREEN_WIDTH) * scanline;
|
lpScanline = lpScreen + SCREEN_WIDTH * scanline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,7 +386,7 @@
|
|||||||
loopy_shift = 0;
|
loopy_shift = 0;
|
||||||
|
|
||||||
if (lpScreen != null)
|
if (lpScreen != null)
|
||||||
MemoryUtility.memset(lpScreen, 0, 0x3F, SCREEN_WIDTH * SCREEN_HEIGHT);
|
Unsafe.InitBlockUnaligned(lpScreen, 0, SCREEN_WIDTH * SCREEN_HEIGHT);
|
||||||
if (lpColormode != null)
|
if (lpColormode != null)
|
||||||
MemoryUtility.memset(lpColormode, 0, SCREEN_HEIGHT);
|
MemoryUtility.memset(lpColormode, 0, SCREEN_HEIGHT);
|
||||||
}
|
}
|
||||||
@ -374,7 +402,7 @@
|
|||||||
|
|
||||||
if (lpScreen != null)
|
if (lpScreen != null)
|
||||||
{
|
{
|
||||||
MemoryUtility.memset(lpScreen, 0, 0x3F, SCREEN_WIDTH);
|
Unsafe.InitBlockUnaligned(lpScreen, 0x3F, SCREEN_WIDTH);
|
||||||
}
|
}
|
||||||
if (lpColormode != null)
|
if (lpColormode != null)
|
||||||
{
|
{
|
||||||
@ -425,18 +453,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] BGwrite = new byte[33 + 1];
|
|
||||||
private byte[] BGmono = new byte[33 + 1];
|
|
||||||
private byte[] SPwrite = new byte[33 + 1];
|
|
||||||
|
|
||||||
internal void Scanline(int scanline, bool bMax, bool bLeftClip)
|
internal void Scanline(int scanline, bool bMax, bool bLeftClip)
|
||||||
{
|
{
|
||||||
int pScn = 0;
|
|
||||||
int pBGw = 0;
|
|
||||||
byte chr_h = 0, chr_l = 0, attr = 0;
|
byte chr_h = 0, chr_l = 0, attr = 0;
|
||||||
|
|
||||||
MemoryUtility.ZEROMEMORY(BGwrite, BGwrite.Length);
|
Unsafe.InitBlockUnaligned(BGwrite, 0, 34);
|
||||||
MemoryUtility.ZEROMEMORY(BGmono, BGmono.Length);
|
Unsafe.InitBlockUnaligned(BGmono, 0, 34);
|
||||||
|
|
||||||
// Linecolor mode
|
// Linecolor mode
|
||||||
lpColormode[scanline] = (byte)(((MMU.PPUREG[1] & PPU_BGCOLOR_BIT) >> 5) | ((MMU.PPUREG[1] & PPU_COLORMODE_BIT) << 7));
|
lpColormode[scanline] = (byte)(((MMU.PPUREG[1] & PPU_BGCOLOR_BIT) >> 5) | ((MMU.PPUREG[1] & PPU_COLORMODE_BIT) << 7));
|
||||||
@ -444,7 +466,7 @@
|
|||||||
// Render BG
|
// Render BG
|
||||||
if ((MMU.PPUREG[1] & PPU_BGDISP_BIT) == 0)
|
if ((MMU.PPUREG[1] & PPU_BGDISP_BIT) == 0)
|
||||||
{
|
{
|
||||||
MemoryUtility.memset(lpScreen, lpScanline, MMU.BGPAL[0], SCREEN_WIDTH);
|
Unsafe.InitBlockUnaligned(lpScanline, MMU.BGPAL[0], SCREEN_WIDTH);
|
||||||
if (nes.GetRenderMethod() == EnumRenderMethod.TILE_RENDER)
|
if (nes.GetRenderMethod() == EnumRenderMethod.TILE_RENDER)
|
||||||
{
|
{
|
||||||
nes.EmulationCPU(NES.FETCH_CYCLES * 4 * 32);
|
nes.EmulationCPU(NES.FETCH_CYCLES * 4 * 32);
|
||||||
@ -457,9 +479,8 @@
|
|||||||
if (!bExtLatch)
|
if (!bExtLatch)
|
||||||
{
|
{
|
||||||
// Without Extension Latch
|
// Without Extension Latch
|
||||||
pScn = lpScanline + (8 - loopy_shift);
|
byte* pScn = lpScanline + (8 - loopy_shift);
|
||||||
pBGw = 0;
|
byte* pBGw = BGwrite;
|
||||||
|
|
||||||
int tileofs = (MMU.PPUREG[0] & PPU_BGTBL_BIT) << 8;
|
int tileofs = (MMU.PPUREG[0] & PPU_BGTBL_BIT) << 8;
|
||||||
int ntbladr = 0x2000 + (MMU.loopy_v & 0x0FFF);
|
int ntbladr = 0x2000 + (MMU.loopy_v & 0x0FFF);
|
||||||
int attradr = 0x23C0 + (MMU.loopy_v & 0x0C00) + ((MMU.loopy_v & 0x0380) >> 4);
|
int attradr = 0x23C0 + (MMU.loopy_v & 0x0C00) + ((MMU.loopy_v & 0x0380) >> 4);
|
||||||
@ -475,7 +496,6 @@
|
|||||||
|
|
||||||
attradr &= 0x3FF;
|
attradr &= 0x3FF;
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < 33; i++)
|
for (int i = 0; i < 33; i++)
|
||||||
{
|
{
|
||||||
tileadr = tileofs + pNTBL[ntbladr & 0x03FF] * 0x10 + loopy_y;
|
tileadr = tileofs + pNTBL[ntbladr & 0x03FF] * 0x10 + loopy_y;
|
||||||
@ -483,17 +503,9 @@
|
|||||||
|
|
||||||
if (cache_tile == tileadr && cache_attr == attr)
|
if (cache_tile == tileadr && cache_attr == attr)
|
||||||
{
|
{
|
||||||
lpScreen[pScn + 0] = lpScreen[pScn - 8];
|
*(uint*)(pScn + 0) = *(uint*)(pScn - 8);
|
||||||
lpScreen[pScn + 0 + 1] = lpScreen[pScn - 8 + 1];
|
*(uint*)(pScn + 4) = *(uint*)(pScn - 4);
|
||||||
lpScreen[pScn + 0 + 2] = lpScreen[pScn - 8 + 2];
|
*(pBGw + 0) = *(pBGw - 1);
|
||||||
lpScreen[pScn + 0 + 3] = lpScreen[pScn - 8 + 3];
|
|
||||||
|
|
||||||
lpScreen[pScn + 4] = lpScreen[pScn - 4];
|
|
||||||
lpScreen[pScn + 4 + 1] = lpScreen[pScn - 4 + 1];
|
|
||||||
lpScreen[pScn + 4 + 2] = lpScreen[pScn - 4 + 2];
|
|
||||||
lpScreen[pScn + 4 + 3] = lpScreen[pScn - 4 + 3];
|
|
||||||
|
|
||||||
BGwrite[pBGw + 0] = BGwrite[pBGw - 1];
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -501,20 +513,20 @@
|
|||||||
cache_attr = attr;
|
cache_attr = attr;
|
||||||
chr_l = MMU.PPU_MEM_BANK[tileadr >> 10][tileadr & 0x03FF];
|
chr_l = MMU.PPU_MEM_BANK[tileadr >> 10][tileadr & 0x03FF];
|
||||||
chr_h = MMU.PPU_MEM_BANK[tileadr >> 10][(tileadr & 0x03FF) + 8];
|
chr_h = MMU.PPU_MEM_BANK[tileadr >> 10][(tileadr & 0x03FF) + 8];
|
||||||
BGwrite[pBGw] = (byte)(chr_h | chr_l);
|
*pBGw = (byte)(chr_h | chr_l);
|
||||||
|
|
||||||
int pBGPAL = attr;
|
fixed (byte* pBGPAL = &MMU.BGPAL[attr])
|
||||||
{
|
{
|
||||||
int c1 = ((chr_l >> 1) & 0x55) | (chr_h & 0xAA);
|
int c1 = ((chr_l >> 1) & 0x55) | (chr_h & 0xAA);
|
||||||
int c2 = (chr_l & 0x55) | ((chr_h << 1) & 0xAA);
|
int c2 = (chr_l & 0x55) | ((chr_h << 1) & 0xAA);
|
||||||
lpScreen[pScn + 0] = MMU.BGPAL[pBGPAL + (c1 >> 6)];
|
pScn[0] = pBGPAL[(c1 >> 6)];
|
||||||
lpScreen[pScn + 4] = MMU.BGPAL[pBGPAL + ((c1 >> 2) & 3)];
|
pScn[4] = pBGPAL[(c1 >> 2) & 3];
|
||||||
lpScreen[pScn + 1] = MMU.BGPAL[pBGPAL + ((c1 >> 6))];
|
pScn[1] = pBGPAL[(c2 >> 6)];
|
||||||
lpScreen[pScn + 5] = MMU.BGPAL[pBGPAL + ((c2 >> 2) & 3)];
|
pScn[5] = pBGPAL[(c2 >> 2) & 3];
|
||||||
lpScreen[pScn + 2] = MMU.BGPAL[pBGPAL + ((c1 >> 4) & 3)];
|
pScn[2] = pBGPAL[(c1 >> 4) & 3];
|
||||||
lpScreen[pScn + 6] = MMU.BGPAL[pBGPAL + (c1 & 3)];
|
pScn[6] = pBGPAL[c1 & 3];
|
||||||
lpScreen[pScn + 3] = MMU.BGPAL[pBGPAL + ((c2 >> 4) & 3)];
|
pScn[3] = pBGPAL[(c2 >> 4) & 3];
|
||||||
lpScreen[pScn + 7] = MMU.BGPAL[pBGPAL + (c2 & 3)];
|
pScn[7] = pBGPAL[c2 & 3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pScn += 8;
|
pScn += 8;
|
||||||
@ -542,8 +554,8 @@
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// With Extension Latch(For MMC5)
|
// With Extension Latch(For MMC5)
|
||||||
pScn = lpScanline + (8 - loopy_shift);
|
byte* pScn = lpScanline + (8 - loopy_shift);
|
||||||
pBGw = 0;
|
byte* pBGw = BGwrite;
|
||||||
|
|
||||||
int ntbladr = 0x2000 + (MMU.loopy_v & 0x0FFF);
|
int ntbladr = 0x2000 + (MMU.loopy_v & 0x0FFF);
|
||||||
int ntbl_x = ntbladr & 0x1F;
|
int ntbl_x = ntbladr & 0x1F;
|
||||||
@ -564,35 +576,27 @@
|
|||||||
{
|
{
|
||||||
cache_tile = ((chr_h << 8) + chr_l);
|
cache_tile = ((chr_h << 8) + chr_l);
|
||||||
cache_attr = attr;
|
cache_attr = attr;
|
||||||
BGwrite[pBGw] = (byte)(chr_h | chr_l);
|
*pBGw = (byte)(chr_h | chr_l);
|
||||||
|
|
||||||
int pBGPAL = attr;
|
fixed (byte* pBGPAL = &MMU.BGPAL[attr])
|
||||||
{
|
{
|
||||||
int c1 = ((chr_l >> 1) & 0x55) | (chr_h & 0xAA);
|
int c1 = ((chr_l >> 1) & 0x55) | (chr_h & 0xAA);
|
||||||
int c2 = (chr_l & 0x55) | ((chr_h << 1) & 0xAA);
|
int c2 = (chr_l & 0x55) | ((chr_h << 1) & 0xAA);
|
||||||
lpScreen[pScn + 0] = MMU.BGPAL[pBGPAL + (c1 >> 6)];
|
pScn[0] = pBGPAL[(c1 >> 6)];
|
||||||
lpScreen[pScn + 4] = MMU.BGPAL[pBGPAL + ((c1 >> 2) & 3)];
|
pScn[4] = pBGPAL[(c1 >> 2) & 3];
|
||||||
lpScreen[pScn + 1] = MMU.BGPAL[pBGPAL + (c2 >> 6)];
|
pScn[1] = pBGPAL[(c2 >> 6)];
|
||||||
lpScreen[pScn + 5] = MMU.BGPAL[pBGPAL + ((c2 >> 2) & 3)];
|
pScn[5] = pBGPAL[(c2 >> 2) & 3];
|
||||||
lpScreen[pScn + 2] = MMU.BGPAL[pBGPAL + ((c1 >> 4) & 3)];
|
pScn[2] = pBGPAL[(c1 >> 4) & 3];
|
||||||
lpScreen[pScn + 6] = MMU.BGPAL[pBGPAL + (c1 & 3)];
|
pScn[6] = pBGPAL[c1 & 3];
|
||||||
lpScreen[pScn + 3] = MMU.BGPAL[pBGPAL + ((c2 >> 4) & 3)];
|
pScn[3] = pBGPAL[(c2 >> 4) & 3];
|
||||||
lpScreen[pScn + 7] = MMU.BGPAL[pBGPAL + (c2 & 3)];
|
pScn[7] = pBGPAL[c2 & 3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lpScreen[pScn + 0] = lpScreen[pScn - 8];
|
*(uint*)(pScn + 0) = *(uint*)(pScn - 8);
|
||||||
lpScreen[pScn + 0 + 1] = lpScreen[pScn - 8 + 1];
|
*(uint*)(pScn + 4) = *(uint*)(pScn - 4);
|
||||||
lpScreen[pScn + 0 + 2] = lpScreen[pScn - 8 + 2];
|
*(pBGw + 0) = *(pBGw - 1);
|
||||||
lpScreen[pScn + 0 + 3] = lpScreen[pScn - 8 + 3];
|
|
||||||
|
|
||||||
lpScreen[pScn + 4] = lpScreen[pScn - 4];
|
|
||||||
lpScreen[pScn + 4 + 1] = lpScreen[pScn - 4 + 1];
|
|
||||||
lpScreen[pScn + 4 + 2] = lpScreen[pScn - 4 + 2];
|
|
||||||
lpScreen[pScn + 4 + 3] = lpScreen[pScn - 4 + 3];
|
|
||||||
|
|
||||||
BGwrite[pBGw + 0] = BGwrite[pBGw - 1];
|
|
||||||
}
|
}
|
||||||
pScn += 8;
|
pScn += 8;
|
||||||
pBGw++;
|
pBGw++;
|
||||||
@ -616,8 +620,8 @@
|
|||||||
// Without Extension Latch
|
// Without Extension Latch
|
||||||
if (!bExtNameTable)
|
if (!bExtNameTable)
|
||||||
{
|
{
|
||||||
pScn = lpScanline + (8 - loopy_shift);
|
byte* pScn = lpScanline + (8 - loopy_shift);
|
||||||
pBGw = 0;
|
byte* pBGw = BGwrite;
|
||||||
|
|
||||||
int ntbladr = 0x2000 + (MMU.loopy_v & 0x0FFF);
|
int ntbladr = 0x2000 + (MMU.loopy_v & 0x0FFF);
|
||||||
int attradr = 0x03C0 + ((MMU.loopy_v & 0x0380) >> 4);
|
int attradr = 0x03C0 + ((MMU.loopy_v & 0x0380) >> 4);
|
||||||
@ -649,35 +653,27 @@
|
|||||||
|
|
||||||
chr_l = MMU.PPU_MEM_BANK[tileadr >> 10][tileadr & 0x03FF];
|
chr_l = MMU.PPU_MEM_BANK[tileadr >> 10][tileadr & 0x03FF];
|
||||||
chr_h = MMU.PPU_MEM_BANK[tileadr >> 10][(tileadr & 0x03FF) + 8];
|
chr_h = MMU.PPU_MEM_BANK[tileadr >> 10][(tileadr & 0x03FF) + 8];
|
||||||
lpScreen[pBGw] = (byte)(chr_l | chr_h);
|
*pBGw = (byte)(chr_l | chr_h);
|
||||||
|
|
||||||
int pBGPAL = attr;
|
fixed (byte* pBGPAL = &MMU.BGPAL[attr])
|
||||||
{
|
{
|
||||||
int c1 = ((chr_l >> 1) & 0x55) | (chr_h & 0xAA);
|
int c1 = ((chr_l >> 1) & 0x55) | (chr_h & 0xAA);
|
||||||
int c2 = (chr_l & 0x55) | ((chr_h << 1) & 0xAA);
|
int c2 = (chr_l & 0x55) | ((chr_h << 1) & 0xAA);
|
||||||
lpScreen[pScn + 0] = MMU.BGPAL[pBGPAL + (c1 >> 6)];
|
pScn[0] = pBGPAL[(c1 >> 6)];
|
||||||
lpScreen[pScn + 4] = MMU.BGPAL[pBGPAL + ((c1 >> 2) & 3)];
|
pScn[4] = pBGPAL[(c1 >> 2) & 3];
|
||||||
lpScreen[pScn + 1] = MMU.BGPAL[pBGPAL + ((c2 >> 6))];
|
pScn[1] = pBGPAL[(c2 >> 6)];
|
||||||
lpScreen[pScn + 5] = MMU.BGPAL[pBGPAL + ((c2 >> 2) & 3)];
|
pScn[5] = pBGPAL[(c2 >> 2) & 3];
|
||||||
lpScreen[pScn + 2] = MMU.BGPAL[pBGPAL + ((c1 >> 4) & 3)];
|
pScn[2] = pBGPAL[(c1 >> 4) & 3];
|
||||||
lpScreen[pScn + 6] = MMU.BGPAL[pBGPAL + (c1 & 3)];
|
pScn[6] = pBGPAL[c1 & 3];
|
||||||
lpScreen[pScn + 3] = MMU.BGPAL[pBGPAL + ((c2 >> 4) & 3)];
|
pScn[3] = pBGPAL[(c2 >> 4) & 3];
|
||||||
lpScreen[pScn + 7] = MMU.BGPAL[pBGPAL + (c2 & 3)];
|
pScn[7] = pBGPAL[c2 & 3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lpScreen[pScn + 0] = lpScreen[pScn - 8];
|
*(uint*)(pScn + 0) = *(uint*)(pScn - 8);
|
||||||
lpScreen[pScn + 0 + 1] = lpScreen[pScn - 8 + 1];
|
*(uint*)(pScn + 4) = *(uint*)(pScn - 4);
|
||||||
lpScreen[pScn + 0 + 2] = lpScreen[pScn - 8 + 2];
|
*(pBGw + 0) = *(pBGw - 1);
|
||||||
lpScreen[pScn + 0 + 3] = lpScreen[pScn - 8 + 3];
|
|
||||||
|
|
||||||
lpScreen[pScn + 4] = lpScreen[pScn - 4];
|
|
||||||
lpScreen[pScn + 4 + 1] = lpScreen[pScn - 4 + 1];
|
|
||||||
lpScreen[pScn + 4 + 2] = lpScreen[pScn - 4 + 2];
|
|
||||||
lpScreen[pScn + 4 + 3] = lpScreen[pScn - 4 + 3];
|
|
||||||
|
|
||||||
BGwrite[pBGw + 0] = BGwrite[pBGw - 1];
|
|
||||||
}
|
}
|
||||||
pScn += 8;
|
pScn += 8;
|
||||||
pBGw++;
|
pBGw++;
|
||||||
@ -703,8 +699,8 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pScn = lpScanline + (8 - loopy_shift);
|
byte* pScn = lpScanline + (8 - loopy_shift);
|
||||||
pBGw = 0;
|
byte* pBGw = BGwrite;
|
||||||
|
|
||||||
int ntbladr;
|
int ntbladr;
|
||||||
int tileadr;
|
int tileadr;
|
||||||
@ -733,35 +729,27 @@
|
|||||||
|
|
||||||
chr_l = MMU.PPU_MEM_BANK[tileadr >> 10][tileadr & 0x03FF];
|
chr_l = MMU.PPU_MEM_BANK[tileadr >> 10][tileadr & 0x03FF];
|
||||||
chr_h = MMU.PPU_MEM_BANK[tileadr >> 10][(tileadr & 0x03FF) + 8];
|
chr_h = MMU.PPU_MEM_BANK[tileadr >> 10][(tileadr & 0x03FF) + 8];
|
||||||
BGwrite[pBGw] = (byte)(chr_l | chr_h);
|
*pBGw = (byte)(chr_l | chr_h);
|
||||||
|
|
||||||
int pBGPAL = attr;
|
fixed (byte* pBGPAL = &MMU.BGPAL[attr])
|
||||||
{
|
{
|
||||||
int c1 = ((chr_l >> 1) & 0x55) | (chr_h & 0xAA);
|
int c1 = ((chr_l >> 1) & 0x55) | (chr_h & 0xAA);
|
||||||
int c2 = (chr_l & 0x55) | ((chr_h << 1) & 0xAA);
|
int c2 = (chr_l & 0x55) | ((chr_h << 1) & 0xAA);
|
||||||
lpScreen[pScn + 0] = MMU.BGPAL[pBGPAL + (c1 >> 6)];
|
pScn[0] = pBGPAL[(c1 >> 6)];
|
||||||
lpScreen[pScn + 4] = MMU.BGPAL[pBGPAL + ((c1 >> 2) & 3)];
|
pScn[4] = pBGPAL[(c1 >> 2) & 3];
|
||||||
lpScreen[pScn + 1] = MMU.BGPAL[pBGPAL + (c2 >> 6)];
|
pScn[1] = pBGPAL[(c2 >> 6)];
|
||||||
lpScreen[pScn + 5] = MMU.BGPAL[pBGPAL + ((c2 >> 2) & 3)];
|
pScn[5] = pBGPAL[(c2 >> 2) & 3];
|
||||||
lpScreen[pScn + 2] = MMU.BGPAL[pBGPAL + ((c1 >> 4) & 3)];
|
pScn[2] = pBGPAL[(c1 >> 4) & 3];
|
||||||
lpScreen[pScn + 6] = MMU.BGPAL[pBGPAL + (c1 & 3)];
|
pScn[6] = pBGPAL[c1 & 3];
|
||||||
lpScreen[pScn + 3] = MMU.BGPAL[pBGPAL + ((c2 >> 4) & 3)];
|
pScn[3] = pBGPAL[(c2 >> 4) & 3];
|
||||||
lpScreen[pScn + 7] = MMU.BGPAL[pBGPAL + (c2 & 3)];
|
pScn[7] = pBGPAL[c2 & 3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lpScreen[pScn + 0] = lpScreen[pScn - 8];
|
*(uint*)(pScn + 0) = *(uint*)(pScn - 8);
|
||||||
lpScreen[pScn + 0 + 1] = lpScreen[pScn - 8 + 1];
|
*(uint*)(pScn + 4) = *(uint*)(pScn - 4);
|
||||||
lpScreen[pScn + 0 + 2] = lpScreen[pScn - 8 + 2];
|
*(pBGw + 0) = *(pBGw - 1);
|
||||||
lpScreen[pScn + 0 + 3] = lpScreen[pScn - 8 + 3];
|
|
||||||
|
|
||||||
lpScreen[pScn + 4] = lpScreen[pScn - 4];
|
|
||||||
lpScreen[pScn + 4 + 1] = lpScreen[pScn - 4 + 1];
|
|
||||||
lpScreen[pScn + 4 + 2] = lpScreen[pScn - 4 + 2];
|
|
||||||
lpScreen[pScn + 4 + 3] = lpScreen[pScn - 4 + 3];
|
|
||||||
|
|
||||||
BGwrite[pBGw + 0] = BGwrite[pBGw - 1];
|
|
||||||
}
|
}
|
||||||
pScn += 8;
|
pScn += 8;
|
||||||
pBGw++;
|
pBGw++;
|
||||||
@ -787,8 +775,8 @@
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// With Extension Latch(For MMC5)
|
// With Extension Latch(For MMC5)
|
||||||
pScn = lpScanline + (8 - loopy_shift);
|
byte* pScn = lpScanline + (8 - loopy_shift);
|
||||||
pBGw = 0;
|
byte* pBGw = BGwrite;
|
||||||
|
|
||||||
int ntbladr = 0x2000 + (MMU.loopy_v & 0x0FFF);
|
int ntbladr = 0x2000 + (MMU.loopy_v & 0x0FFF);
|
||||||
int ntbl_x = ntbladr & 0x1F;
|
int ntbl_x = ntbladr & 0x1F;
|
||||||
@ -813,35 +801,27 @@
|
|||||||
{
|
{
|
||||||
cache_tile = ((chr_h << 8) + chr_l);
|
cache_tile = ((chr_h << 8) + chr_l);
|
||||||
cache_attr = attr;
|
cache_attr = attr;
|
||||||
BGwrite[pBGw] = (byte)(chr_l | chr_h);
|
*pBGw = (byte)(chr_l | chr_h);
|
||||||
|
|
||||||
int pBGPAL = attr;
|
fixed (byte* pBGPAL = &MMU.BGPAL[attr])
|
||||||
{
|
{
|
||||||
int c1 = ((chr_l >> 1) & 0x55) | (chr_h & 0xAA);
|
int c1 = ((chr_l >> 1) & 0x55) | (chr_h & 0xAA);
|
||||||
int c2 = (chr_l & 0x55) | ((chr_h << 1) & 0xAA);
|
int c2 = (chr_l & 0x55) | ((chr_h << 1) & 0xAA);
|
||||||
lpScreen[pScn + 0] = MMU.BGPAL[pBGPAL + ((c1 >> 6))];
|
pScn[0] = pBGPAL[(c1 >> 6)];
|
||||||
lpScreen[pScn + 4] = MMU.BGPAL[pBGPAL + ((c1 >> 2) & 3)];
|
pScn[4] = pBGPAL[(c1 >> 2) & 3];
|
||||||
lpScreen[pScn + 1] = MMU.BGPAL[pBGPAL + ((c2 >> 6))];
|
pScn[1] = pBGPAL[(c2 >> 6)];
|
||||||
lpScreen[pScn + 5] = MMU.BGPAL[pBGPAL + ((c2 >> 2) & 3)];
|
pScn[5] = pBGPAL[(c2 >> 2) & 3];
|
||||||
lpScreen[pScn + 2] = MMU.BGPAL[pBGPAL + ((c1 >> 4) & 3)];
|
pScn[2] = pBGPAL[(c1 >> 4) & 3];
|
||||||
lpScreen[pScn + 6] = MMU.BGPAL[pBGPAL + (c1 & 3)];
|
pScn[6] = pBGPAL[c1 & 3];
|
||||||
lpScreen[pScn + 3] = MMU.BGPAL[pBGPAL + ((c2 >> 4) & 3)];
|
pScn[3] = pBGPAL[(c2 >> 4) & 3];
|
||||||
lpScreen[pScn + 7] = MMU.BGPAL[pBGPAL + (c2 & 3)];
|
pScn[7] = pBGPAL[c2 & 3];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lpScreen[pScn + 0] = lpScreen[pScn - 8];
|
*(uint*)(pScn + 0) = *(uint*)(pScn - 8);
|
||||||
lpScreen[pScn + 0 + 1] = lpScreen[pScn - 8 + 1];
|
*(uint*)(pScn + 4) = *(uint*)(pScn - 4);
|
||||||
lpScreen[pScn + 0 + 2] = lpScreen[pScn - 8 + 2];
|
*(pBGw + 0) = *(pBGw - 1);
|
||||||
lpScreen[pScn + 0 + 3] = lpScreen[pScn - 8 + 3];
|
|
||||||
|
|
||||||
lpScreen[pScn + 4] = lpScreen[pScn - 4];
|
|
||||||
lpScreen[pScn + 4 + 1] = lpScreen[pScn - 4 + 1];
|
|
||||||
lpScreen[pScn + 4 + 2] = lpScreen[pScn - 4 + 2];
|
|
||||||
lpScreen[pScn + 4 + 3] = lpScreen[pScn - 4 + 3];
|
|
||||||
|
|
||||||
BGwrite[pBGw + 0] = BGwrite[pBGw - 1];
|
|
||||||
}
|
}
|
||||||
pScn += 8;
|
pScn += 8;
|
||||||
pBGw++;
|
pBGw++;
|
||||||
@ -860,17 +840,17 @@
|
|||||||
}
|
}
|
||||||
if ((MMU.PPUREG[1] & PPU_BGCLIP_BIT) == 0 && bLeftClip)
|
if ((MMU.PPUREG[1] & PPU_BGCLIP_BIT) == 0 && bLeftClip)
|
||||||
{
|
{
|
||||||
pScn = lpScanline + 8;
|
byte* pScn = lpScanline + 8;
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
lpScreen[i] = MMU.BGPAL[0];
|
pScn[i] = MMU.BGPAL[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render sprites
|
// Render sprites
|
||||||
var temp = ~PPU_SPMAX_FLAG;
|
var temp = ~PPU_SPMAX_FLAG;
|
||||||
MMU.PPUREG[2] = (byte)(MMU.PPUREG[2] & temp);
|
MMU.PPUREG[2] &= (byte)(MMU.PPUREG[2] & temp);
|
||||||
|
|
||||||
// 昞帵婜娫奜偱偁傟偽僉儍儞僙儖
|
// 昞帵婜娫奜偱偁傟偽僉儍儞僙儖
|
||||||
if (scanline > 239)
|
if (scanline > 239)
|
||||||
@ -885,145 +865,144 @@
|
|||||||
int spraddr = 0, sp_y = 0, sp_h = 0;
|
int spraddr = 0, sp_y = 0, sp_h = 0;
|
||||||
chr_h = chr_l = 0;
|
chr_h = chr_l = 0;
|
||||||
|
|
||||||
|
fixed (byte* pBit2Rev = &Bit2Rev[0])
|
||||||
pBGw = 0;
|
|
||||||
int pSPw = 0;
|
|
||||||
int pBit2Rev = 0;
|
|
||||||
|
|
||||||
MemoryUtility.ZEROMEMORY(SPwrite, SPwrite.Length);
|
|
||||||
|
|
||||||
spmax = 0;
|
|
||||||
Sprite sp = new Sprite(MMU.SPRAM, 0);
|
|
||||||
sp_h = (MMU.PPUREG[0] & PPU_SP16_BIT) != 0 ? 15 : 7;
|
|
||||||
|
|
||||||
// Left clip
|
|
||||||
if (bLeftClip && ((MMU.PPUREG[1] & PPU_SPCLIP_BIT) == 0))
|
|
||||||
{
|
{
|
||||||
SPwrite[0] = 0xFF;
|
byte* pBGw = BGwrite;
|
||||||
}
|
byte* pSPw = SPwrite;
|
||||||
|
Unsafe.InitBlockUnaligned(pSPw, 0, 34);
|
||||||
|
|
||||||
for (int i = 0; i < 64; i++, sp.AddOffset(1))
|
spmax = 0;
|
||||||
{
|
Sprite sp = new Sprite(MMU.SPRAM, 0);
|
||||||
sp_y = scanline - (sp.y + 1);
|
sp_h = (MMU.PPUREG[0] & PPU_SP16_BIT) != 0 ? 15 : 7;
|
||||||
// 僗僉儍儞儔僀儞撪偵SPRITE偑懚嵼偡傞偐傪僠僃僢僋
|
|
||||||
if (sp_y != (sp_y & sp_h))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((MMU.PPUREG[0] & PPU_SP16_BIT) == 0)
|
// Left clip
|
||||||
|
if (bLeftClip && ((MMU.PPUREG[1] & PPU_SPCLIP_BIT) == 0))
|
||||||
{
|
{
|
||||||
// 8x8 Sprite
|
SPwrite[0] = 0xFF;
|
||||||
spraddr = ((MMU.PPUREG[0] & PPU_SPTBL_BIT) << 9) + (sp.tile << 4);
|
|
||||||
if ((sp.attr & SP_VMIRROR_BIT) == 0)
|
|
||||||
spraddr += sp_y;
|
|
||||||
else
|
|
||||||
spraddr += 7 - sp_y;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 8x16 Sprite
|
|
||||||
spraddr = ((sp.tile & 1) << 12) + ((sp.tile & 0xFE) << 4);
|
|
||||||
if ((sp.attr & SP_VMIRROR_BIT) == 0)
|
|
||||||
spraddr += ((sp_y & 8) << 1) + (sp_y & 7);
|
|
||||||
else
|
|
||||||
spraddr += ((~sp_y & 8) << 1) + (7 - (sp_y & 7));
|
|
||||||
}
|
|
||||||
// Character pattern
|
|
||||||
chr_l = MMU.PPU_MEM_BANK[spraddr >> 10][spraddr & 0x3FF];
|
|
||||||
chr_h = MMU.PPU_MEM_BANK[spraddr >> 10][(spraddr & 0x3FF) + 8];
|
|
||||||
|
|
||||||
// Character latch(For MMC2/MMC4)
|
|
||||||
if (bChrLatch)
|
|
||||||
{
|
|
||||||
nes.mapper.PPU_ChrLatch((ushort)spraddr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// pattern mask
|
for (int i = 0; i < 64; i++, sp.AddOffset(1))
|
||||||
if ((sp.attr & SP_HMIRROR_BIT) != 0)
|
|
||||||
{
|
{
|
||||||
chr_l = Bit2Rev[pBit2Rev + chr_l];
|
sp_y = scanline - (sp.y + 1);
|
||||||
chr_h = Bit2Rev[pBit2Rev + chr_h];
|
// 僗僉儍儞儔僀儞撪偵SPRITE偑懚嵼偡傞偐傪僠僃僢僋
|
||||||
}
|
if (sp_y != (sp_y & sp_h))
|
||||||
byte SPpat = (byte)(chr_l | chr_h);
|
continue;
|
||||||
|
|
||||||
// Sprite hitcheck
|
if ((MMU.PPUREG[0] & PPU_SP16_BIT) == 0)
|
||||||
if (i == 0 && (MMU.PPUREG[2] & PPU_SPHIT_FLAG) == 0)
|
|
||||||
{
|
|
||||||
int BGpos = ((sp.x & 0xF8) + ((loopy_shift + (sp.x & 7)) & 8)) >> 3;
|
|
||||||
int BGsft = 8 - ((loopy_shift + sp.x) & 7);
|
|
||||||
|
|
||||||
var temp1 = BGwrite[pBGw + BGpos + 0] << 8;
|
|
||||||
var temp2 = BGwrite[pBGw + BGpos + 1];
|
|
||||||
byte BGmsk = (byte)((temp1 | temp2) >> BGsft);
|
|
||||||
|
|
||||||
if ((SPpat & BGmsk) != 0)
|
|
||||||
{
|
{
|
||||||
MMU.PPUREG[2] |= PPU_SPHIT_FLAG;
|
// 8x8 Sprite
|
||||||
|
spraddr = ((MMU.PPUREG[0] & PPU_SPTBL_BIT) << 9) + (sp.tile << 4);
|
||||||
|
if ((sp.attr & SP_VMIRROR_BIT) == 0)
|
||||||
|
spraddr += sp_y;
|
||||||
|
else
|
||||||
|
spraddr += 7 - sp_y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 8x16 Sprite
|
||||||
|
spraddr = ((sp.tile & 1) << 12) + ((sp.tile & 0xFE) << 4);
|
||||||
|
if ((sp.attr & SP_VMIRROR_BIT) == 0)
|
||||||
|
spraddr += ((sp_y & 8) << 1) + (sp_y & 7);
|
||||||
|
else
|
||||||
|
spraddr += ((~sp_y & 8) << 1) + (7 - (sp_y & 7));
|
||||||
|
}
|
||||||
|
// Character pattern
|
||||||
|
chr_l = MMU.PPU_MEM_BANK[spraddr >> 10][spraddr & 0x3FF];
|
||||||
|
chr_h = MMU.PPU_MEM_BANK[spraddr >> 10][(spraddr & 0x3FF) + 8];
|
||||||
|
|
||||||
|
// Character latch(For MMC2/MMC4)
|
||||||
|
if (bChrLatch)
|
||||||
|
{
|
||||||
|
nes.mapper.PPU_ChrLatch((ushort)spraddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// pattern mask
|
||||||
|
if ((sp.attr & SP_HMIRROR_BIT) != 0)
|
||||||
|
{
|
||||||
|
chr_l = pBit2Rev[chr_l];
|
||||||
|
chr_h = pBit2Rev[chr_h];
|
||||||
|
}
|
||||||
|
byte SPpat = (byte)(chr_l | chr_h);
|
||||||
|
|
||||||
|
// Sprite hitcheck
|
||||||
|
if (i == 0 && (MMU.PPUREG[2] & PPU_SPHIT_FLAG) == 0)
|
||||||
|
{
|
||||||
|
int BGpos = ((sp.x & 0xF8) + ((loopy_shift + (sp.x & 7)) & 8)) >> 3;
|
||||||
|
int BGsft = 8 - ((loopy_shift + sp.x) & 7);
|
||||||
|
byte BGmsk = (byte)(((pBGw[BGpos + 0] << 8) | pBGw[BGpos + 1]) >> BGsft);
|
||||||
|
|
||||||
|
if ((SPpat & BGmsk) != 0)
|
||||||
|
{
|
||||||
|
MMU.PPUREG[2] |= PPU_SPHIT_FLAG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sprite mask
|
||||||
|
int SPpos = sp.x / 8;
|
||||||
|
int SPsft = 8 - (sp.x & 7);
|
||||||
|
byte SPmsk = (byte)(((pSPw[SPpos + 0] << 8) | pSPw[SPpos + 1]) >> SPsft);
|
||||||
|
ushort SPwrt = (ushort)(SPpat << SPsft);
|
||||||
|
pSPw[SPpos + 0] = (byte)((pSPw[SPpos + 0]) | (SPwrt >> 8));
|
||||||
|
pSPw[SPpos + 1] = (byte)((pSPw[SPpos + 1]) | (SPwrt & 0xFF));
|
||||||
|
SPpat = (byte)(SPpat & ~SPmsk);
|
||||||
|
|
||||||
|
if ((sp.attr & SP_PRIORITY_BIT) != 0)
|
||||||
|
{
|
||||||
|
// BG > SP priority
|
||||||
|
int BGpos = ((sp.x & 0xF8) + ((loopy_shift + (sp.x & 7)) & 8)) >> 3;
|
||||||
|
int BGsft = 8 - ((loopy_shift + sp.x) & 7);
|
||||||
|
byte BGmsk = (byte)(((pBGw[BGpos + 0] << 8) | pBGw[BGpos + 1]) >> BGsft);
|
||||||
|
|
||||||
|
SPpat = (byte)(SPpat & ~BGmsk);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attribute
|
||||||
|
fixed (byte* pSPPAL = &MMU.SPPAL[(sp.attr & SP_COLOR_BIT) << 2])
|
||||||
|
{
|
||||||
|
// Ptr
|
||||||
|
byte* pScn = lpScanline + sp.x + 8;
|
||||||
|
|
||||||
|
if (!bExtMono)
|
||||||
|
{
|
||||||
|
int c1 = ((chr_l >> 1) & 0x55) | (chr_h & 0xAA);
|
||||||
|
int c2 = (chr_l & 0x55) | ((chr_h << 1) & 0xAA);
|
||||||
|
if ((SPpat & 0x80) != 0) pScn[0] = pSPPAL[(c1 >> 6)];
|
||||||
|
if ((SPpat & 0x08) != 0) pScn[4] = pSPPAL[(c1 >> 2) & 3];
|
||||||
|
if ((SPpat & 0x40) != 0) pScn[1] = pSPPAL[(c2 >> 6)];
|
||||||
|
if ((SPpat & 0x04) != 0) pScn[5] = pSPPAL[(c2 >> 2) & 3];
|
||||||
|
if ((SPpat & 0x20) != 0) pScn[2] = pSPPAL[(c1 >> 4) & 3];
|
||||||
|
if ((SPpat & 0x02) != 0) pScn[6] = pSPPAL[c1 & 3];
|
||||||
|
if ((SPpat & 0x10) != 0) pScn[3] = pSPPAL[(c2 >> 4) & 3];
|
||||||
|
if ((SPpat & 0x01) != 0) pScn[7] = pSPPAL[c2 & 3];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Monocrome effect (for Final Fantasy)
|
||||||
|
byte mono = BGmono[((sp.x & 0xF8) + ((loopy_shift + (sp.x & 7)) & 8)) >> 3];
|
||||||
|
|
||||||
|
int c1 = ((chr_l >> 1) & 0x55) | (chr_h & 0xAA);
|
||||||
|
int c2 = (chr_l & 0x55) | ((chr_h << 1) & 0xAA);
|
||||||
|
if ((SPpat & 0x80) != 0) pScn[0] = (byte)(pSPPAL[c1>>6] |mono);
|
||||||
|
if ((SPpat & 0x08) != 0) pScn[4] = (byte)(pSPPAL[(c1>>2)&3] |mono);
|
||||||
|
if ((SPpat & 0x40) != 0) pScn[1] = (byte)(pSPPAL[c2>>6] |mono);
|
||||||
|
if ((SPpat & 0x04) != 0) pScn[5] = (byte)(pSPPAL[(c2>>2)&3] |mono);
|
||||||
|
if ((SPpat & 0x20) != 0) pScn[2] = (byte)(pSPPAL[(c1>>4)&3] |mono);
|
||||||
|
if ((SPpat & 0x02) != 0) pScn[6] = (byte)(pSPPAL[c1&3] |mono);
|
||||||
|
if ((SPpat & 0x10) != 0) pScn[3] = (byte)(pSPPAL[(c2>>4)&3] |mono);
|
||||||
|
if ((SPpat & 0x01) != 0) pScn[7] = (byte)(pSPPAL[c2 & 3] | mono);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++spmax > 8 - 1)
|
||||||
|
{
|
||||||
|
if (!bMax)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (spmax > 8 - 1)
|
||||||
// Sprite mask
|
|
||||||
int SPpos = sp.x / 8;
|
|
||||||
int SPsft = 8 - (sp.x & 7);
|
|
||||||
byte SPmsk = (byte)((SPwrite[pSPw + SPpos + 0] << 8 | SPwrite[pSPw + SPpos + 1]) >> SPsft);
|
|
||||||
ushort SPwrt = (ushort)(SPpat << SPsft);
|
|
||||||
SPwrite[pSPw + SPpos + 0] = (byte)(SPwrite[pSPw + SPpos + 0] | SPwrt >> 8);
|
|
||||||
SPwrite[pSPw + SPpos + 1] = (byte)(SPwrite[pSPw + SPpos + 1] | SPwrt & 0xFF);
|
|
||||||
SPpat = (byte)(SPpat & ~SPmsk);
|
|
||||||
|
|
||||||
if ((sp.attr & SP_PRIORITY_BIT) != 0)
|
|
||||||
{
|
{
|
||||||
// BG > SP priority
|
MMU.PPUREG[2] |= PPU_SPMAX_FLAG;
|
||||||
int BGpos = ((sp.x & 0xF8) + ((loopy_shift + (sp.x & 7)) & 8)) >> 3;
|
|
||||||
int BGsft = 8 - ((loopy_shift + sp.x) & 7);
|
|
||||||
byte BGmsk = (byte)(((BGwrite[pBGw + BGpos + 0] << 8) | BGwrite[pBGw + BGpos + 1]) >> BGsft);
|
|
||||||
|
|
||||||
SPpat = (byte)(SPpat & ~BGmsk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attribute
|
|
||||||
int pSPPAL = (sp.attr & SP_COLOR_BIT) << 2;
|
|
||||||
// Ptr
|
|
||||||
pScn = lpScanline + sp.x + 8;
|
|
||||||
|
|
||||||
if (!bExtMono)
|
|
||||||
{
|
|
||||||
int c1 = ((chr_l >> 1) & 0x55) | (chr_h & 0xAA);
|
|
||||||
int c2 = (chr_l & 0x55) | ((chr_h << 1) & 0xAA);
|
|
||||||
if ((SPpat & 0x80) != 0) lpScreen[pScn + 0] = MMU.SPPAL[pSPPAL + (c1 >> 6)];
|
|
||||||
if ((SPpat & 0x08) != 0) lpScreen[pScn + 4] = MMU.SPPAL[pSPPAL + ((c1 >> 2) & 3)];
|
|
||||||
if ((SPpat & 0x40) != 0) lpScreen[pScn + 1] = MMU.SPPAL[pSPPAL + ((c2 >> 6))];
|
|
||||||
if ((SPpat & 0x04) != 0) lpScreen[pScn + 5] = MMU.SPPAL[pSPPAL + ((c2 >> 2) & 3)];
|
|
||||||
if ((SPpat & 0x20) != 0) lpScreen[pScn + 2] = MMU.SPPAL[pSPPAL + ((c1 >> 4) & 3)];
|
|
||||||
if ((SPpat & 0x02) != 0) lpScreen[pScn + 6] = MMU.SPPAL[pSPPAL + (c1 & 3)];
|
|
||||||
if ((SPpat & 0x10) != 0) lpScreen[pScn + 3] = MMU.SPPAL[pSPPAL + ((c2 >> 4) & 3)];
|
|
||||||
if ((SPpat & 0x01) != 0) lpScreen[pScn + 7] = MMU.SPPAL[pSPPAL + (c2 & 3)];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Monocrome effect (for Final Fantasy)
|
|
||||||
byte mono = BGmono[((sp.x & 0xF8) + ((loopy_shift + (sp.x & 7)) & 8)) >> 3];
|
|
||||||
|
|
||||||
int c1 = ((chr_l >> 1) & 0x55) | (chr_h & 0xAA);
|
|
||||||
int c2 = (chr_l & 0x55) | ((chr_h << 1) & 0xAA);
|
|
||||||
if ((SPpat & 0x80) != 0) lpScreen[pScn + 0] = (byte)(MMU.SPPAL[pSPPAL + (c1 >> 6)] | mono);
|
|
||||||
if ((SPpat & 0x08) != 0) lpScreen[pScn + 4] = (byte)(MMU.SPPAL[pSPPAL + ((c1 >> 2) & 3)] | mono);
|
|
||||||
if ((SPpat & 0x40) != 0) lpScreen[pScn + 1] = (byte)(MMU.SPPAL[pSPPAL + (c2 >> 6)] | mono);
|
|
||||||
if ((SPpat & 0x04) != 0) lpScreen[pScn + 5] = (byte)(MMU.SPPAL[pSPPAL + ((c2 >> 2) & 3)] | mono);
|
|
||||||
if ((SPpat & 0x20) != 0) lpScreen[pScn + 2] = (byte)(MMU.SPPAL[pSPPAL + ((c1 >> 4) & 3)] | mono);
|
|
||||||
if ((SPpat & 0x02) != 0) lpScreen[pScn + 6] = (byte)(MMU.SPPAL[pSPPAL + (c1 & 3)] | mono);
|
|
||||||
if ((SPpat & 0x10) != 0) lpScreen[pScn + 3] = (byte)(MMU.SPPAL[pSPPAL + ((c2 >> 4) & 3)] | mono);
|
|
||||||
if ((SPpat & 0x01) != 0) lpScreen[pScn + 7] = (byte)(MMU.SPPAL[pSPPAL + (c2 & 3)] | mono);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (++spmax > 8 - 1)
|
|
||||||
{
|
|
||||||
if (!bMax)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (spmax > 8 - 1)
|
|
||||||
{
|
|
||||||
MMU.PPUREG[2] |= PPU_SPMAX_FLAG;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1103,7 +1082,7 @@
|
|||||||
MMU.PPUREG[2] |= PPU_VBLANK_FLAG;
|
MMU.PPUREG[2] |= PPU_VBLANK_FLAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint[] GetScreenPtr()
|
public byte* GetScreenPtr()
|
||||||
{
|
{
|
||||||
return lpScreen;
|
return lpScreen;
|
||||||
}
|
}
|
||||||
@ -1113,9 +1092,10 @@
|
|||||||
return lpColormode;
|
return lpColormode;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void SetScreenPtr(uint[] screenBuffer, byte[] colormode)
|
internal void SetScreenPtr(byte[] screenBuffer, byte[] colormode)
|
||||||
{
|
{
|
||||||
lpScreen = screenBuffer;
|
lpScreenGCH = GCHandle.Alloc(screenBuffer, GCHandleType.Pinned);
|
||||||
|
lpScreen = (byte*)lpScreenGCH.AddrOfPinnedObject();
|
||||||
lpColormode = colormode;
|
lpColormode = colormode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user