This commit is contained in:
sin365 2024-08-16 21:50:32 +08:00
parent 8d0487be8b
commit 68d8c7d3b2
6 changed files with 115 additions and 144 deletions

View File

@ -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:

View File

@ -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;

View File

@ -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)
//{ //{

View File

@ -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
} }
} }

View File

@ -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;

View File

@ -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();
//}
} }