完善
This commit is contained in:
parent
8d0487be8b
commit
68d8c7d3b2
@ -182,11 +182,11 @@ MonoBehaviour:
|
|||||||
m_Calls: []
|
m_Calls: []
|
||||||
m_FontData:
|
m_FontData:
|
||||||
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
|
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
|
||||||
m_FontSize: 14
|
m_FontSize: 53
|
||||||
m_FontStyle: 0
|
m_FontStyle: 0
|
||||||
m_BestFit: 0
|
m_BestFit: 0
|
||||||
m_MinSize: 10
|
m_MinSize: 10
|
||||||
m_MaxSize: 40
|
m_MaxSize: 53
|
||||||
m_Alignment: 4
|
m_Alignment: 4
|
||||||
m_AlignByGeometry: 0
|
m_AlignByGeometry: 0
|
||||||
m_RichText: 1
|
m_RichText: 1
|
||||||
@ -907,8 +907,8 @@ RectTransform:
|
|||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||||
m_AnchoredPosition: {x: -471, y: -281}
|
m_AnchoredPosition: {x: -560.94934, y: -316.46082}
|
||||||
m_SizeDelta: {x: 160, y: 30}
|
m_SizeDelta: {x: 339.8987, y: 100.9216}
|
||||||
m_Pivot: {x: 0.5, y: 0.5}
|
m_Pivot: {x: 0.5, y: 0.5}
|
||||||
--- !u!114 &1712987039
|
--- !u!114 &1712987039
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
|
@ -14,9 +14,9 @@ public class AudioProvider : MonoBehaviour
|
|||||||
|
|
||||||
public void Awake()
|
public void Awake()
|
||||||
{
|
{
|
||||||
//var dummy = AudioClip.Create("dummy", 1,2, AudioSettings.outputSampleRate, false);
|
AudioClip clip = AudioClip.Create("dummy", GbaAudio.SampleRate * 2, 2, GbaAudio.SampleRate, true);
|
||||||
AudioClip clip = AudioClip.Create("blank", GbaAudio.SampleRate * 2, 2, GbaAudio.SampleRate, true);
|
AudioSettings.GetDSPBufferSize(out int bufferLength, out _);
|
||||||
_buffer = new RingBuffer<float>(GbaAudio.SampleRate * 2);
|
_buffer = new RingBuffer<float>(bufferLength * 2 * 2);
|
||||||
m_as.clip = clip;
|
m_as.clip = clip;
|
||||||
m_as.playOnAwake = true;
|
m_as.playOnAwake = true;
|
||||||
//m_as.loop = true;
|
//m_as.loop = true;
|
||||||
@ -36,13 +36,9 @@ public class AudioProvider : MonoBehaviour
|
|||||||
for (int i = 0; i < data.Length; i += step)
|
for (int i = 0; i < data.Length; i += step)
|
||||||
{
|
{
|
||||||
if (_buffer.TryRead(out float rawData))
|
if (_buffer.TryRead(out float rawData))
|
||||||
{
|
|
||||||
data[i] = rawData;
|
data[i] = rawData;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//int step = channels;
|
//int step = channels;
|
||||||
|
@ -28,9 +28,9 @@ public class Emulator : MonoBehaviour
|
|||||||
Thread EmulationThread;
|
Thread EmulationThread;
|
||||||
AutoResetEvent ThreadSync = new AutoResetEvent(false);
|
AutoResetEvent ThreadSync = new AutoResetEvent(false);
|
||||||
|
|
||||||
private int _samplesAvailable;
|
//private int _samplesAvailable;
|
||||||
//private PipeStream _pipeStream;
|
//private PipeStream _pipeStream;
|
||||||
private byte[] _buffer;
|
//private byte[] _buffer;
|
||||||
public float audioGain = 1.0f;
|
public float audioGain = 1.0f;
|
||||||
|
|
||||||
// key delegate
|
// key delegate
|
||||||
@ -42,19 +42,11 @@ public class Emulator : MonoBehaviour
|
|||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
instance = this;
|
instance = this;
|
||||||
//BetterStreamingAssets.Initialize();
|
|
||||||
// must set it to 60 or it won't sync with audio or run too fast.
|
// must set it to 60 or it won't sync with audio or run too fast.
|
||||||
Application.targetFrameRate = (int)FrameRate;
|
Application.targetFrameRate = (int)FrameRate;
|
||||||
//audioSource = GetComponent<AudioSource>();
|
|
||||||
//AudioClip clip = AudioClip.Create("blank", GbaAudio.SampleRate * 2, 2, GbaAudio.SampleRate, true);
|
|
||||||
//audioSource.clip = clip;
|
|
||||||
//audioSource.playOnAwake = true;
|
|
||||||
//audioSource.enabled = false;
|
|
||||||
//screenRenderer.material.mainTexture = new Texture2D(240, 160, TextureFormat.RGBA32, false, false);
|
|
||||||
|
|
||||||
// Get Unity Buffer size
|
// Get Unity Buffer size
|
||||||
AudioSettings.GetDSPBufferSize(out int bufferLength, out _);
|
//AudioSettings.GetDSPBufferSize(out int bufferLength, out _);
|
||||||
_samplesAvailable = bufferLength;
|
//_samplesAvailable = bufferLength;
|
||||||
// Must be set to 32768
|
// Must be set to 32768
|
||||||
var audioConfig = AudioSettings.GetConfiguration();
|
var audioConfig = AudioSettings.GetConfiguration();
|
||||||
audioConfig.sampleRate = GbaAudio.SampleRate;
|
audioConfig.sampleRate = GbaAudio.SampleRate;
|
||||||
@ -62,7 +54,7 @@ public class Emulator : MonoBehaviour
|
|||||||
// Prepare our buffer
|
// Prepare our buffer
|
||||||
//_pipeStream = new PipeStream();
|
//_pipeStream = new PipeStream();
|
||||||
//_pipeStream.MaxBufferLength = _samplesAvailable * 2 * sizeof(float);
|
//_pipeStream.MaxBufferLength = _samplesAvailable * 2 * sizeof(float);
|
||||||
_buffer = new byte[_samplesAvailable * 2 * sizeof(float)];
|
//_buffer = new byte[_samplesAvailable * 2 * sizeof(float)];
|
||||||
}
|
}
|
||||||
void Start()
|
void Start()
|
||||||
{
|
{
|
||||||
@ -155,15 +147,15 @@ public class Emulator : MonoBehaviour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetOutputSampleRate()
|
//public int GetOutputSampleRate()
|
||||||
{
|
//{
|
||||||
return AudioSettings.outputSampleRate;
|
// return AudioSettings.outputSampleRate;
|
||||||
}
|
//}
|
||||||
|
|
||||||
public int GetSamplesAvailable()
|
//public int GetSamplesAvailable()
|
||||||
{
|
//{
|
||||||
return _samplesAvailable;
|
// return _samplesAvailable;
|
||||||
}
|
//}
|
||||||
|
|
||||||
//private void OnAudioFilterRead(float[] data, int channels)
|
//private void OnAudioFilterRead(float[] data, int channels)
|
||||||
//{
|
//{
|
||||||
|
@ -33,6 +33,8 @@ public class EmulatorGUI : MonoBehaviour
|
|||||||
#if UNITY_EDITOR || UNITY_STANDALONE
|
#if UNITY_EDITOR || UNITY_STANDALONE
|
||||||
bool input = Input.GetKey( keyboardKeyCodeMap[keyCode]);
|
bool input = Input.GetKey( keyboardKeyCodeMap[keyCode]);
|
||||||
if(input) return true;else return false;
|
if(input) return true;else return false;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,10 @@ using static OptimeGBA.MemoryUtil;
|
|||||||
using Unity.Burst.Intrinsics;
|
using Unity.Burst.Intrinsics;
|
||||||
using static Unity.Burst.Intrinsics.X86;
|
using static Unity.Burst.Intrinsics.X86;
|
||||||
|
|
||||||
|
#if UNITY_STANDALONE_WIN || UNITY_EDITOR
|
||||||
|
#else
|
||||||
|
|
||||||
|
#endif
|
||||||
namespace OptimeGBA
|
namespace OptimeGBA
|
||||||
{
|
{
|
||||||
public sealed unsafe class PpuRenderer
|
public sealed unsafe class PpuRenderer
|
||||||
@ -39,7 +43,7 @@ namespace OptimeGBA
|
|||||||
WinMasks = MemoryUtil.AllocateUnmanagedArray(Width + 16);
|
WinMasks = MemoryUtil.AllocateUnmanagedArray(Width + 16);
|
||||||
BgLo = MemoryUtil.AllocateUnmanagedArray32(width + 16);
|
BgLo = MemoryUtil.AllocateUnmanagedArray32(width + 16);
|
||||||
BgHi = MemoryUtil.AllocateUnmanagedArray32(width + 16);
|
BgHi = MemoryUtil.AllocateUnmanagedArray32(width + 16);
|
||||||
#else
|
#else
|
||||||
ScreenFront = new ushort[ScreenBufferSize];
|
ScreenFront = new ushort[ScreenBufferSize];
|
||||||
ScreenBack = new ushort[ScreenBufferSize];
|
ScreenBack = new ushort[ScreenBufferSize];
|
||||||
|
|
||||||
@ -613,86 +617,91 @@ namespace OptimeGBA
|
|||||||
v256 indicesVec;
|
v256 indicesVec;
|
||||||
uint paletteRow = 0;
|
uint paletteRow = 0;
|
||||||
|
|
||||||
if (bg.Use8BitColor)
|
//mm256_cvtepu8_epi32 用于将无符号的8位整数(uint8)转换成32位整数(int32)
|
||||||
{
|
|
||||||
clearMaskVec = new v256(0xFFU);
|
|
||||||
|
|
||||||
uint vramTileAddr = charBase + tileNumber * 64 + effectiveIntraTileY * 8;
|
//{
|
||||||
ulong data = GetUlong(vram, vramTileAddr);
|
// if (bg.Use8BitColor)
|
||||||
|
// {
|
||||||
|
// clearMaskVec = new v256(0xFFU);
|
||||||
|
|
||||||
if (data != 0)
|
// uint vramTileAddr = charBase + tileNumber * 64 + effectiveIntraTileY * 8;
|
||||||
{
|
// ulong data = GetUlong(vram, vramTileAddr);
|
||||||
indicesVec = Avx2.mm256_cvtepu8_epi32(new v128(data));
|
|
||||||
if (xFlip)
|
|
||||||
{
|
|
||||||
// First, reverse within 128-bit lanes
|
|
||||||
indicesVec = Avx2.mm256_shuffle_epi32(indicesVec, 0b00_01_10_11);
|
|
||||||
// Then, swap upper and lower halves
|
|
||||||
indicesVec = Avx2.mm256_permute2x128_si256(indicesVec, indicesVec, 1);
|
|
||||||
}
|
|
||||||
indicesVec = Avx2.mm256_and_si256(indicesVec, clearMaskVec);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pixelX += 8;
|
|
||||||
lineIndex += 8;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
clearMaskVec = new v256(0xFU);
|
|
||||||
|
|
||||||
paletteRow = (mapEntry >> 12) & 0xF;
|
// if (data != 0)
|
||||||
uint vramTileAddr = charBase + tileNumber * 32 + effectiveIntraTileY * 4;
|
// {
|
||||||
|
// indicesVec = Avx2.mm256_cvtepu8_epi32(new v128(data));
|
||||||
|
// if (xFlip)
|
||||||
|
// {
|
||||||
|
// // First, reverse within 128-bit lanes
|
||||||
|
// indicesVec = Avx2.mm256_shuffle_epi32(indicesVec, 0b00_01_10_11);
|
||||||
|
// // Then, swap upper and lower halves
|
||||||
|
// indicesVec = Avx2.mm256_permute2x128_si256(indicesVec, indicesVec, 1);
|
||||||
|
// }
|
||||||
|
// indicesVec = Avx2.mm256_and_si256(indicesVec, clearMaskVec);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// pixelX += 8;
|
||||||
|
// lineIndex += 8;
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// clearMaskVec = new v256(0xFU);
|
||||||
|
|
||||||
uint data = GetUint(vram, vramTileAddr);
|
// paletteRow = (mapEntry >> 12) & 0xF;
|
||||||
|
// uint vramTileAddr = charBase + tileNumber * 32 + effectiveIntraTileY * 4;
|
||||||
|
|
||||||
if (data != 0)
|
// uint data = GetUint(vram, vramTileAddr);
|
||||||
{
|
|
||||||
v256 shifts;
|
|
||||||
if (xFlip)
|
|
||||||
{
|
|
||||||
shifts = new v256(28U, 24U, 20U, 16U, 12U, 8U, 4U, 0U);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
shifts = new v256(0U, 4U, 8U, 12U, 16U, 20U, 24U, 28U);
|
|
||||||
}
|
|
||||||
indicesVec = new v256(data);
|
|
||||||
indicesVec = Avx2.mm256_srlv_epi32(indicesVec, shifts);
|
|
||||||
indicesVec = Avx2.mm256_and_si256(indicesVec, clearMaskVec);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pixelX += 8;
|
|
||||||
lineIndex += 8;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
v256 color = Avx2.mm256_i32gather_epi32((int*)((ushort*)palettes + paletteRow * 16), indicesVec, sizeof(ushort));
|
// if (data != 0)
|
||||||
color = Avx2.mm256_and_si256(color, new v256(0xFFFF));
|
// {
|
||||||
// Weave metadata (priority, ID) into color data
|
// v256 shifts;
|
||||||
color = Avx2.mm256_or_si256(color, Avx2.mm256_slli_epi32(metaVec, 16));
|
// if (xFlip)
|
||||||
|
// {
|
||||||
|
// shifts = new v256(28U, 24U, 20U, 16U, 12U, 8U, 4U, 0U);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// shifts = new v256(0U, 4U, 8U, 12U, 16U, 20U, 24U, 28U);
|
||||||
|
// }
|
||||||
|
// indicesVec = new v256(data);
|
||||||
|
// indicesVec = Avx2.mm256_srlv_epi32(indicesVec, shifts);
|
||||||
|
// indicesVec = Avx2.mm256_and_si256(indicesVec, clearMaskVec);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// pixelX += 8;
|
||||||
|
// lineIndex += 8;
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
ulong addr = GetUlong(winMasks, lineIndex);
|
// v256 color = Avx2.mm256_i32gather_epi32((int*)((ushort*)palettes + paletteRow * 16), indicesVec, sizeof(ushort));
|
||||||
v256 winMask = Avx2.mm256_cvtepi8_epi32(new v128(addr));
|
// color = Avx2.mm256_and_si256(color, new v256(0xFFFF));
|
||||||
winMask = Avx2.mm256_and_si256(winMask, metaVec);
|
// // Weave metadata (priority, ID) into color data
|
||||||
winMask = Avx2.mm256_cmpeq_epi32(winMask, new v256((byte)0));
|
// color = Avx2.mm256_or_si256(color, Avx2.mm256_slli_epi32(metaVec, 16));
|
||||||
// Get important color bits
|
|
||||||
v256 clear = Avx2.mm256_and_si256(indicesVec, clearMaskVec);
|
// ulong addr = GetUlong(winMasks, lineIndex);
|
||||||
// Are those bits clear?
|
// v256 winMask = Avx2.mm256_cvtepi8_epi32(new v128(addr));
|
||||||
clear = Avx2.mm256_cmpeq_epi32(clear, new v256(0));
|
// winMask = Avx2.mm256_and_si256(winMask, metaVec);
|
||||||
// Merge with window mask
|
// winMask = Avx2.mm256_cmpeq_epi32(winMask, new v256((byte)0));
|
||||||
winMask = Avx2.mm256_or_si256(winMask, clear);
|
// // Get important color bits
|
||||||
winMask = Avx2.mm256_xor_si256(winMask, new v256(int.MinValue));
|
// v256 clear = Avx2.mm256_and_si256(indicesVec, clearMaskVec);
|
||||||
|
// // Are those bits clear?
|
||||||
|
// clear = Avx2.mm256_cmpeq_epi32(clear, new v256(0));
|
||||||
|
// // Merge with window mask
|
||||||
|
// winMask = Avx2.mm256_or_si256(winMask, clear);
|
||||||
|
// winMask = Avx2.mm256_xor_si256(winMask, new v256(int.MinValue));
|
||||||
|
|
||||||
|
// // Push back covered pixels from hi to lo
|
||||||
|
// // This render the front image
|
||||||
|
// Avx2.mm256_maskstore_epi32((void*)(lo + lineIndex), winMask, Avx2.mm256_stream_load_si256((void*)(hi + lineIndex)));
|
||||||
|
// // This render the background, has some bugs
|
||||||
|
// Avx2.mm256_maskstore_epi32((void*)(hi + lineIndex), winMask, color);
|
||||||
|
//}
|
||||||
|
|
||||||
// Push back covered pixels from hi to lo
|
|
||||||
// This render the front image
|
|
||||||
Avx2.mm256_maskstore_epi32((void*)(lo + lineIndex), winMask, Avx2.mm256_stream_load_si256((void*)(hi + lineIndex)));
|
|
||||||
// This render the background, has some bugs
|
|
||||||
Avx2.mm256_maskstore_epi32((void*)(hi + lineIndex), winMask, color);
|
|
||||||
|
|
||||||
pixelX += 8;
|
pixelX += 8;
|
||||||
lineIndex += 8;
|
lineIndex += 8;
|
||||||
|
@ -13,12 +13,10 @@ public class VideoProvider : MonoBehaviour
|
|||||||
private Texture2D wrapTex;
|
private Texture2D wrapTex;
|
||||||
private int TexBufferSize;
|
private int TexBufferSize;
|
||||||
|
|
||||||
|
|
||||||
uint[] wrapTexBuffer = new uint[240 * 160];
|
uint[] wrapTexBuffer = new uint[240 * 160];
|
||||||
Color32[] DisplayColorBuffer = new Color32[240 * 160];
|
//Color32[] DisplayColorBuffer = new Color32[240 * 160];
|
||||||
|
|
||||||
|
private void Awake()
|
||||||
public void OnRenderFrame()
|
|
||||||
{
|
{
|
||||||
if (wrapTex == null)
|
if (wrapTex == null)
|
||||||
{
|
{
|
||||||
@ -39,10 +37,9 @@ public class VideoProvider : MonoBehaviour
|
|||||||
m_drawCanvasrect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, targetWidth);
|
m_drawCanvasrect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, targetWidth);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawDisplay();
|
|
||||||
}
|
}
|
||||||
public void DrawDisplay()
|
|
||||||
|
public void OnRenderFrame()
|
||||||
{
|
{
|
||||||
var buf = Emulator.instance.ShowBackBuf ? Emulator.instance.gba.Ppu.Renderer.ScreenBack : Emulator.instance.gba.Ppu.Renderer.ScreenFront;
|
var buf = Emulator.instance.ShowBackBuf ? Emulator.instance.gba.Ppu.Renderer.ScreenBack : Emulator.instance.gba.Ppu.Renderer.ScreenFront;
|
||||||
unsafe
|
unsafe
|
||||||
@ -50,41 +47,16 @@ public class VideoProvider : MonoBehaviour
|
|||||||
for (uint i = 0; i < 240 * 160; i++)
|
for (uint i = 0; i < 240 * 160; i++)
|
||||||
{
|
{
|
||||||
wrapTexBuffer[i] = PpuRenderer.ColorLutCorrected[buf[i] & 0x7FFF];
|
wrapTexBuffer[i] = PpuRenderer.ColorLutCorrected[buf[i] & 0x7FFF];
|
||||||
fixed (uint* p = &wrapTexBuffer[i])
|
//fixed (uint* p = &wrapTexBuffer[i])
|
||||||
{
|
//{
|
||||||
byte* bp = (byte*)p;
|
// byte* bp = (byte*)p;
|
||||||
DisplayColorBuffer[i] = new Color32(*(bp++), *(bp++), *(bp++), *(bp++));
|
// DisplayColorBuffer[i] = new Color32(*(bp++), *(bp++), *(bp++), *(bp++));
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//wrapTex.LoadRawTextureData(wrapTexBufferPointer, TexBufferSize);
|
wrapTex.LoadRawTextureData(wrapTexBufferPointer, TexBufferSize);
|
||||||
wrapTex.SetPixels32(DisplayColorBuffer, 0);
|
//wrapTex.SetPixels32(DisplayColorBuffer, 0);
|
||||||
wrapTex.Apply();
|
wrapTex.Apply();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//public void SetDrawData(uint[] screenData, byte[] lineColorMode, int screenWidth, int screenHeight)
|
|
||||||
//{
|
|
||||||
// if (wrapTex == null)
|
|
||||||
// {
|
|
||||||
// //wrapTex = new Texture2D(272, 240, TextureFormat.BGRA32, false);
|
|
||||||
// wrapTex = new Texture2D(272, 240, TextureFormat.RGBA32, false);
|
|
||||||
// wrapTex.filterMode = FilterMode.Point;
|
|
||||||
// wrapTexBuffer = screenData;
|
|
||||||
|
|
||||||
// // 固定数组,防止垃圾回收器移动它
|
|
||||||
// GCHandle handle = GCHandle.Alloc(wrapTexBuffer, GCHandleType.Pinned);
|
|
||||||
// // 获取数组的指针
|
|
||||||
// wrapTexBufferPointer = handle.AddrOfPinnedObject();
|
|
||||||
|
|
||||||
// Image.texture = wrapTex;
|
|
||||||
// Image.material.SetTexture("_MainTex", wrapTex);
|
|
||||||
|
|
||||||
// TexBufferSize = wrapTexBuffer.Length * 4;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// wrapTex.LoadRawTextureData(wrapTexBufferPointer, TexBufferSize);
|
|
||||||
// wrapTex.Apply();
|
|
||||||
//}
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user