diff --git a/Assets/Game.unity b/Assets/Game.unity index 98b5053..45be518 100644 --- a/Assets/Game.unity +++ b/Assets/Game.unity @@ -182,11 +182,11 @@ MonoBehaviour: m_Calls: [] m_FontData: m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} - m_FontSize: 14 + m_FontSize: 53 m_FontStyle: 0 m_BestFit: 0 m_MinSize: 10 - m_MaxSize: 40 + m_MaxSize: 53 m_Alignment: 4 m_AlignByGeometry: 0 m_RichText: 1 @@ -907,8 +907,8 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: -471, y: -281} - m_SizeDelta: {x: 160, y: 30} + m_AnchoredPosition: {x: -560.94934, y: -316.46082} + m_SizeDelta: {x: 339.8987, y: 100.9216} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &1712987039 MonoBehaviour: diff --git a/Assets/emulator/AudioProvider.cs b/Assets/emulator/AudioProvider.cs index 5dbbfd8..05f30d2 100644 --- a/Assets/emulator/AudioProvider.cs +++ b/Assets/emulator/AudioProvider.cs @@ -14,9 +14,9 @@ public class AudioProvider : MonoBehaviour public void Awake() { - //var dummy = AudioClip.Create("dummy", 1,2, AudioSettings.outputSampleRate, false); - AudioClip clip = AudioClip.Create("blank", GbaAudio.SampleRate * 2, 2, GbaAudio.SampleRate, true); - _buffer = new RingBuffer(GbaAudio.SampleRate * 2); + AudioClip clip = AudioClip.Create("dummy", GbaAudio.SampleRate * 2, 2, GbaAudio.SampleRate, true); + AudioSettings.GetDSPBufferSize(out int bufferLength, out _); + _buffer = new RingBuffer(bufferLength * 2 * 2); m_as.clip = clip; m_as.playOnAwake = true; //m_as.loop = true; @@ -36,13 +36,9 @@ public class AudioProvider : MonoBehaviour for (int i = 0; i < data.Length; i += step) { if (_buffer.TryRead(out float rawData)) - { data[i] = rawData; - } else - { break; - } } //int step = channels; diff --git a/Assets/emulator/Emulator.cs b/Assets/emulator/Emulator.cs index 7944e01..bbde7f4 100644 --- a/Assets/emulator/Emulator.cs +++ b/Assets/emulator/Emulator.cs @@ -28,9 +28,9 @@ public class Emulator : MonoBehaviour Thread EmulationThread; AutoResetEvent ThreadSync = new AutoResetEvent(false); - private int _samplesAvailable; + //private int _samplesAvailable; //private PipeStream _pipeStream; - private byte[] _buffer; + //private byte[] _buffer; public float audioGain = 1.0f; // key delegate @@ -42,19 +42,11 @@ public class Emulator : MonoBehaviour private void Awake() { instance = this; - //BetterStreamingAssets.Initialize(); // must set it to 60 or it won't sync with audio or run too fast. Application.targetFrameRate = (int)FrameRate; - //audioSource = GetComponent(); - //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 - AudioSettings.GetDSPBufferSize(out int bufferLength, out _); - _samplesAvailable = bufferLength; + //AudioSettings.GetDSPBufferSize(out int bufferLength, out _); + //_samplesAvailable = bufferLength; // Must be set to 32768 var audioConfig = AudioSettings.GetConfiguration(); audioConfig.sampleRate = GbaAudio.SampleRate; @@ -62,7 +54,7 @@ public class Emulator : MonoBehaviour // Prepare our buffer //_pipeStream = new PipeStream(); //_pipeStream.MaxBufferLength = _samplesAvailable * 2 * sizeof(float); - _buffer = new byte[_samplesAvailable * 2 * sizeof(float)]; + //_buffer = new byte[_samplesAvailable * 2 * sizeof(float)]; } void Start() { @@ -155,15 +147,15 @@ public class Emulator : MonoBehaviour } } - public int GetOutputSampleRate() - { - return AudioSettings.outputSampleRate; - } + //public int GetOutputSampleRate() + //{ + // return AudioSettings.outputSampleRate; + //} - public int GetSamplesAvailable() - { - return _samplesAvailable; - } + //public int GetSamplesAvailable() + //{ + // return _samplesAvailable; + //} //private void OnAudioFilterRead(float[] data, int channels) //{ diff --git a/Assets/emulator/EmulatorGUI.cs b/Assets/emulator/EmulatorGUI.cs index ecd2e5f..a7a3798 100644 --- a/Assets/emulator/EmulatorGUI.cs +++ b/Assets/emulator/EmulatorGUI.cs @@ -33,6 +33,8 @@ public class EmulatorGUI : MonoBehaviour #if UNITY_EDITOR || UNITY_STANDALONE bool input = Input.GetKey( keyboardKeyCodeMap[keyCode]); if(input) return true;else return false; +#else + return false; #endif } } diff --git a/Assets/emulator/PpuRenderer.cs b/Assets/emulator/PpuRenderer.cs index cbe6de8..4bf70f2 100644 --- a/Assets/emulator/PpuRenderer.cs +++ b/Assets/emulator/PpuRenderer.cs @@ -6,6 +6,10 @@ using static OptimeGBA.MemoryUtil; using Unity.Burst.Intrinsics; using static Unity.Burst.Intrinsics.X86; +#if UNITY_STANDALONE_WIN || UNITY_EDITOR +#else + +#endif namespace OptimeGBA { public sealed unsafe class PpuRenderer @@ -39,7 +43,7 @@ namespace OptimeGBA WinMasks = MemoryUtil.AllocateUnmanagedArray(Width + 16); BgLo = MemoryUtil.AllocateUnmanagedArray32(width + 16); BgHi = MemoryUtil.AllocateUnmanagedArray32(width + 16); -#else +#else ScreenFront = new ushort[ScreenBufferSize]; ScreenBack = new ushort[ScreenBufferSize]; @@ -613,86 +617,91 @@ namespace OptimeGBA v256 indicesVec; uint paletteRow = 0; - if (bg.Use8BitColor) - { - clearMaskVec = new v256(0xFFU); + //mm256_cvtepu8_epi32 用于将无符号的8位整数(uint8)转换成32位整数(int32) - uint vramTileAddr = charBase + tileNumber * 64 + effectiveIntraTileY * 8; - ulong data = GetUlong(vram, vramTileAddr); + //{ + // if (bg.Use8BitColor) + // { + // clearMaskVec = new v256(0xFFU); - if (data != 0) - { - 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 vramTileAddr = charBase + tileNumber * 64 + effectiveIntraTileY * 8; + // ulong data = GetUlong(vram, vramTileAddr); - paletteRow = (mapEntry >> 12) & 0xF; - uint vramTileAddr = charBase + tileNumber * 32 + effectiveIntraTileY * 4; + // if (data != 0) + // { + // 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) - { - 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; - } - } + // uint data = GetUint(vram, vramTileAddr); - v256 color = Avx2.mm256_i32gather_epi32((int*)((ushort*)palettes + paletteRow * 16), indicesVec, sizeof(ushort)); - color = Avx2.mm256_and_si256(color, new v256(0xFFFF)); - // Weave metadata (priority, ID) into color data - color = Avx2.mm256_or_si256(color, Avx2.mm256_slli_epi32(metaVec, 16)); + // if (data != 0) + // { + // 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; + // } + // } - ulong addr = GetUlong(winMasks, lineIndex); - v256 winMask = Avx2.mm256_cvtepi8_epi32(new v128(addr)); - winMask = Avx2.mm256_and_si256(winMask, metaVec); - winMask = Avx2.mm256_cmpeq_epi32(winMask, new v256((byte)0)); - // Get important color bits - 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)); + // v256 color = Avx2.mm256_i32gather_epi32((int*)((ushort*)palettes + paletteRow * 16), indicesVec, sizeof(ushort)); + // color = Avx2.mm256_and_si256(color, new v256(0xFFFF)); + // // Weave metadata (priority, ID) into color data + // color = Avx2.mm256_or_si256(color, Avx2.mm256_slli_epi32(metaVec, 16)); + + // ulong addr = GetUlong(winMasks, lineIndex); + // v256 winMask = Avx2.mm256_cvtepi8_epi32(new v128(addr)); + // winMask = Avx2.mm256_and_si256(winMask, metaVec); + // winMask = Avx2.mm256_cmpeq_epi32(winMask, new v256((byte)0)); + // // Get important color bits + // 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; lineIndex += 8; diff --git a/Assets/emulator/VideoProvider.cs b/Assets/emulator/VideoProvider.cs index 68f1a70..9a7e7fa 100644 --- a/Assets/emulator/VideoProvider.cs +++ b/Assets/emulator/VideoProvider.cs @@ -13,12 +13,10 @@ public class VideoProvider : MonoBehaviour private Texture2D wrapTex; private int TexBufferSize; - uint[] wrapTexBuffer = new uint[240 * 160]; - Color32[] DisplayColorBuffer = new Color32[240 * 160]; + //Color32[] DisplayColorBuffer = new Color32[240 * 160]; - - public void OnRenderFrame() + private void Awake() { if (wrapTex == null) { @@ -39,10 +37,9 @@ public class VideoProvider : MonoBehaviour 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; unsafe @@ -50,41 +47,16 @@ public class VideoProvider : MonoBehaviour for (uint i = 0; i < 240 * 160; i++) { wrapTexBuffer[i] = PpuRenderer.ColorLutCorrected[buf[i] & 0x7FFF]; - fixed (uint* p = &wrapTexBuffer[i]) - { - byte* bp = (byte*)p; - DisplayColorBuffer[i] = new Color32(*(bp++), *(bp++), *(bp++), *(bp++)); - } + //fixed (uint* p = &wrapTexBuffer[i]) + //{ + // byte* bp = (byte*)p; + // DisplayColorBuffer[i] = new Color32(*(bp++), *(bp++), *(bp++), *(bp++)); + //} } } - //wrapTex.LoadRawTextureData(wrapTexBufferPointer, TexBufferSize); - wrapTex.SetPixels32(DisplayColorBuffer, 0); + wrapTex.LoadRawTextureData(wrapTexBufferPointer, TexBufferSize); + //wrapTex.SetPixels32(DisplayColorBuffer, 0); 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(); - //} } \ No newline at end of file