From 4da4a243cbd8ba2c8c56ed51e4ab8e3afb98ccce Mon Sep 17 00:00:00 2001 From: "ALIENJACK\\alien" Date: Fri, 9 Aug 2024 15:47:44 +0800 Subject: [PATCH] =?UTF-8?q?virtuaNES=20core=20=E4=BA=A7=E7=94=9F=E7=9A=84?= =?UTF-8?q?=E5=B1=8F=E5=B9=95=E6=95=B0=E6=8D=AE=E7=8E=B0=E5=9C=A8=E4=BD=BF?= =?UTF-8?q?=E7=94=A8Shader=E8=BF=9B=E8=A1=8C=E8=BD=AC=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Assets/Scene/EmuTest.unity | 10 +- .../Script/NesEmulator/AudioProvider.cs | 2 +- .../Script/NesEmulator/NesEmulator.prefab | 4 +- .../Script/NesEmulator/VideoProvider.cs | 53 ++++--- .../Script/NesEmulator/VirtuNesDraw.mat | 89 ++++++++++++ .../Script/NesEmulator/VirtuNesDraw.mat.meta | 8 ++ .../Script/NesEmulator/VirtuaNesDraw.shader | 130 ++++++++++++++++++ .../NesEmulator/VirtuaNesDraw.shader.meta | 10 ++ .../VirtualNes.Core/CoreLibs/MemoryUtility.cs | 16 +++ .../Assets/VirtualNes.Core/NES.cs | 2 +- .../Assets/VirtualNes.Core/PPU.cs | 6 +- 11 files changed, 292 insertions(+), 38 deletions(-) create mode 100644 AxibugEmuOnline.Client/Assets/Script/NesEmulator/VirtuNesDraw.mat create mode 100644 AxibugEmuOnline.Client/Assets/Script/NesEmulator/VirtuNesDraw.mat.meta create mode 100644 AxibugEmuOnline.Client/Assets/Script/NesEmulator/VirtuaNesDraw.shader create mode 100644 AxibugEmuOnline.Client/Assets/Script/NesEmulator/VirtuaNesDraw.shader.meta diff --git a/AxibugEmuOnline.Client/Assets/Scene/EmuTest.unity b/AxibugEmuOnline.Client/Assets/Scene/EmuTest.unity index 8e9ca8b..9804021 100644 --- a/AxibugEmuOnline.Client/Assets/Scene/EmuTest.unity +++ b/AxibugEmuOnline.Client/Assets/Scene/EmuTest.unity @@ -325,7 +325,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 4232056521131536012, guid: f8bea3f8aa351bb46ada33b2274729ea, type: 3} propertyPath: RomName - value: tstd2.nes + value: mario.nes objectReference: {fileID: 0} - target: {fileID: 4232056521131536013, guid: f8bea3f8aa351bb46ada33b2274729ea, type: 3} propertyPath: m_Name @@ -339,6 +339,14 @@ PrefabInstance: propertyPath: m_Texture value: objectReference: {fileID: 0} + - target: {fileID: 4232056521759880274, guid: f8bea3f8aa351bb46ada33b2274729ea, type: 3} + propertyPath: m_Material + value: + objectReference: {fileID: 2100000, guid: 07e28fcb992bc124e986f9d8ff3beb97, type: 2} + - target: {fileID: 4232056521759880275, guid: f8bea3f8aa351bb46ada33b2274729ea, type: 3} + propertyPath: m_SizeDelta.x + value: 256 + objectReference: {fileID: 0} - target: {fileID: 4232056521759880276, guid: f8bea3f8aa351bb46ada33b2274729ea, type: 3} propertyPath: m_IsActive value: 1 diff --git a/AxibugEmuOnline.Client/Assets/Script/NesEmulator/AudioProvider.cs b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/AudioProvider.cs index f4335b7..eebb2c9 100644 --- a/AxibugEmuOnline.Client/Assets/Script/NesEmulator/AudioProvider.cs +++ b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/AudioProvider.cs @@ -5,7 +5,7 @@ namespace AxibugEmuOnline.Client { public class AudioProvider : MonoBehaviour { - public NesEmulator NesEmu; + public NesEmulator NesEmu { get; set; } [SerializeField] private AudioSource m_as; diff --git a/AxibugEmuOnline.Client/Assets/Script/NesEmulator/NesEmulator.prefab b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/NesEmulator.prefab index 2c66afb..de3b472 100644 --- a/AxibugEmuOnline.Client/Assets/Script/NesEmulator/NesEmulator.prefab +++ b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/NesEmulator.prefab @@ -44,7 +44,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: a6a09b6a4cf4c2d4f994a13fd7e89d6f, type: 3} m_Name: m_EditorClassIdentifier: - NesEmu: {fileID: 0} + NesEmu: {fileID: 4232056521131536012} m_as: {fileID: 8726979175317618791} --- !u!82 &8726979175317618791 AudioSource: @@ -257,7 +257,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 83fbe375412d1af4482ae76e81c1dda2, type: 3} m_Name: m_EditorClassIdentifier: - NesEmu: {fileID: 0} + NesEmu: {fileID: 4232056521131536012} Image: {fileID: 4232056521759880274} --- !u!1 &4232056520494431712 GameObject: diff --git a/AxibugEmuOnline.Client/Assets/Script/NesEmulator/VideoProvider.cs b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/VideoProvider.cs index e21593b..4fa0d3e 100644 --- a/AxibugEmuOnline.Client/Assets/Script/NesEmulator/VideoProvider.cs +++ b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/VideoProvider.cs @@ -2,6 +2,7 @@ using System; using System.Runtime.InteropServices; using UnityEngine; using UnityEngine.UI; +using VirtualNes.Core; namespace AxibugEmuOnline.Client { @@ -16,48 +17,40 @@ namespace AxibugEmuOnline.Client private Texture2D wrapTex; private int TexBufferSize; - private uint[] pPal; - public void SetDrawData(byte[] screenData, byte[] lineColorMode, int screenWidth, int screenHeight) + private Texture2D pPal; + public void SetDrawData(uint[] screenData, byte[] lineColorMode, int screenWidth, int screenHeight) { if (wrapTex == null) { - wrapTex = new Texture2D(screenWidth, screenHeight, TextureFormat.BGRA32, false); - wrapTexBuffer = new UInt32[screenWidth * screenHeight]; + wrapTex = new Texture2D(272, 240, TextureFormat.BGRA32, false); + wrapTex.filterMode = FilterMode.Point; + wrapTexBuffer = screenData; + // ¹Ì¶¨Êý×飬·ÀÖ¹À¬»ø»ØÊÕÆ÷Òƶ¯Ëü GCHandle handle = GCHandle.Alloc(wrapTexBuffer, GCHandleType.Pinned); // »ñÈ¡Êý×éµÄÖ¸Õë wrapTexBufferPointer = handle.AddrOfPinnedObject(); - - Image.texture = wrapTex; - pPal = PaletteDefine.m_cnPalette[0]; + + Image.material.SetTexture("_MainTex", wrapTex); TexBufferSize = wrapTexBuffer.Length * 4; - } - int pScn = 0; - int width; - - var Dst = wrapTexBuffer; - var pDst = 0; - - for (int line = 0; line < screenHeight; line++) - { - width = screenWidth; - - while (width > 0) + var palRaw = PaletteDefine.m_cnPalette[0]; + pPal = new Texture2D(palRaw.Length, 1, TextureFormat.BGRA32, 1, true); + pPal.filterMode = FilterMode.Point; + for (int i = 0; i < palRaw.Length; i++) { - var edx = screenData[pScn + 8]; - - int index = edx & 0xFF; - var colorData = pPal[index]; - Dst[pDst] = 0xFF000000 | colorData; - - pScn += 1; - pDst += 1; - width -= 1; + uint colorRaw = palRaw[i]; + var argbColor = BitConverter.GetBytes(colorRaw); + Color temp = Color.white; + temp.r = argbColor[2]/255f; + temp.g = argbColor[1]/255f; + temp.b = argbColor[0]/255f; + temp.a = 1; + pPal.SetPixel(i, 0, temp); } - - pScn += 16;// PPU.SCREEN_WIDTH - screenWidth; + pPal.Apply(); + Image.material.SetTexture("_PalTex", pPal); } wrapTex.LoadRawTextureData(wrapTexBufferPointer, TexBufferSize); diff --git a/AxibugEmuOnline.Client/Assets/Script/NesEmulator/VirtuNesDraw.mat b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/VirtuNesDraw.mat new file mode 100644 index 0000000..105f730 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/VirtuNesDraw.mat @@ -0,0 +1,89 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: VirtuNesDraw + m_Shader: {fileID: 4800000, guid: b351396ff606116478d7f4412abe4e2e, type: 3} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _PalTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _ColorMask: 15 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _Stencil: 0 + - _StencilComp: 8 + - _StencilOp: 0 + - _StencilReadMask: 255 + - _StencilWriteMask: 255 + - _UVSec: 0 + - _UseUIAlphaClip: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + m_BuildTextureStacks: [] diff --git a/AxibugEmuOnline.Client/Assets/Script/NesEmulator/VirtuNesDraw.mat.meta b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/VirtuNesDraw.mat.meta new file mode 100644 index 0000000..4d65b1a --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/VirtuNesDraw.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 07e28fcb992bc124e986f9d8ff3beb97 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/Script/NesEmulator/VirtuaNesDraw.shader b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/VirtuaNesDraw.shader new file mode 100644 index 0000000..99400dc --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/VirtuaNesDraw.shader @@ -0,0 +1,130 @@ +Shader "AleinUI/Clip" +{ + Properties + { + _MainTex ("Sprite Texture", 2D) = "white" {} + _PalTex ("PAL", 2D) = "white" {} + _Color ("Tint", Color) = (1,1,1,1) + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _ColorMask ("Color Mask", Float) = 15 + + + [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0 + } + + SubShader + { + Tags + { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + "PreviewType"="Plane" + "CanUseSpriteAtlas"="True" + } + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull Off + Lighting Off + ZWrite Off + ZTest [unity_GUIZTestMode] + Blend SrcAlpha OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass + { + Name "Default" + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma target 2.0 + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + + #pragma multi_compile_local _ UNITY_UI_CLIP_RECT + #pragma multi_compile_local _ UNITY_UI_ALPHACLIP + + struct appdata_t + { + float4 vertex : POSITION; + float4 color : COLOR; + float2 texcoord : TEXCOORD0; + UNITY_VERTEX_INPUT_INSTANCE_ID + }; + + struct v2f + { + float4 vertex : SV_POSITION; + fixed4 color : COLOR; + float2 texcoord : TEXCOORD0; + float4 worldPosition : TEXCOORD1; + UNITY_VERTEX_OUTPUT_STEREO + }; + + sampler2D _MainTex; + fixed4 _Color; + fixed4 _TextureSampleAdd; + float4 _ClipRect; + float4 _MainTex_ST; + float4 _MainTex_TexelSize; + sampler2D _PalTex; + + v2f vert(appdata_t v) + { + v2f OUT; + UNITY_SETUP_INSTANCE_ID(v); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); + OUT.worldPosition = v.vertex; + OUT.vertex = UnityObjectToClipPos(OUT.worldPosition); + + OUT.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex); + + OUT.color = v.color * _Color; + return OUT; + } + + fixed4 frag(v2f IN) : SV_Target + { + float2 mapUV = IN.texcoord; + + float start= 8.0/272.0; + float end = (272.0-8.0)/272.0; + + //mapUV.x = lerp(start,end, mapUV.x); + + half4 color = tex2D(_MainTex,mapUV); + + float rawIndex = color.b; + + color = tex2D(_PalTex,float2(rawIndex,0.5)); + + #ifdef UNITY_UI_CLIP_RECT + color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect); + #endif + + #ifdef UNITY_UI_ALPHACLIP + clip (color.a - 0.001); + #endif + + + return color; + } + ENDCG + } + } +} \ No newline at end of file diff --git a/AxibugEmuOnline.Client/Assets/Script/NesEmulator/VirtuaNesDraw.shader.meta b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/VirtuaNesDraw.shader.meta new file mode 100644 index 0000000..626d908 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/VirtuaNesDraw.shader.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: b351396ff606116478d7f4412abe4e2e +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + preprocessorOverride: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/MemoryUtility.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/MemoryUtility.cs index 691ec13..f8bd081 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/MemoryUtility.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/MemoryUtility.cs @@ -19,6 +19,14 @@ namespace VirtualNes.Core memset(array, 0, value, length); } + public static void memset(uint[] array, uint value, int length) + { + for (int i = 0; i < length; i++) + { + array[i] = value; + } + } + public static void memset(byte[] array, int offset, byte value, int length) { for (int i = offset; i < length; i++) @@ -26,5 +34,13 @@ namespace VirtualNes.Core array[i] = value; } } + + public static void memset(uint[] array, int offset, uint value, int length) + { + for (int i = offset; i < length; i++) + { + array[i] = value; + } + } } } diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/NES.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/NES.cs index 0fce4a7..e02ce41 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/NES.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/NES.cs @@ -225,7 +225,7 @@ namespace VirtualNes.Core Debuger.Log("Allocating PPU..."); ppu = new PPU(this); - var screenBuffer = new byte[PPU.SCREEN_WIDTH * PPU.SCREEN_HEIGHT]; + var screenBuffer = new uint[PPU.SCREEN_WIDTH * PPU.SCREEN_HEIGHT]; var colormode = new byte[PPU.SCREEN_HEIGHT]; ppu.SetScreenPtr(screenBuffer, colormode); diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PPU.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PPU.cs index 46fa90b..a33b44e 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PPU.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PPU.cs @@ -106,7 +106,7 @@ namespace VirtualNes.Core private ushort loopy_y; private ushort loopy_shift; - private byte[] lpScreen; + private uint[] lpScreen; /// 作为lpScreen数组的索引 private int lpScanline; private int ScanlineNo; @@ -1105,7 +1105,7 @@ namespace VirtualNes.Core MMU.PPUREG[2] |= PPU_VBLANK_FLAG; } - public byte[] GetScreenPtr() + public uint[] GetScreenPtr() { return lpScreen; } @@ -1115,7 +1115,7 @@ namespace VirtualNes.Core return lpColormode; } - internal void SetScreenPtr(byte[] screenBuffer, byte[] colormode) + internal void SetScreenPtr(uint[] screenBuffer, byte[] colormode) { lpScreen = screenBuffer; lpColormode = colormode; -- 2.36.0.windows.1