diff --git a/.gitignore b/.gitignore index 44e618d..41a8bcd 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ /AxibugEmuOnline.Client/ProjectSettings/ProjectVersion.txt /AxibugEmuOnline.Client/ProjectSettings/AutoStreamingSettings.asset /AxibugEmuOnline.Client/Logs +/virtuanessrc097-master/save diff --git a/AxibugEmuOnline.Client/Assets/Script/NesEmulator/CoreDebuger.cs b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/CoreDebuger.cs index d031095..cdf1191 100644 --- a/AxibugEmuOnline.Client/Assets/Script/NesEmulator/CoreDebuger.cs +++ b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/CoreDebuger.cs @@ -7,6 +7,7 @@ namespace AxibugEmuOnline.Client { public class CoreDebuger : IDebugerImpl { + public void Log(string message) { Debug.Log(message); diff --git a/AxibugEmuOnline.Client/Assets/Script/NesEmulator/NesEmulator.cs b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/NesEmulator.cs index 411c3c0..a7c7010 100644 --- a/AxibugEmuOnline.Client/Assets/Script/NesEmulator/NesEmulator.cs +++ b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/NesEmulator.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using UnityEngine; using VirtualNes.Core; using VirtualNes.Core.Debug; @@ -26,7 +27,6 @@ namespace AxibugEmuOnline.Client try { m_nesIns = new NES(romName); - m_nesIns.Command(NESCOMMAND.NESCMD_HWRESET); } catch (Exception ex) { @@ -46,9 +46,17 @@ namespace AxibugEmuOnline.Client if (m_nesIns != null) { m_nesIns.EmulateFrame(true); + var screenBuffer = m_nesIns.ppu.GetScreenPtr(); - VideoProvider.SetDrawData(screenBuffer, PPU.SCREEN_WIDTH, PPU.SCREEN_HEIGHT); + var lineColorMode = m_nesIns.ppu.GetLineColorMode(); + + VideoProvider.SetDrawData(screenBuffer, lineColorMode, 256, 240); } } + + private void OnDestroy() + { + File.WriteAllLines("E:/log.txt", Debuger.logRecords); + } } } diff --git a/AxibugEmuOnline.Client/Assets/Script/NesEmulator/PaletteDefine.cs b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/PaletteDefine.cs new file mode 100644 index 0000000..4cb4fd3 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/PaletteDefine.cs @@ -0,0 +1,242 @@ +using Codice.CM.Client.Differences; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; +using VirtualNes.Core; + +namespace AxibugEmuOnline.Client.Assets.Script.NesEmulator +{ + public static class PaletteDefine + { + public class PALBUF + { + public byte r; + public byte g; + public byte b; + + public PALBUF(byte r, byte g, byte b) + { + this.r = r; + this.g = g; + this.b = b; + } + } + + // スキャンラインカラー + private static int m_nScanlineColor => Supporter.Config.graphics.nScanlineColor; + + public static float[][] PalConvTbl = new float[8][] + { + new float[3]{1.00f, 1.00f, 1.00f}, + new float[3]{1.00f, 0.80f, 0.73f}, + new float[3]{0.73f, 1.00f, 0.70f}, + new float[3]{0.76f, 0.78f, 0.58f}, + new float[3]{0.86f, 0.80f, 1.00f}, + new float[3]{0.83f, 0.68f, 0.85f}, + new float[3]{0.67f, 0.77f, 0.83f}, + new float[3]{0.68f, 0.68f, 0.68f}, + }; + + public static PALBUF[] m_PaletteBuf = new PALBUF[64] + { + new PALBUF(0x7F, 0x7F, 0x7F), + new PALBUF(0x20, 0x00, 0xB0), + new PALBUF(0x28, 0x00, 0xB8), + new PALBUF(0x60, 0x10, 0xA0), + new PALBUF(0x98, 0x20, 0x78), + new PALBUF(0xB0, 0x10, 0x30), + new PALBUF(0xA0, 0x30, 0x00), + new PALBUF(0x78, 0x40, 0x00), + new PALBUF(0x48, 0x58, 0x00), + new PALBUF(0x38, 0x68, 0x00), + new PALBUF(0x38, 0x6C, 0x00), + new PALBUF(0x30, 0x60, 0x40), + new PALBUF(0x30, 0x50, 0x80), + new PALBUF(0x00, 0x00, 0x00), + new PALBUF(0x00, 0x00, 0x00), + new PALBUF(0x00, 0x00, 0x00), + new PALBUF(0xBC, 0xBC, 0xBC), + new PALBUF(0x40, 0x60, 0xF8), + new PALBUF(0x40, 0x40, 0xFF), + new PALBUF(0x90, 0x40, 0xF0), + new PALBUF(0xD8, 0x40, 0xC0), + new PALBUF(0xD8, 0x40, 0x60), + new PALBUF(0xE0, 0x50, 0x00), + new PALBUF(0xC0, 0x70, 0x00), + new PALBUF(0x88, 0x88, 0x00), + new PALBUF(0x50, 0xA0, 0x00), + new PALBUF(0x48, 0xA8, 0x10), + new PALBUF(0x48, 0xA0, 0x68), + new PALBUF(0x40, 0x90, 0xC0), + new PALBUF(0x00, 0x00, 0x00), + new PALBUF(0x00, 0x00, 0x00), + new PALBUF(0x00, 0x00, 0x00), + new PALBUF(0xFF, 0xFF, 0xFF), + new PALBUF(0x60, 0xA0, 0xFF), + new PALBUF(0x50, 0x80, 0xFF), + new PALBUF(0xA0, 0x70, 0xFF), + new PALBUF(0xF0, 0x60, 0xFF), + new PALBUF(0xFF, 0x60, 0xB0), + new PALBUF(0xFF, 0x78, 0x30), + new PALBUF(0xFF, 0xA0, 0x00), + new PALBUF(0xE8, 0xD0, 0x20), + new PALBUF(0x98, 0xE8, 0x00), + new PALBUF(0x70, 0xF0, 0x40), + new PALBUF(0x70, 0xE0, 0x90), + new PALBUF(0x60, 0xD0, 0xE0), + new PALBUF(0x60, 0x60, 0x60), + new PALBUF(0x00, 0x00, 0x00), + new PALBUF(0x00, 0x00, 0x00), + new PALBUF(0xFF, 0xFF, 0xFF), + new PALBUF(0x90, 0xD0, 0xFF), + new PALBUF(0xA0, 0xB8, 0xFF), + new PALBUF(0xC0, 0xB0, 0xFF), + new PALBUF(0xE0, 0xB0, 0xFF), + new PALBUF(0xFF, 0xB8, 0xE8), + new PALBUF(0xFF, 0xC8, 0xB8), + new PALBUF(0xFF, 0xD8, 0xA0), + new PALBUF(0xFF, 0xF0, 0x90), + new PALBUF(0xC8, 0xF0, 0x80), + new PALBUF(0xA0, 0xF0, 0xA0), + new PALBUF(0xA0, 0xFF, 0xC8), + new PALBUF(0xA0, 0xFF, 0xF0), + new PALBUF(0xA0, 0xA0, 0xA0), + new PALBUF(0x00, 0x00, 0x00), + new PALBUF(0x00, 0x00, 0x00), + }; + + #region ピクセルフォーマットに変換したパレット + // Color + public static uint[][] m_cnPalette = new uint[8][] + { + new uint[256], + new uint[256], + new uint[256], + new uint[256], + new uint[256], + new uint[256], + new uint[256], + new uint[256], + }; + // Color/Scanline + public static uint[][] m_csPalette = new uint[8][] + { + new uint[256], + new uint[256], + new uint[256], + new uint[256], + new uint[256], + new uint[256], + new uint[256], + new uint[256], + }; + + // Monochrome + public static uint[][] m_mnPalette = new uint[8][] + { + new uint[256], + new uint[256], + new uint[256], + new uint[256], + new uint[256], + new uint[256], + new uint[256], + new uint[256], + }; + + // Monochrome/Scanline + public static uint[][] m_msPalette = new uint[8][] + { + new uint[256], + new uint[256], + new uint[256], + new uint[256], + new uint[256], + new uint[256], + new uint[256], + new uint[256], + }; + #endregion + + static PaletteDefine() + { + int Rbit = 0, Gbit = 0, Bbit = 0; + int Rsft = 0, Gsft = 0, Bsft = 0; + + GetBitMask(0xFF0000, ref Rsft, ref Rbit); + GetBitMask(0x00FF00, ref Gsft, ref Gbit); + GetBitMask(0x0000FF, ref Bsft, ref Bbit); + + for (int j = 0; j < 8; j++) + { + for (int i = 0; i < 64; i++) + { + uint Rn, Gn, Bn; + uint Rs, Gs, Bs; + + // Normal + Rn = (uint)(PalConvTbl[j][0] * m_PaletteBuf[i].r); + Gn = (uint)(PalConvTbl[j][1] * m_PaletteBuf[i].g); + Bn = (uint)(PalConvTbl[j][2] * m_PaletteBuf[i].b); + // Scanline + Rs = (uint)(PalConvTbl[j][0] * m_PaletteBuf[i].r * m_nScanlineColor / 100.0f); + Gs = (uint)(PalConvTbl[j][1] * m_PaletteBuf[i].g * m_nScanlineColor / 100.0f); + Bs = (uint)(PalConvTbl[j][2] * m_PaletteBuf[i].b * m_nScanlineColor / 100.0f); + + m_cnPalette[j][i] = ((Rn >> (8 - Rbit)) << Rsft) | ((Gn >> (8 - Gbit)) << Gsft) | ((Bn >> (8 - Bbit)) << Bsft); + m_csPalette[j][i] = ((Rs >> (8 - Rbit)) << Rsft) | ((Gs >> (8 - Gbit)) << Gsft) | ((Bs >> (8 - Bbit)) << Bsft); + + // Monochrome + Rn = (uint)(m_PaletteBuf[i & 0x30].r); + Gn = (uint)(m_PaletteBuf[i & 0x30].g); + Bn = (uint)(m_PaletteBuf[i & 0x30].b); + Rn = + Gn = + Bn = (uint)(0.299f * Rn + 0.587f * Gn + 0.114f * Bn); + Rn = (uint)(PalConvTbl[j][0] * Rn); + Gn = (uint)(PalConvTbl[j][1] * Gn); + Bn = (uint)(PalConvTbl[j][2] * Bn); + if (Rn > 0xFF) Rs = 0xFF; + if (Gn > 0xFF) Gs = 0xFF; + if (Bn > 0xFF) Bs = 0xFF; + // Scanline + Rs = (uint)(m_PaletteBuf[i & 0x30].r * m_nScanlineColor / 100.0f); + Gs = (uint)(m_PaletteBuf[i & 0x30].g * m_nScanlineColor / 100.0f); + Bs = (uint)(m_PaletteBuf[i & 0x30].b * m_nScanlineColor / 100.0f); + Rs = + Gs = + Bs = (uint)(0.299f * Rs + 0.587f * Gs + 0.114f * Bs); + Rs = (uint)(PalConvTbl[j][0] * Rs); + Gs = (uint)(PalConvTbl[j][1] * Gs); + Bs = (uint)(PalConvTbl[j][2] * Bs); + if (Rs > 0xFF) Rs = 0xFF; + if (Gs > 0xFF) Gs = 0xFF; + if (Bs > 0xFF) Bs = 0xFF; + + m_mnPalette[j][i] = ((Rn >> (8 - Rbit)) << Rsft) | ((Gn >> (8 - Gbit)) << Gsft) | ((Bn >> (8 - Bbit)) << Bsft); + m_msPalette[j][i] = ((Rs >> (8 - Rbit)) << Rsft) | ((Gs >> (8 - Gbit)) << Gsft) | ((Bs >> (8 - Bbit)) << Bsft); + } + } + } + + // ビット位置の取得 + static void GetBitMask(uint val, ref int shift, ref int bits) + { + shift = 0; + while (((val & (1 << shift)) == 0) && (shift < 32)) + { + shift++; + } + + bits = 32; + while (((val & (1 << (bits - 1))) == 0) && (bits > 0)) + { + bits--; + } + bits = bits - shift; + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/Script/NesEmulator/PaletteDefine.cs.meta b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/PaletteDefine.cs.meta new file mode 100644 index 0000000..d93c9c2 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/PaletteDefine.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bbd3f54279eb4ae45831a914b13d1cec +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/Script/NesEmulator/VideoProvider.cs b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/VideoProvider.cs index f077271..662bac7 100644 --- a/AxibugEmuOnline.Client/Assets/Script/NesEmulator/VideoProvider.cs +++ b/AxibugEmuOnline.Client/Assets/Script/NesEmulator/VideoProvider.cs @@ -1,8 +1,13 @@ +using AxibugEmuOnline.Client.Assets.Script.NesEmulator; +using Codice.CM.Client.Differences; +using System; using System.Collections; using System.Collections.Generic; using System.Linq; +using System.Text; using UnityEngine; using UnityEngine.UI; +using VirtualNes.Core; namespace AxibugEmuOnline.Client { @@ -12,14 +17,56 @@ namespace AxibugEmuOnline.Client private Texture2D wrapTex; - public void SetDrawData(byte[] data, int width, int height) + public void SetDrawData(byte[] screenData, byte[] lineColorMode, int screenWidth, int screenHeight) { - if (wrapTex == null) wrapTex = new Texture2D(width, height); + if (wrapTex == null) wrapTex = new Texture2D(screenWidth, screenHeight); - var colors = data.Select(d => new Color((d / 255f), (d / 255f), (d / 255f), 1)).ToArray(); - wrapTex.SetPixels(colors); + var str = Encoding.ASCII.GetString(screenData, 0, screenData.Length); + + uint[] pPal; + int pScn = 0; + int width; + + var Dst = wrapTex.GetPixels32(); + var pDst = 0; + + for (int line = 0; line < screenHeight; line++) + { + if ((lineColorMode[line] & 0x80) != 0) + { + pPal = PaletteDefine.m_cnPalette[lineColorMode[line] & 0x07]; + } + else + { + pPal = PaletteDefine.m_mnPalette[lineColorMode[line] & 0x07]; + } + + width = screenWidth; + + while (width > 0) + { + Color32 temp = new Color32(255, 255, 255, 255); + var edx = screenData[pScn]; + + byte index = (byte)(edx & 0xFF); + var colorData = pPal[index]; + var rawData = BitConverter.GetBytes(colorData); + Dst[pDst] = new Color32(rawData[0], rawData[1], rawData[2], 255); + + pScn += 1; + pDst += 1; + width -= 1; + } + + pScn += PPU.SCREEN_WIDTH - screenWidth; + } + + wrapTex.SetPixels32(Dst); wrapTex.Apply(); - Graphics.Blit(wrapTex, Image.texture as RenderTexture); + + Graphics.Blit(wrapTex, Image.mainTexture as RenderTexture); } + + } } diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CPU.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CPU.cs index 2b5fad9..4594c8b 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CPU.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CPU.cs @@ -1169,7 +1169,7 @@ namespace VirtualNes.Core return (ushort)(nes.Read(addr) + nes.Read((ushort)(addr + 1)) * 0x100); } - var temp = MMU.CPU_MEM_BANK[addr >> 13].Span; + var temp = MMU.CPU_MEM_BANK[addr >> 13]; shortTemp[0] = temp[addr & 0x1FFF]; shortTemp[1] = temp[(addr & 0x1FFF) + 1]; return BitConverter.ToUInt16(shortTemp, 0); @@ -1716,14 +1716,14 @@ namespace VirtualNes.Core internal byte OP6502(ushort addr) { - return MMU.CPU_MEM_BANK[addr >> 13].Span[addr & 0x1FFF]; + return MMU.CPU_MEM_BANK[addr >> 13][addr & 0x1FFF]; } private byte[] shortTemp = new byte[2]; internal ushort OP6502W(ushort addr) { var bytePage = MMU.CPU_MEM_BANK[addr >> 13]; - var spanByte = bytePage.Span; + var spanByte = bytePage; shortTemp[0] = spanByte[addr & 0x1FFF]; shortTemp[1] = spanByte[(addr & 0x1FFF) + 1]; return BitConverter.ToUInt16(shortTemp, 0); @@ -1744,11 +1744,11 @@ namespace VirtualNes.Core else { // Dummy access - mapper.Read(addr, MMU.CPU_MEM_BANK[addr >> 13].Span[addr & 0x1FFF]); + mapper.Read(addr, MMU.CPU_MEM_BANK[addr >> 13][addr & 0x1FFF]); } // Quick bank read - return MMU.CPU_MEM_BANK[addr >> 13].Span[addr & 0x1FFF]; + return MMU.CPU_MEM_BANK[addr >> 13][addr & 0x1FFF]; } private void AND() diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/ByteArrayRef.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/ByteArrayRef.cs new file mode 100644 index 0000000..4966557 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/ByteArrayRef.cs @@ -0,0 +1,28 @@ +namespace VirtualNes.Core +{ + public class ByteArrayRef + { + private byte[] m_rawArray; + private int m_offset; + private int m_length; + + public ByteArrayRef(byte[] array, int offset, int length) + { + m_rawArray = array; + m_offset = offset; + m_length = length; + } + + public byte this[int index] + { + get + { + return m_rawArray[m_offset + index]; + } + set + { + m_rawArray[(m_offset + index)] = value; + } + } + } +} diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/ByteArrayRef.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/ByteArrayRef.cs.meta new file mode 100644 index 0000000..eba7e42 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/CoreLibs/ByteArrayRef.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fe59f85b299db6f498a7e87a5125df58 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Debuger.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Debuger.cs index 8845558..526ef75 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Debuger.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Debuger.cs @@ -1,7 +1,11 @@ -namespace VirtualNes.Core.Debug +using System.Collections.Generic; + +namespace VirtualNes.Core.Debug { public static class Debuger { + public static List logRecords = new List(); + private static IDebugerImpl s_debuger; public static void Setup(IDebugerImpl debuger) { @@ -10,6 +14,7 @@ public static void Log(string message) { s_debuger.Log(message); + logRecords.Add(message); } public static void LogError(string message) diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/MMU.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/MMU.cs index 790f5ed..2ce14c8 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/MMU.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/MMU.cs @@ -1,15 +1,16 @@ using System; +using VirtualNes.Core; namespace VirtualNes { public static class MMU { // CPU 儊儌儕僶儞僋 - public static Memory[] CPU_MEM_BANK = new Memory[8]; // 8K扨埵 + public static ByteArrayRef[] CPU_MEM_BANK = new ByteArrayRef[8]; // 8K扨埵 public static byte[] CPU_MEM_TYPE = new byte[8]; public static int[] CPU_MEM_PAGE = new int[8]; // 僗僥乕僩僙乕僽梡 // PPU 儊儌儕僶儞僋 - public static Memory[] PPU_MEM_BANK = new Memory[12]; // 1K扨埵 + public static ByteArrayRef[] PPU_MEM_BANK = new ByteArrayRef[12]; // 1K扨埵 public static byte[] PPU_MEM_TYPE = new byte[12]; public static int[] PPU_MEM_PAGE = new int[12]; // 僗僥乕僩僙乕僽梡 public static byte[] CRAM_USED = new byte[16]; // 僗僥乕僩僙乕僽梡 @@ -70,9 +71,9 @@ namespace VirtualNes // Frame-IRQ儗僕僗僞($4017) public static int FrameIRQ; - internal static void SetPROM_Bank(byte page, Memory ptr, byte type) + internal static void SetPROM_Bank(byte page, byte[] ptr, byte type) { - CPU_MEM_BANK[page] = ptr; + CPU_MEM_BANK[page] = new ByteArrayRef(ptr, 0, ptr.Length); CPU_MEM_TYPE[page] = type; CPU_MEM_PAGE[page] = 0; } @@ -80,7 +81,7 @@ namespace VirtualNes internal static void SetPROM_8K_Bank(byte page, int bank) { bank %= PROM_8K_SIZE; - CPU_MEM_BANK[page] = new Memory(MMU.PROM, 0x2000 * bank, MMU.PROM.Length - 0x2000 * bank); + CPU_MEM_BANK[page] = new ByteArrayRef(MMU.PROM, 0x2000 * bank, MMU.PROM.Length - 0x2000 * bank); CPU_MEM_TYPE[page] = BANKTYPE_ROM; CPU_MEM_PAGE[page] = bank; } @@ -108,7 +109,7 @@ namespace VirtualNes } // PPU VROM bank - internal static void SetVROM_Bank(byte page, Memory ptr, byte type) + internal static void SetVROM_Bank(byte page, ByteArrayRef ptr, byte type) { PPU_MEM_BANK[page] = ptr; PPU_MEM_TYPE[page] = type; @@ -118,7 +119,7 @@ namespace VirtualNes internal static void SetVROM_1K_Bank(byte page, int bank) { bank %= VROM_1K_SIZE; - PPU_MEM_BANK[page] = new Memory(VROM, 0x0400 * bank, VROM.Length - (0x0400 * bank)); + PPU_MEM_BANK[page] = new ByteArrayRef(VROM, 0x0400 * bank, VROM.Length - (0x0400 * bank)); PPU_MEM_TYPE[page] = BANKTYPE_VROM; PPU_MEM_PAGE[page] = bank; } @@ -161,7 +162,7 @@ namespace VirtualNes internal static void SetCRAM_1K_Bank(byte page, int bank) { bank &= 0x1F; - PPU_MEM_BANK[page] = new Memory(MMU.CRAM, 0x0400 * bank, MMU.CRAM.Length - 0x0400 * bank); + PPU_MEM_BANK[page] = new ByteArrayRef(MMU.CRAM, 0x0400 * bank, MMU.CRAM.Length - 0x0400 * bank); PPU_MEM_TYPE[page] = BANKTYPE_CRAM; PPU_MEM_PAGE[page] = bank; @@ -193,7 +194,7 @@ namespace VirtualNes internal static void SetVRAM_1K_Bank(byte page, int bank) { bank &= 3; - PPU_MEM_BANK[page] = new Memory(VRAM, 0x0400 * bank, VRAM.Length - 0x0400 * bank); + PPU_MEM_BANK[page] = new ByteArrayRef(VRAM, 0x0400 * bank, VRAM.Length - 0x0400 * bank); PPU_MEM_TYPE[page] = BANKTYPE_VRAM; PPU_MEM_PAGE[page] = bank; } diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper.cs index 542201a..c61fae7 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper.cs @@ -26,7 +26,7 @@ namespace VirtualNes.Core // $6000-$7FFF WRAM if (addr >= 0x6000 && addr <= 0x7FFF) { - return MMU.CPU_MEM_BANK[addr >> 13].Span[addr & 0x1FFF]; + return MMU.CPU_MEM_BANK[addr >> 13][addr & 0x1FFF]; } return (byte)(addr >> 8); @@ -35,7 +35,7 @@ namespace VirtualNes.Core { if (addr >= 0x6000 && addr <= 0x7FFF) { - MMU.CPU_MEM_BANK[addr >> 13].Span[addr & 0x1FFF] = data; + MMU.CPU_MEM_BANK[addr >> 13][addr & 0x1FFF] = data; } } diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/NES.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/NES.cs index d6359e2..aad3066 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/NES.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/NES.cs @@ -75,6 +75,10 @@ namespace VirtualNes.Core private long base_cycles; private long emul_cycles; + // For VS-Unisystem + byte m_VSDipValue; + VSDIPSWITCH[] m_VSDipTable; + private byte[] m_PadImg = new byte[226] { 28, 8, @@ -253,6 +257,65 @@ namespace VirtualNes.Core NesSub_MemoryInitial(); LoadSRAM(); LoadDISK(); + + { + // Pad饹ڤȳڻߥ󥰤WΤǤ + uint crc = rom.GetPROM_CRC(); + if ( + crc == 0xe792de94 // Best Play - Pro Yakyuu (New) (J) + || crc == 0xf79d684a // Best Play - Pro Yakyuu (Old) (J) + || crc == 0xc2ef3422 // Best Play - Pro Yakyuu 2 (J) + || crc == 0x974e8840 // Best Play - Pro Yakyuu '90 (J) + || crc == 0xb8747abf // Best Play - Pro Yakyuu Special (J) + || crc == 0x9fa1c11f // Castle Excellent (J) + || crc == 0x0b0d4d1b // Derby Stallion - Zenkoku Ban (J) + || crc == 0x728c3d98 // Downtown - Nekketsu Monogatari (J) + || crc == 0xd68a6f33 // Dungeon Kid (J) + || crc == 0x3a51eb04 // Fleet Commander (J) + || crc == 0x7c46998b // Haja no Fuuin (J) + || crc == 0x7e5d2f1a // Itadaki Street - Watashi no Mise ni Yottette (J) + || crc == 0xcee5857b // Ninjara Hoi! (J) + || crc == 0x50ec5e8b // Wizardry - Legacy of Llylgamyn (J) + || crc == 0x343e9146 // Wizardry - Proving Grounds of the Mad Overlord (J) + || crc == 0x33d07e45) + { // Wizardry - The Knight of Diamonds (J) + pad.SetExController(EXCONTROLLER.EXCONTROLLER_TURBOFILE); + } + } + + LoadTurboFile(); + + // VS-UnisystemΥǥեO + if (rom.IsVSUNISYSTEM()) + { + uint crc = rom.GetPROM_CRC(); + + m_VSDipValue = 0; + m_VSDipTable = VsUnisystem.vsdip_default; + } + + Reset(); + + // `ФΥǥեȥץO(Orʹ) + GameOption.defRenderMethod = (int)GetRenderMethod(); + GameOption.defIRQtype = GetIrqType(); + GameOption.defFrameIRQ = GetFrameIRQmode(); + GameOption.defVideoMode = GetVideoMode(); + + // O`ɤO(ȥ꤬oХǥեȤ) + if (rom.GetMapperNo() != 20) + { + GameOption.Load(rom.GetPROM_CRC()); + } + else + { + GameOption.Load(rom.GetGameID(), rom.GetMakerID()); + } + + SetRenderMethod((EnumRenderMethod)GameOption.nRenderMethod); + SetIrqType((IRQMETHOD)GameOption.nIRQtype); + SetFrameIRQmode(GameOption.bFrameIRQ); + SetVideoMode(GameOption.bVideoMode); } catch (Exception ex) { @@ -261,6 +324,44 @@ namespace VirtualNes.Core } } + private int GetIrqType() + { + return nIRQtype; + } + + private void LoadTurboFile() + { + MemoryUtility.ZEROMEMORY(MMU.ERAM, MMU.ERAM.Length); + + if (pad.GetExController() != (int)EXCONTROLLER.EXCONTROLLER_TURBOFILE) + return; + + var fp = Supporter.OpenFile(Supporter.Config.path.szSavePath, "TurboFile.vtf"); + try + { + if (fp == null) + { + // xxx ե_ޤ + throw new Exception($"Can Not Open File [TurboFile.vtf]"); + } + + long size = fp.Length; + // ե륵ȡ + if (size > 32 * 1024) + { + size = 32 * 1024; + } + + fp.Read(MMU.ERAM, 0, MMU.ERAM.Length); + fp.Close(); + } + catch (Exception ex) + { + fp?.Close(); + Debuger.LogError($"Loading TurboFile Error.\n{ex}"); + } + } + private void LoadDISK() { //todo : ŵȡ֧ @@ -1308,7 +1409,7 @@ namespace VirtualNes.Core case 0x05: // $A000-$BFFF case 0x06: // $C000-$DFFF case 0x07: // $E000-$FFFF - return MMU.CPU_MEM_BANK[addr >> 13].Span[addr & 0x1FFF]; + return MMU.CPU_MEM_BANK[addr >> 13][addr & 0x1FFF]; } return 0x00; // Warning\h @@ -1414,8 +1515,13 @@ namespace VirtualNes.Core return ret; } + static int NESWRITECOUNT = 0; internal void Write(ushort addr, byte data) { + NESWRITECOUNT++; + + Debuger.Log($"[{NESWRITECOUNT}] addr:{addr},data:{data}"); + switch (addr >> 13) { case 0x00: // $0000-$1FFF @@ -1461,16 +1567,16 @@ namespace VirtualNes.Core if ((addr & 0x8000) != 0) { // 8character codes - if (MMU.CPU_MEM_BANK[addr >> 13].Span[addr & 0x1FFF] == m_GenieCode[i].cmp) + if (MMU.CPU_MEM_BANK[addr >> 13][addr & 0x1FFF] == m_GenieCode[i].cmp) { - MMU.CPU_MEM_BANK[addr >> 13].Span[addr & 0x1FFF] = m_GenieCode[i].data; + MMU.CPU_MEM_BANK[addr >> 13][addr & 0x1FFF] = m_GenieCode[i].data; } } else { // 6character codes addr |= 0x8000; - MMU.CPU_MEM_BANK[addr >> 13].Span[addr & 0x1FFF] = m_GenieCode[i].data; + MMU.CPU_MEM_BANK[addr >> 13][addr & 0x1FFF] = m_GenieCode[i].data; } } } diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PAD.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PAD.cs index df417bb..01f5df1 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PAD.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PAD.cs @@ -330,7 +330,7 @@ namespace VirtualNes.Core } } - private void SetExController(EXCONTROLLER type) + internal void SetExController(EXCONTROLLER type) { excontroller_select = (int)type; diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PPU.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PPU.cs index fff8fe7..ffbeb54 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PPU.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/PPU.cs @@ -1,12 +1,4 @@ -using Codice.CM.Client.Differences; -using Microsoft.Win32; -using System; -using System.IO; -using Unity.VisualScripting.Antlr3.Runtime.Tree; -using UnityEngine; -using static VirtualNes.Core.PPU; - -namespace VirtualNes.Core +namespace VirtualNes.Core { public class PPU { @@ -195,7 +187,7 @@ namespace VirtualNes.Core } addr &= 0xEFFF; } - MMU.PPU7_Temp = MMU.PPU_MEM_BANK[addr >> 10].Span[addr & 0x03FF]; + MMU.PPU7_Temp = MMU.PPU_MEM_BANK[addr >> 10][addr & 0x03FF]; break; } @@ -331,7 +323,7 @@ namespace VirtualNes.Core } if (MMU.PPU_MEM_TYPE[vaddr >> 10] != MMU.BANKTYPE_VROM) { - MMU.PPU_MEM_BANK[vaddr >> 10].Span[vaddr & 0x03FF] = data; + MMU.PPU_MEM_BANK[vaddr >> 10][vaddr & 0x03FF] = data; } break; } @@ -473,7 +465,7 @@ namespace VirtualNes.Core int attradr = 0x23C0 + (MMU.loopy_v & 0x0C00) + ((MMU.loopy_v & 0x0380) >> 4); int ntbl_x = ntbladr & 0x001F; int attrsft = (ntbladr & 0x0040) >> 4; - var pNTBL = MMU.PPU_MEM_BANK[ntbladr >> 10].Span; + var pNTBL = MMU.PPU_MEM_BANK[ntbladr >> 10]; int tileadr; int cache_tile = unchecked((int)(0xFFFF0000)); @@ -486,7 +478,6 @@ namespace VirtualNes.Core for (int i = 0; i < 33; i++) { - tileadr = tileofs + pNTBL[ntbladr & 0x03FF] * 0x10 + loopy_y; attr = (byte)(((pNTBL[attradr + (ntbl_x >> 2)] >> ((ntbl_x & 2) + attrsft)) & 3) << 2); @@ -508,8 +499,8 @@ namespace VirtualNes.Core { cache_tile = tileadr; cache_attr = attr; - chr_l = MMU.PPU_MEM_BANK[tileadr >> 10].Span[tileadr & 0x03FF]; - chr_h = MMU.PPU_MEM_BANK[tileadr >> 10].Span[(tileadr & 0x03FF) + 8]; + chr_l = MMU.PPU_MEM_BANK[tileadr >> 10][tileadr & 0x03FF]; + chr_h = MMU.PPU_MEM_BANK[tileadr >> 10][(tileadr & 0x03FF) + 8]; BGwrite[pBGw] = (byte)(chr_h | chr_l); int pBGPAL = attr; @@ -540,7 +531,7 @@ namespace VirtualNes.Core ntbl_x = 0; ntbladr ^= 0x41F; attradr = 0x03C0 + ((ntbladr & 0x0380) >> 4); - pNTBL = MMU.PPU_MEM_BANK[ntbladr >> 10].Span; + pNTBL = MMU.PPU_MEM_BANK[ntbladr >> 10]; } else { @@ -632,7 +623,7 @@ namespace VirtualNes.Core int attradr = 0x03C0 + ((MMU.loopy_v & 0x0380) >> 4); int ntbl_x = ntbladr & 0x001F; int attrsft = (ntbladr & 0x0040) >> 4; - var pNTBL = MMU.PPU_MEM_BANK[ntbladr >> 10].Span; + var pNTBL = MMU.PPU_MEM_BANK[ntbladr >> 10]; int tileadr = 0; int cache_tile = unchecked((int)(0xFFFF0000)); @@ -656,8 +647,8 @@ namespace VirtualNes.Core cache_tile = tileadr; cache_attr = attr; - chr_l = MMU.PPU_MEM_BANK[tileadr >> 10].Span[tileadr & 0x03FF]; - chr_h = MMU.PPU_MEM_BANK[tileadr >> 10].Span[(tileadr & 0x03FF) + 8]; + chr_l = MMU.PPU_MEM_BANK[tileadr >> 10][tileadr & 0x03FF]; + chr_h = MMU.PPU_MEM_BANK[tileadr >> 10][(tileadr & 0x03FF) + 8]; lpScreen[pBGw] = (byte)(chr_l | chr_h); int pBGPAL = attr; @@ -702,7 +693,7 @@ namespace VirtualNes.Core ntbl_x = 0; ntbladr ^= 0x41F; attradr = 0x03C0 + ((ntbladr & 0x0380) >> 4); - pNTBL = MMU.PPU_MEM_BANK[ntbladr >> 10].Span; + pNTBL = MMU.PPU_MEM_BANK[ntbladr >> 10]; } else { @@ -732,16 +723,16 @@ namespace VirtualNes.Core } ntbladr = 0x2000 + (MMU.loopy_v & 0x0FFF); - tileadr = ((MMU.PPUREG[0] & PPU_BGTBL_BIT) << 8) + MMU.PPU_MEM_BANK[ntbladr >> 10].Span[ntbladr & 0x03FF] * 0x10 + ((MMU.loopy_v & 0x7000) >> 12); - attr = (byte)(((MMU.PPU_MEM_BANK[ntbladr >> 10].Span[0x03C0 + ((ntbladr & 0x0380) >> 4) + ((ntbladr & 0x001C) >> 2)] >> (((ntbladr & 0x40) >> 4) + (ntbladr & 0x02))) & 3) << 2); + tileadr = ((MMU.PPUREG[0] & PPU_BGTBL_BIT) << 8) + MMU.PPU_MEM_BANK[ntbladr >> 10][ntbladr & 0x03FF] * 0x10 + ((MMU.loopy_v & 0x7000) >> 12); + attr = (byte)(((MMU.PPU_MEM_BANK[ntbladr >> 10][0x03C0 + ((ntbladr & 0x0380) >> 4) + ((ntbladr & 0x001C) >> 2)] >> (((ntbladr & 0x40) >> 4) + (ntbladr & 0x02))) & 3) << 2); if (cache_tile != tileadr || cache_attr != attr) { cache_tile = tileadr; cache_attr = attr; - chr_l = MMU.PPU_MEM_BANK[tileadr >> 10].Span[tileadr & 0x03FF]; - chr_h = MMU.PPU_MEM_BANK[tileadr >> 10].Span[(tileadr & 0x03FF) + 8]; + chr_l = MMU.PPU_MEM_BANK[tileadr >> 10][tileadr & 0x03FF]; + chr_h = MMU.PPU_MEM_BANK[tileadr >> 10][(tileadr & 0x03FF) + 8]; BGwrite[pBGw] = (byte)(chr_l | chr_h); int pBGPAL = attr; @@ -937,8 +928,8 @@ namespace VirtualNes.Core spraddr += ((~sp_y & 8) << 1) + (7 - (sp_y & 7)); } // Character pattern - chr_l = MMU.PPU_MEM_BANK[spraddr >> 10].Span[spraddr & 0x3FF]; - chr_h = MMU.PPU_MEM_BANK[spraddr >> 10].Span[(spraddr & 0x3FF) + 8]; + 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) @@ -1117,12 +1108,18 @@ namespace VirtualNes.Core return lpScreen; } + public byte[] GetLineColorMode() + { + return lpColormode; + } + internal void SetScreenPtr(byte[] screenBuffer, byte[] colormode) { lpScreen = screenBuffer; lpColormode = colormode; } + internal bool IsDispON() { return (MMU.PPUREG[1] & (PPU_BGDISP_BIT | PPU_SPDISP_BIT)) != 0; diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ROM.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ROM.cs index b7aacbd..d6cdd26 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ROM.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/ROM.cs @@ -347,12 +347,12 @@ namespace VirtualNes.Core return diskno; } - internal ulong GetGameID() + internal uint GetGameID() { return fdsgameID; } - internal ulong GetMakerID() + internal uint GetMakerID() { return fdsmakerID; } diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/EmulatorConfig.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/EmulatorConfig.cs index 961e389..77f78a8 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/EmulatorConfig.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Supporter/EmulatorConfig/EmulatorConfig.cs @@ -17,4 +17,29 @@ public CfgExtraSound extsound { get; private set; } = new CfgExtraSound(); public CfgNetPlay netplay { get; private set; } = new CfgNetPlay(); } + + public static class GameOption + { + // Default保存 + public static int defRenderMethod; + public static int defIRQtype; + public static bool defFrameIRQ; + public static bool defVideoMode; + + // データ + public static int nRenderMethod; + public static int nIRQtype; + public static bool bFrameIRQ; + public static bool bVideoMode; + + public static void Load(uint crc) + { + + } + + public static void Load(uint gid, uint mid) + { + + } + } } diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/VsUnisystem.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/VsUnisystem.cs new file mode 100644 index 0000000..18f995c --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/VsUnisystem.cs @@ -0,0 +1,49 @@ +namespace VirtualNes.Core +{ + public class VSDIPSWITCH + { + public string name; + public ushort value; + } + + + public static class VsUnisystem + { + public static VSDIPSWITCH[] vsdip_default = new VSDIPSWITCH[] + { + new VSDIPSWITCH{name="Unknown", value= 0x0100}, + new VSDIPSWITCH{name="Off", value= 0x00}, + new VSDIPSWITCH{name="On", value= 0x01}, + new VSDIPSWITCH{name=null, value= 0xFF}, + new VSDIPSWITCH{name="Unknown", value= 0x0200}, + new VSDIPSWITCH{name="Off", value= 0x00}, + new VSDIPSWITCH{name="On", value= 0x02}, + new VSDIPSWITCH{name=null, value= 0xFF}, + new VSDIPSWITCH{name="Unknown", value= 0x0400}, + new VSDIPSWITCH{name="Off", value= 0x00}, + new VSDIPSWITCH{name="On", value= 0x04}, + new VSDIPSWITCH{name=null, value= 0xFF}, + new VSDIPSWITCH{name="Unknown", value= 0x0800}, + new VSDIPSWITCH{name="Off", value= 0x00}, + new VSDIPSWITCH{name="On", value= 0x08}, + new VSDIPSWITCH{name=null, value= 0xFF}, + new VSDIPSWITCH{name="Unknown", value= 0x1000}, + new VSDIPSWITCH{name="Off", value= 0x00}, + new VSDIPSWITCH{name="On", value= 0x10}, + new VSDIPSWITCH{name=null, value= 0xFF}, + new VSDIPSWITCH{name="Unknown", value= 0x2000}, + new VSDIPSWITCH{name="Off", value= 0x00}, + new VSDIPSWITCH{name="On", value= 0x20}, + new VSDIPSWITCH{name=null, value= 0xFF}, + new VSDIPSWITCH{name="Unknown", value= 0x4000}, + new VSDIPSWITCH{name="Off", value= 0x00}, + new VSDIPSWITCH{name="On", value= 0x40}, + new VSDIPSWITCH{name=null, value= 0xFF}, + new VSDIPSWITCH{name="Unknown", value= 0x8000}, + new VSDIPSWITCH{name="Off", value= 0x00}, + new VSDIPSWITCH{name="On", value= 0x80}, + new VSDIPSWITCH{name=null, value= 0xFF}, + new VSDIPSWITCH{name=null, value= 0 }, + }; + } +} diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/VsUnisystem.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/VsUnisystem.cs.meta new file mode 100644 index 0000000..3d06276 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/VsUnisystem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: db82d3b2d60f2c14fa3c5582acc439c6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/virtuanessrc097-master/Render32bpp.h b/virtuanessrc097-master/Render32bpp.h index 118bad7..9ecb5b6 100644 Binary files a/virtuanessrc097-master/Render32bpp.h and b/virtuanessrc097-master/Render32bpp.h differ