Merge pull request 'master' (#71) from Alienjack/AxibugEmuOnline:master into master

Reviewed-on: #71
This commit is contained in:
sin365 2024-12-25 22:33:20 +08:00
commit 7f2792bbdc
21 changed files with 165 additions and 189 deletions

View File

@ -1,4 +1,4 @@
using UnityEngine;
using UnityEngine;
namespace AxibugEmuOnline.Client
{
@ -14,7 +14,9 @@ namespace AxibugEmuOnline.Client
void Resume();
void SetupScheme();
void StartGame(RomFile romFile);
void DoReset();
void DoReset();
IControllerSetuper GetControllerSetuper();
EnumPlatform Platform { get; }
uint Frame { get; }
}

View File

@ -13,7 +13,7 @@ namespace AxibugEmuOnline.Client.Manager
/// </summary>
private IEmuCore m_emuCore;
private VirtualNes.Core.IControllerSetuper m_controllerSetuper;
private IControllerSetuper m_controllerSetuper;
/// <summary>
/// unity的c#实现有bug,以接口类型保存的monobehaviour引用,!=和==运算符没有调用到monobehaviour重写过的运算符
@ -63,7 +63,7 @@ namespace AxibugEmuOnline.Client.Manager
m_emuCore.SetupScheme();
m_controllerSetuper = Supporter.GetControllerSetuper();
m_controllerSetuper = m_emuCore.GetControllerSetuper();
//自动分配0号手柄到0号手柄位
m_controllerSetuper.SetConnect(con0ToSlot: 0);

View File

@ -0,0 +1,39 @@
/// <summary>
/// 负责管理本地控制器与具体游戏之间的槽位分配
/// </summary>
public interface IControllerSetuper
{
/// <summary>
/// 设置本地手柄与游戏手柄槽位的映射,这个方法是一个全量更新手柄插入设置的方法
/// </summary>
void SetConnect(
uint? con0ToSlot = null,
uint? con1ToSlot = null,
uint? con2ToSlot = null,
uint? con3ToSlot = null);
/// <summary>
/// 指定手柄插槽位,获取当前槽位连接的本地手柄序号
/// </summary>
/// <param name="slotIndex"></param>
/// <returns></returns>
int? GetSlotConnectingControllerIndex(int slotIndex);
IController GetSlotConnectingController(int slotIndex);
/// <summary>
/// 获得一个空的槽位
/// </summary>
/// <returns></returns>
uint? GetFreeSlotIndex();
/// <summary>
/// 增量式的修改一个手柄和一个槽位的连接关系
/// </summary>
/// <param name="conIndex"></param>
/// <param name="slotIndex"></param>
void LetControllerConnect(int conIndex, uint slotIndex);
}
public interface IController
{
bool AnyButtonDown();
}

View File

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f567cb126b157854e9f9b2c71f8cda8e

View File

@ -1,4 +1,4 @@
using AxibugEmuOnline.Client.ClientCore;
using AxibugEmuOnline.Client.ClientCore;
using AxiReplay;
using System;
using System.IO;
@ -10,6 +10,12 @@ namespace AxibugEmuOnline.Client
{
public class CoreSupporter : ISupporterImpl
{
private NesControllerMapper m_controllerMapper;
public CoreSupporter(NesControllerMapper conMapper)
{
m_controllerMapper = conMapper;
}
public Stream OpenRom(string fname)
{
try
@ -57,7 +63,6 @@ namespace AxibugEmuOnline.Client
}
public EmulatorConfig Config { get; private set; } = new EmulatorConfig();
public NesControllerMapper ControllerMapper { get; private set; } = new NesControllerMapper();
public void PrepareDirectory(string directPath)
{
Directory.CreateDirectory($"{App.PersistentDataPath}/{directPath}");
@ -116,7 +121,7 @@ namespace AxibugEmuOnline.Client
}
else m_sampledState = default(ControllerState);
var localState = ControllerMapper.CreateState();
var localState = m_controllerMapper.CreateState();
var rawData = ToNet(localState);
if (LastTestInput != rawData)
{
@ -127,15 +132,10 @@ namespace AxibugEmuOnline.Client
}
else
{
m_sampledState = ControllerMapper.CreateState();
m_sampledState = m_controllerMapper.CreateState();
}
}
public IControllerSetuper GetControllerSetuper()
{
return ControllerMapper;
}
public ControllerState FromNet(AxiReplay.ReplayStep step)
{
var temp = new ServerInputSnapShot();

View File

@ -46,7 +46,7 @@ namespace AxibugEmuOnline.Client
Controller3.ConnectSlot = con3ToSlot;
}
public int? GetSlotConnectingController(int slotIndex)
public int? GetSlotConnectingControllerIndex(int slotIndex)
{
if (Controller0.ConnectSlot.HasValue && Controller0.ConnectSlot.Value == slotIndex) return 0;
else if (Controller1.ConnectSlot.HasValue && Controller1.ConnectSlot.Value == slotIndex) return 1;
@ -55,6 +55,15 @@ namespace AxibugEmuOnline.Client
else return null;
}
public IController GetSlotConnectingController(int slotIndex)
{
if (Controller0.ConnectSlot.HasValue && Controller0.ConnectSlot.Value == slotIndex) return Controller0;
else if (Controller1.ConnectSlot.HasValue && Controller1.ConnectSlot.Value == slotIndex) return Controller1;
else if (Controller2.ConnectSlot.HasValue && Controller2.ConnectSlot.Value == slotIndex) return Controller2;
else if (Controller3.ConnectSlot.HasValue && Controller3.ConnectSlot.Value == slotIndex) return Controller3;
else return null;
}
static HashSet<uint> s_temp = new HashSet<uint>(4);
public uint? GetFreeSlotIndex()
{
@ -94,7 +103,7 @@ namespace AxibugEmuOnline.Client
/// <summary>
/// Nes控制器
/// </summary>
public class Controller
public class Controller : IController
{
/// <summary>
/// 控制器编号

View File

@ -21,7 +21,13 @@ namespace AxibugEmuOnline.Client
public NES NesCore { get; private set; }
/// <summary> 是否暂停 </summary>
public bool IsPause { get; private set; }
public bool IsPause { get; private set; }
public NesControllerMapper ControllerMapper { get; private set; }
private void Awake()
{
ControllerMapper = new NesControllerMapper();
}
private void Start()
{
@ -48,12 +54,11 @@ namespace AxibugEmuOnline.Client
VideoProvider.SetDrawData(screenBuffer);
}
VideoProvider.ApplyFilterEffect();
}
public EnumPlatform Platform => EnumPlatform.NES;
private CoreSupporter m_coreSupporter;
/// <summary>
/// 指定ROM开始游戏
/// </summary>
@ -61,7 +66,8 @@ namespace AxibugEmuOnline.Client
{
StopGame();
Supporter.Setup(new CoreSupporter());
m_coreSupporter = new CoreSupporter(ControllerMapper);
Supporter.Setup(m_coreSupporter);
Debuger.Setup(new CoreDebuger());
App.nesRomLib.AddRomFile(rom);
@ -159,8 +165,8 @@ namespace AxibugEmuOnline.Client
//推进帧
private bool PushEmulatorFrame()
{
Supporter.SampleInput(NesCore.FrameCount);
var controlState = Supporter.GetControllerState();
m_coreSupporter.SampleInput(NesCore.FrameCount);
var controlState = m_coreSupporter.GetControllerState();
//如果未收到Input数据,核心帧不推进
if (!controlState.valid) return false;
@ -205,8 +211,13 @@ namespace AxibugEmuOnline.Client
EditorUtility.SetDirty(db);
AssetDatabase.SaveAssets();
}
}
public IControllerSetuper GetControllerSetuper()
{
return ControllerMapper;
}
#endif
}
}

View File

@ -27,7 +27,7 @@ namespace AxibugEmuOnline.Client
}
// スキャンラインカラー
private static int m_nScanlineColor => Supporter.Config.graphics.nScanlineColor;
private static int m_nScanlineColor => 75; //patternViewer调试器用的,参照EmulatorConfig.graphics.nScanlineColor的值
public static float[][] PalConvTbl = new float[8][]
{

View File

@ -117,10 +117,10 @@ namespace AxibugEmuOnline.Client
m_delayCreateRoom = false;
//延迟创建房间成功后,同步本地手柄连接状态
Dictionary<uint, uint> temp = new Dictionary<uint, uint>();
var setuper = Supporter.GetControllerSetuper();
var setuper = App.emu.Core.GetControllerSetuper();
for (int i = 0; i < 4; i++)
{
var joyIndex = setuper.GetSlotConnectingController(i);
var joyIndex = setuper.GetSlotConnectingControllerIndex(i);
if (joyIndex != null) temp[(uint)i] = (uint)joyIndex.Value;
}
App.roomMgr.SendChangePlaySlotIdxWithJoyIdx(temp);

View File

@ -1,6 +1,7 @@
using AxibugEmuOnline.Client;
using AxibugEmuOnline.Client.ClientCore;
using AxibugEmuOnline.Client.Event;
using DG.Tweening;
using System;
using UnityEngine;
using UnityEngine.UI;
@ -18,9 +19,7 @@ public class ControllerInfo : MonoBehaviour
Image m_indexIcon;
[SerializeField]
Text m_playerName;
int m_localJoyIndex;
bool m_isLocal;
private bool m_islocal;
public int SlotIndex
{
@ -60,6 +59,18 @@ public class ControllerInfo : MonoBehaviour
Eventer.Instance.UnregisterEvent(EEvent.OnControllerConnectChanged, OnControlConnectChanged);
}
private void Update()
{
if (m_islocal)
{
var controller = App.emu.Core.GetControllerSetuper().GetSlotConnectingController(m_slotIndex);
if (controller == null) return;
if (!controller.AnyButtonDown()) return;
m_indexIcon.rectTransform.DOShakePosition(0.1f);
}
}
private void OnMineRoomCreated() => UpdateConnectInfo();
private void OnJoinRoom() => UpdateConnectInfo();
private void OnLeaveRoom() => UpdateConnectInfo();
@ -79,14 +90,15 @@ public class ControllerInfo : MonoBehaviour
}
else
{
var connecter = Supporter.GetControllerSetuper();
if (connecter == null)
if (App.emu.Core.IsNull())
{
SetDisconnect();
return;
}
var localControlIndex = connecter.GetSlotConnectingController(SlotIndex);
}
var connecter = App.emu.Core.GetControllerSetuper();
var localControlIndex = connecter.GetSlotConnectingControllerIndex(SlotIndex);
if (localControlIndex == null)
SetDisconnect();
else
@ -101,8 +113,7 @@ public class ControllerInfo : MonoBehaviour
private void UpdateStateView(bool isLocal, string playerName, int slotIndex)
{
m_localJoyIndex = slotIndex;
m_isLocal = isLocal;
m_islocal = isLocal;
m_connectInfoNode.SetActiveEx(true);
m_playerName.text = playerName;
@ -110,11 +121,9 @@ public class ControllerInfo : MonoBehaviour
private void SetDisconnect()
{
m_localJoyIndex = -1;
m_isLocal = false;
m_connectInfoNode.SetActiveEx(false);
m_playerName.text = null;
m_islocal = false;
}
private void UpdateIndexIcon()

View File

@ -1,4 +1,5 @@
using AxibugEmuOnline.Client.ClientCore;
using AxibugEmuOnline.Client;
using AxibugEmuOnline.Client.ClientCore;
using AxibugEmuOnline.Client.Event;
using AxibugEmuOnline.Client.Manager;
using System;
@ -31,7 +32,8 @@ public class ControllerInfoPanel : MonoBehaviour
}
else //不在房间中,直接设置
{
var setuper = Supporter.GetControllerSetuper();
if (App.emu.Core.IsNull()) return;
var setuper = App.emu.Core.GetControllerSetuper();
if (setuper == null) return;
var freeSlotIndex = setuper.GetFreeSlotIndex();

View File

@ -73,7 +73,7 @@ namespace VirtualNes.Core
public void Process(ISoundDataBuffer lpBuffer, uint dwSize)
{
int nBits = Supporter.Config.sound.nBits;
int nBits = Supporter.S.Config.sound.nBits;
uint dwLength = (uint)(dwSize / (nBits / 8));
int output;
QUEUEDATA q = new QUEUEDATA();
@ -82,11 +82,11 @@ namespace VirtualNes.Core
var pSoundBuf = m_SoundBuffer;
int nCcount = 0;
int nFilterType = Supporter.Config.sound.nFilterType;
int nFilterType = Supporter.S.Config.sound.nFilterType;
if (!Supporter.Config.sound.bEnable)
if (!Supporter.S.Config.sound.bEnable)
{
byte empty = (byte)(Supporter.Config.sound.nRate == 8 ? 128 : 0);
byte empty = (byte)(Supporter.S.Config.sound.nRate == 8 ? 128 : 0);
for (int i = 0; i < dwSize; i++)
lpBuffer.WriteByte(empty);
return;
@ -108,7 +108,7 @@ namespace VirtualNes.Core
MemoryUtility.ZEROMEMORY(vol, vol.Length);
var bMute = m_bMute;
var nVolume = Supporter.Config.sound.nVolume;
var nVolume = Supporter.S.Config.sound.nVolume;
int nMasterVolume = bMute[0] ? nVolume[0] : 0;
@ -151,7 +151,7 @@ namespace VirtualNes.Core
vol[23] = (int)(bMute[8] ? (FME7_VOL * nVolume[11] * nMasterVolume) / (100 * 100) : 0);
// double cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
double cycle_rate = (nes.nescfg.FrameCycles * 60.0 / 12.0) / Supporter.Config.sound.nRate;
double cycle_rate = (nes.nescfg.FrameCycles * 60.0 / 12.0) / Supporter.S.Config.sound.nRate;
// CPUサイクル数がループしてしまった時の対策処理
if (elapsed_time > nes.cpu.GetTotalCycles())
@ -253,7 +253,7 @@ namespace VirtualNes.Core
// DC成分のカット(HPF TEST)
{
// static double cutoff = (2.0*3.141592653579*40.0/44100.0);
double cutoff = cutofftemp / Supporter.Config.sound.nRate;
double cutoff = cutofftemp / Supporter.S.Config.sound.nRate;
double @in, @out;
@in = output;
@ -436,7 +436,7 @@ namespace VirtualNes.Core
public void SoundSetup()
{
float fClock = nes.nescfg.CpuClock;
int nRate = Supporter.Config.sound.nRate;
int nRate = Supporter.S.Config.sound.nRate;
@internal.Setup(fClock, nRate);
vrc6.Setup(fClock, nRate);
@ -460,7 +460,7 @@ namespace VirtualNes.Core
elapsed_time = 0;
float fClock = nes.nescfg.CpuClock;
int nRate = Supporter.Config.sound.nRate;
int nRate = Supporter.S.Config.sound.nRate;
@internal.Reset(fClock, nRate);
vrc6.Reset(fClock, nRate);

View File

@ -1,4 +1,4 @@

using System;
namespace VirtualNes.Core
@ -184,15 +184,15 @@ namespace VirtualNes.Core
Setup(fClock, nRate);
// $4011反場ヽ趙仄卅中
// $4011は初期化しない
ushort addr;
for (addr = 0x4000; addr <= 0x4010; addr++)
{
Write(addr, 0x00);
SyncWrite(addr, 0x00);
}
// Write( 0x4001, 0x08 ); // Reset媆反inc乒奈玉卞卅月?
// Write( 0x4005, 0x08 ); // Reset媆反inc乒奈玉卞卅月?
// Write( 0x4001, 0x08 ); // Reset時はincモードになる?
// Write( 0x4005, 0x08 ); // Reset時はincモードになる?
Write(0x4012, 0x00);
Write(0x4013, 0x00);
Write(0x4015, 0x00);
@ -200,7 +200,7 @@ namespace VirtualNes.Core
SyncWrite(0x4013, 0x00);
SyncWrite(0x4015, 0x00);
// $4017反𤩸五煋心匹場ヽ趙仄卅中(場ヽ乒奈玉互0匹丐月及毛ヽ渾仄凶末白玄互丐月鮋)
// $4017は書き込みで初期化しない(初期モードが0であるのを期待したソフトがある為)
FrameIRQ = 0xC0;
FrameCycle = 0;
FrameIRQoccur = 0;
@ -301,7 +301,7 @@ namespace VirtualNes.Core
case 0x4017:
break;
// VirtuaNES嘐衄禾奈玄
// VirtuaNES固有ポート
case 0x4018:
UpdateRectangle(ch0, data);
UpdateRectangle(ch1, data);
@ -635,7 +635,7 @@ namespace VirtualNes.Core
}
}
// 奶件民平堪中皿民用奶朮市永玄(TEST)
// インチキ臭いプチノイズカット(TEST)
ch4.dpcm_output_real = ((ch4.reg[1] & 0x01) + ch4.dpcm_value * 2) - 0x40;
if (Math.Abs(ch4.dpcm_output_real - ch4.dpcm_output_fake) <= 8)
{
@ -712,7 +712,7 @@ namespace VirtualNes.Core
private int RenderTriangle()
{
int vol;
if (Supporter.Config.sound.bDisableVolumeEffect)
if (Supporter.S.Config.sound.bDisableVolumeEffect)
{
vol = 256;
}
@ -731,7 +731,7 @@ namespace VirtualNes.Core
return ch2.nowvolume * vol / 256;
}
if (!(Supporter.Config.sound.bChangeTone && ChannelTone[2, 0] != 0))
if (!(Supporter.S.Config.sound.bChangeTone && ChannelTone[2, 0] != 0))
{
ch2.phaseacc -= cycle_rate;
if (ch2.phaseacc >= 0)
@ -756,7 +756,7 @@ namespace VirtualNes.Core
return ch2.nowvolume * vol / 256;
}
// 樓笭ⅸ歙
// 加重平均
int num_times, total;
num_times = total = 0;
while (ch2.phaseacc < 0)
@ -799,7 +799,7 @@ namespace VirtualNes.Core
return ch2.nowvolume * vol / 256;
}
// 樓笭ⅸ歙
// 加重平均
int num_times, total;
num_times = total = 0;
while (ch2.phaseacc < 0)
@ -832,9 +832,9 @@ namespace VirtualNes.Core
}
int volume = ch.nowvolume;
if (!(Supporter.Config.sound.bChangeTone && (ChannelTone[(ch.complement == 0) ? 0 : 1, ch.reg[0] >> 6]) != 0))
if (!(Supporter.S.Config.sound.bChangeTone && (ChannelTone[(ch.complement == 0) ? 0 : 1, ch.reg[0] >> 6]) != 0))
{
// 娗嶲<EFBFBD>
// 補間処理
double total;
double sample_weight = ch.phaseacc;
if (sample_weight > cycle_rate)
@ -864,7 +864,7 @@ namespace VirtualNes.Core
int x = ChannelTone[(ch.complement == 0) ? 0 : 1, ch.reg[0] >> 6] - 1;
int pTone = 0;
// 載陔剠仄
// 更新無し
ch.phaseacc -= cycle_rate * 2;
if (ch.phaseacc >= 0)
{
@ -872,7 +872,7 @@ namespace VirtualNes.Core
return temp * volume / ((1 << RECTANGLE_VOL_SHIFT) / 2);
}
// 1旦氾永皿分仃載陔
// 1ステップだけ更新
int freq = INT2FIX(ch.freq + 1);
if (freq > cycle_rate * 2)
{
@ -882,7 +882,7 @@ namespace VirtualNes.Core
return temp * volume / ((1 << RECTANGLE_VOL_SHIFT) / 2);
}
// 樓笭ⅸ歙
// 加重平均
int num_times, total;
num_times = total = 0;
while (ch.phaseacc < 0)
@ -1015,7 +1015,7 @@ namespace VirtualNes.Core
SyncWrite4017(data);
break;
// VirtuaNES娚葲<EFBFBD><EFBFBD><EFBFBD>
// VirtuaNES屌桳億乕僩
case 0x4018:
SyncUpdateRectangle(ch0, data);
SyncUpdateRectangle(ch1, data);

View File

@ -1110,7 +1110,7 @@ namespace VirtualNes.Core
case 0xD2: /* JAM */
case 0xF2: /* JAM */
default:
if (!Supporter.Config.emulator.bIllegalOp)
if (!Supporter.S.Config.emulator.bIllegalOp)
{
throw new Exception("IllegalOp");
}

View File

@ -40,7 +40,7 @@ namespace VirtualNes.Core
Debuger.Log($"SOUND CODE:{addr & 0x1F:X2}");
// OSDにするべきか…
if (Supporter.Config.sound.bExtraSoundEnable)
if (Supporter.S.Config.sound.bExtraSoundEnable)
{
//TODO : 似乎VirtuaNES有直接播放某个音频文件的功能
//DirectSound.EsfAllStop();

View File

@ -43,7 +43,7 @@ namespace VirtualNes.Core
}
// OSDにするべきか…
if (Supporter.Config.sound.bExtraSoundEnable)
if (Supporter.S.Config.sound.bExtraSoundEnable)
{
//TODO : 似乎VirtuaNES有直接播放某个音频文件的功能
//DirectSound.EsfAllStop();

View File

@ -57,7 +57,7 @@ namespace VirtualNes.Core
9,10, 8,11,13,12,14,15 };
// OSDにするべきか…
if (Supporter.Config.sound.bExtraSoundEnable)
if (Supporter.S.Config.sound.bExtraSoundEnable)
{
//TODO : 似乎VirtuaNES有直接播放某个音频文件的功能
Debuger.Log($"CODE {data:X2}");

View File

@ -326,7 +326,7 @@ namespace VirtualNes.Core
if (pad.GetExController() != (int)EXCONTROLLER.EXCONTROLLER_TURBOFILE)
return;
var fp = Supporter.OpenFile(Supporter.Config.path.szSavePath, "TurboFile.vtf");
var fp = Supporter.S.OpenFile(Supporter.S.Config.path.szSavePath, "TurboFile.vtf");
try
{
if (fp == null)
@ -367,10 +367,10 @@ namespace VirtualNes.Core
if (!rom.IsSAVERAM())
return;
var saveFileDir = Supporter.Config.path.szSavePath;
var saveFileDir = Supporter.S.Config.path.szSavePath;
var saveFileName = $"{rom.GetRomName()}.sav";
var fp = Supporter.OpenFile(saveFileDir, saveFileName);
var fp = Supporter.S.OpenFile(saveFileDir, saveFileName);
try
{
@ -502,13 +502,13 @@ namespace VirtualNes.Core
EmulationCPU(nescfg.ScanlineCycles);
if (bDraw)
{
ppu.Scanline(scanline, Supporter.Config.graphics.bAllSprite, Supporter.Config.graphics.bLeftClip);
ppu.Scanline(scanline, Supporter.S.Config.graphics.bAllSprite, Supporter.S.Config.graphics.bLeftClip);
}
else
{
if (pad.IsZapperMode() && scanline == ZapperY)
{
ppu.Scanline(scanline, Supporter.Config.graphics.bAllSprite, Supporter.Config.graphics.bLeftClip);
ppu.Scanline(scanline, Supporter.S.Config.graphics.bAllSprite, Supporter.S.Config.graphics.bLeftClip);
}
else
{
@ -518,7 +518,7 @@ namespace VirtualNes.Core
}
else
{
ppu.Scanline(scanline, Supporter.Config.graphics.bAllSprite, Supporter.Config.graphics.bLeftClip);
ppu.Scanline(scanline, Supporter.S.Config.graphics.bAllSprite, Supporter.S.Config.graphics.bLeftClip);
}
}
}
@ -535,13 +535,13 @@ namespace VirtualNes.Core
EmulationCPU(nescfg.HDrawCycles);
if (bDraw)
{
ppu.Scanline(scanline, Supporter.Config.graphics.bAllSprite, Supporter.Config.graphics.bLeftClip);
ppu.Scanline(scanline, Supporter.S.Config.graphics.bAllSprite, Supporter.S.Config.graphics.bLeftClip);
}
else
{
if (pad.IsZapperMode() && scanline == ZapperY)
{
ppu.Scanline(scanline, Supporter.Config.graphics.bAllSprite, Supporter.Config.graphics.bLeftClip);
ppu.Scanline(scanline, Supporter.S.Config.graphics.bAllSprite, Supporter.S.Config.graphics.bLeftClip);
}
else
{
@ -551,7 +551,7 @@ namespace VirtualNes.Core
}
else
{
ppu.Scanline(scanline, Supporter.Config.graphics.bAllSprite, Supporter.Config.graphics.bLeftClip);
ppu.Scanline(scanline, Supporter.S.Config.graphics.bAllSprite, Supporter.S.Config.graphics.bLeftClip);
}
}
}
@ -658,7 +658,7 @@ namespace VirtualNes.Core
// 僗僋儕乕儞昤夋(Scanline 1乣239)
if (bDraw)
{
ppu.Scanline(scanline, Supporter.Config.graphics.bAllSprite, Supporter.Config.graphics.bLeftClip);
ppu.Scanline(scanline, Supporter.S.Config.graphics.bAllSprite, Supporter.S.Config.graphics.bLeftClip);
ppu.ScanlineNext();
EmulationCPU(FETCH_CYCLES * 10);
mapper.HSync(scanline);
@ -670,7 +670,7 @@ namespace VirtualNes.Core
{
if (pad.IsZapperMode() && scanline == ZapperY)
{
ppu.Scanline(scanline, Supporter.Config.graphics.bAllSprite, Supporter.Config.graphics.bLeftClip);
ppu.Scanline(scanline, Supporter.S.Config.graphics.bAllSprite, Supporter.S.Config.graphics.bLeftClip);
ppu.ScanlineNext();
EmulationCPU(FETCH_CYCLES * 10);
mapper.HSync(scanline);
@ -694,7 +694,7 @@ namespace VirtualNes.Core
}
else
{
ppu.Scanline(scanline, Supporter.Config.graphics.bAllSprite, Supporter.Config.graphics.bLeftClip);
ppu.Scanline(scanline, Supporter.S.Config.graphics.bAllSprite, Supporter.S.Config.graphics.bLeftClip);
ppu.ScanlineNext();
EmulationCPU(FETCH_CYCLES * 10);
mapper.HSync(scanline);
@ -1095,7 +1095,7 @@ namespace VirtualNes.Core
Debuger.Log($"Saving SAVERAM...[{romName}]");
Supporter.SaveSRAMToFile(MMU.WRAM, romName);
Supporter.S.SaveSRAMToFile(MMU.WRAM, romName);
}
}
@ -1143,7 +1143,7 @@ namespace VirtualNes.Core
}
}
Supporter.SaveDISKToFile(contents.ToArray(), rom.GetRomName());
Supporter.S.SaveDISKToFile(contents.ToArray(), rom.GetRomName());
}
catch (Exception ex)
{
@ -1168,7 +1168,7 @@ namespace VirtualNes.Core
{
Debuger.Log("Saving TURBOFILE...");
Supporter.SaveFile(MMU.ERAM, Supporter.Config.path.szSavePath, "TurboFile.vtf");
Supporter.S.SaveFile(MMU.ERAM, Supporter.S.Config.path.szSavePath, "TurboFile.vtf");
}
}

View File

@ -181,7 +181,7 @@ namespace VirtualNes.Core
}
else
{
if (Supporter.Config.emulator.bFourPlayer)
if (Supporter.S.Config.emulator.bFourPlayer)
{
// NES type
pad1bit = padbitsync[0] | ((uint)padbitsync[2] << 8) | 0x00080000;

View File

@ -50,7 +50,7 @@ namespace VirtualNes.Core
try
{
fp = Supporter.OpenRom(fname);
fp = Supporter.S.OpenRom(fname);
if (fp == null)
{
throw new System.Exception($"Open Rom Failed:[{fname}]");
@ -167,7 +167,7 @@ namespace VirtualNes.Core
lpPRG[3] = 0x1A;
lpPRG[4] = (byte)diskno;
fp = Supporter.OpenFile_DISKSYS();
fp = Supporter.S.OpenFile_DISKSYS();
if (fp == null)
{
throw new Exception($"Not found DISKSYS.ROM for [{fname}]");
@ -217,7 +217,7 @@ namespace VirtualNes.Core
throw new Exception($"Unsupport format:[{fname}]");
}
Supporter.GetFilePathInfo(fname, out fullpath, out path);
Supporter.S.GetRomPathInfo(fname, out fullpath, out path);
name = Path.GetFileNameWithoutExtension(fullpath);
if (!bNSF)
{
@ -244,7 +244,7 @@ namespace VirtualNes.Core
FileNameCheck(fname);
if (Supporter.TryGetMapperNo(this, out int mapperNo))
if (Supporter.S.TryGetMapperNo(this, out int mapperNo))
{
Debuger.Log($"ROMDB Set Mapper #{mapper:000} to #{mapperNo:000}");
mapper = mapperNo;

View File

@ -5,73 +5,12 @@ namespace VirtualNes.Core
public static class Supporter
{
private static ISupporterImpl s_support;
internal static ISupporterImpl S => s_support;
public static void Setup(ISupporterImpl supporter)
{
s_support = supporter;
}
public static Stream OpenRom(string fname)
{
return s_support.OpenRom(fname);
}
public static void GetFilePathInfo(string fname, out string fullPath, out string directPath)
{
s_support.GetRomPathInfo(fname, out fullPath, out directPath);
}
public static Stream OpenFile_DISKSYS()
{
return s_support.OpenFile_DISKSYS();
}
public static void SaveSRAMToFile(byte[] sramContent, string romName)
{
s_support.SaveSRAMToFile(sramContent, romName);
}
public static void SaveDISKToFile(byte[] diskFileContent, string romName)
{
s_support.SaveDISKToFile(diskFileContent, romName);
}
public static void PrepareDirectory(string directPath)
{
s_support.PrepareDirectory(directPath);
}
public static void SaveFile(byte[] fileData, string directPath, string fileName)
{
s_support.SaveFile(fileData, directPath, fileName);
}
public static Stream OpenFile(string directPath, string fileName)
{
return s_support.OpenFile(directPath, fileName);
}
public static bool TryGetMapperNo(ROM rom, out int mapperNo)
{
return s_support.TryGetMapperNo(rom, out mapperNo);
}
public static ControllerState GetControllerState()
{
return s_support.GetControllerState();
}
public static void SampleInput(uint frameCount)
{
s_support.SampleInput(frameCount);
}
public static IControllerSetuper GetControllerSetuper()
{
return s_support?.GetControllerSetuper();
}
public static EmulatorConfig Config => s_support.Config;
}
public interface ISupporterImpl
@ -82,48 +21,11 @@ namespace VirtualNes.Core
void SaveSRAMToFile(byte[] sramContent, string romName);
void SaveDISKToFile(byte[] diskFileContent, string romName);
EmulatorConfig Config { get; }
void PrepareDirectory(string directPath);
void SaveFile(byte[] fileData, string directPath, string fileName);
Stream OpenFile(string directPath, string fileName);
bool TryGetMapperNo(ROM rom, out int mapperNo);
ControllerState GetControllerState();
void SampleInput(uint frameCount);
IControllerSetuper GetControllerSetuper();
}
/// <summary>
/// 负责管理本地控制器与具体游戏之间的槽位分配
/// </summary>
public interface IControllerSetuper
{
/// <summary>
/// 设置本地手柄与游戏手柄槽位的映射,这个方法是一个全量更新手柄插入设置的方法
/// </summary>
void SetConnect(
uint? con0ToSlot = null,
uint? con1ToSlot = null,
uint? con2ToSlot = null,
uint? con3ToSlot = null);
/// <summary>
/// 指定手柄插槽位,获取当前槽位连接的本地手柄序号
/// </summary>
/// <param name="slotIndex"></param>
/// <returns></returns>
int? GetSlotConnectingController(int slotIndex);
/// <summary>
/// 获得一个空的槽位
/// </summary>
/// <returns></returns>
uint? GetFreeSlotIndex();
/// <summary>
/// 增量式的修改一个手柄和一个槽位的连接关系
/// </summary>
/// <param name="conIndex"></param>
/// <param name="slotIndex"></param>
void LetControllerConnect(int conIndex, uint slotIndex);
}
}