dev_4VirtualNes #23
1
.gitignore
vendored
1
.gitignore
vendored
@ -13,3 +13,4 @@
|
||||
/AxibugEmuOnline.Client/ProjectSettings/ProjectVersion.txt
|
||||
/AxibugEmuOnline.Client/ProjectSettings/AutoStreamingSettings.asset
|
||||
/AxibugEmuOnline.Client/Logs
|
||||
/virtuanessrc097-master/save
|
||||
|
@ -123,49 +123,6 @@ NavMeshSettings:
|
||||
debug:
|
||||
m_Flags: 0
|
||||
m_NavMeshData: {fileID: 0}
|
||||
--- !u!1 &149545946
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 149545948}
|
||||
- component: {fileID: 149545947}
|
||||
m_Layer: 0
|
||||
m_Name: NesEmulator
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!114 &149545947
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 149545946}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 39557e19783acee499ace6c68549e8f8, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!4 &149545948
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 149545946}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 3
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &708549044
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -408,3 +365,60 @@ Transform:
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1001 &4232056520998800727
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications:
|
||||
- target: {fileID: 4232056521131536011, guid: f8bea3f8aa351bb46ada33b2274729ea, type: 3}
|
||||
propertyPath: m_RootOrder
|
||||
value: 3
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4232056521131536011, guid: f8bea3f8aa351bb46ada33b2274729ea, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4232056521131536011, guid: f8bea3f8aa351bb46ada33b2274729ea, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4232056521131536011, guid: f8bea3f8aa351bb46ada33b2274729ea, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4232056521131536011, guid: f8bea3f8aa351bb46ada33b2274729ea, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4232056521131536011, guid: f8bea3f8aa351bb46ada33b2274729ea, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4232056521131536011, guid: f8bea3f8aa351bb46ada33b2274729ea, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4232056521131536011, guid: f8bea3f8aa351bb46ada33b2274729ea, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4232056521131536011, guid: f8bea3f8aa351bb46ada33b2274729ea, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4232056521131536011, guid: f8bea3f8aa351bb46ada33b2274729ea, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4232056521131536011, guid: f8bea3f8aa351bb46ada33b2274729ea, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 4232056521131536013, guid: f8bea3f8aa351bb46ada33b2274729ea, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: NesEmulator
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: f8bea3f8aa351bb46ada33b2274729ea, type: 3}
|
||||
|
@ -7,6 +7,7 @@ namespace AxibugEmuOnline.Client
|
||||
{
|
||||
public class CoreDebuger : IDebugerImpl
|
||||
{
|
||||
|
||||
public void Log(string message)
|
||||
{
|
||||
Debug.Log(message);
|
||||
|
@ -64,5 +64,33 @@ namespace AxibugEmuOnline.Client
|
||||
}
|
||||
|
||||
public EmulatorConfig Config { get; private set; } = new EmulatorConfig();
|
||||
|
||||
public void PrepareDirectory(string directPath)
|
||||
{
|
||||
Directory.CreateDirectory($"{Application.persistentDataPath}/{directPath}");
|
||||
}
|
||||
|
||||
public void SaveFile(byte[] fileData, string directPath, string fileName)
|
||||
{
|
||||
PrepareDirectory(directPath);
|
||||
|
||||
var fileFullpath = $"{Application.persistentDataPath}/{directPath}/{fileName}";
|
||||
File.WriteAllBytes(fileFullpath, fileData);
|
||||
}
|
||||
|
||||
public Stream OpenFile(string directPath, string fileName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var data = File.ReadAllBytes($"{Application.persistentDataPath}/{directPath}/{fileName}");
|
||||
if (data == null) return null;
|
||||
return new MemoryStream(data);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using VirtualNes.Core;
|
||||
using VirtualNes.Core.Debug;
|
||||
@ -8,6 +10,8 @@ namespace AxibugEmuOnline.Client
|
||||
{
|
||||
private NES m_nesIns;
|
||||
|
||||
public VideoProvider VideoProvider;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
StartGame("Kirby.nes");
|
||||
@ -19,8 +23,16 @@ namespace AxibugEmuOnline.Client
|
||||
|
||||
Supporter.Setup(new CoreSupporter());
|
||||
Debuger.Setup(new CoreDebuger());
|
||||
m_nesIns = new NES(romName);
|
||||
m_nesIns.Command(NESCOMMAND.NESCMD_HWRESET);
|
||||
|
||||
try
|
||||
{
|
||||
m_nesIns = new NES(romName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
m_nesIns = null;
|
||||
Debug.LogError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void StopGame()
|
||||
@ -29,9 +41,18 @@ namespace AxibugEmuOnline.Client
|
||||
m_nesIns = null;
|
||||
}
|
||||
|
||||
|
||||
private void Update()
|
||||
{
|
||||
m_nesIns?.EmulateFrame(true);
|
||||
if (m_nesIns != null)
|
||||
{
|
||||
m_nesIns.EmulateFrame(true);
|
||||
|
||||
var screenBuffer = m_nesIns.ppu.GetScreenPtr();
|
||||
var lineColorMode = m_nesIns.ppu.GetLineColorMode();
|
||||
|
||||
VideoProvider.SetDrawData(screenBuffer, lineColorMode, 256, 240);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,264 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &4232056520112715746
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4232056520112715745}
|
||||
- component: {fileID: 4232056520112715744}
|
||||
m_Layer: 0
|
||||
m_Name: VideoProvider
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &4232056520112715745
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4232056520112715746}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children:
|
||||
- {fileID: 4232056520494431727}
|
||||
m_Father: {fileID: 4232056521131536011}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &4232056520112715744
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4232056520112715746}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 83fbe375412d1af4482ae76e81c1dda2, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
Image: {fileID: 4232056521759880274}
|
||||
--- !u!1 &4232056520494431712
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4232056520494431727}
|
||||
- component: {fileID: 4232056520494431724}
|
||||
- component: {fileID: 4232056520494431725}
|
||||
- component: {fileID: 4232056520494431726}
|
||||
m_Layer: 5
|
||||
m_Name: Canvas
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &4232056520494431727
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4232056520494431712}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 0, y: 0, z: 0}
|
||||
m_Children:
|
||||
- {fileID: 4232056521759880275}
|
||||
m_Father: {fileID: 4232056520112715745}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0, y: 0}
|
||||
m_AnchorMax: {x: 0, y: 0}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 0, y: 0}
|
||||
m_Pivot: {x: 0, y: 0}
|
||||
--- !u!223 &4232056520494431724
|
||||
Canvas:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4232056520494431712}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 3
|
||||
m_RenderMode: 0
|
||||
m_Camera: {fileID: 0}
|
||||
m_PlaneDistance: 100
|
||||
m_PixelPerfect: 0
|
||||
m_ReceivesEvents: 1
|
||||
m_OverrideSorting: 0
|
||||
m_OverridePixelPerfect: 0
|
||||
m_SortingBucketNormalizedSize: 0
|
||||
m_AdditionalShaderChannelsFlag: 0
|
||||
m_SortingLayerID: 0
|
||||
m_SortingOrder: 0
|
||||
m_TargetDisplay: 0
|
||||
--- !u!114 &4232056520494431725
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4232056520494431712}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_UiScaleMode: 0
|
||||
m_ReferencePixelsPerUnit: 100
|
||||
m_ScaleFactor: 1
|
||||
m_ReferenceResolution: {x: 800, y: 600}
|
||||
m_ScreenMatchMode: 0
|
||||
m_MatchWidthOrHeight: 0
|
||||
m_PhysicalUnit: 3
|
||||
m_FallbackScreenDPI: 96
|
||||
m_DefaultSpriteDPI: 96
|
||||
m_DynamicPixelsPerUnit: 1
|
||||
m_PresetInfoIsWorld: 0
|
||||
--- !u!114 &4232056520494431726
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4232056520494431712}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_IgnoreReversedGraphics: 1
|
||||
m_BlockingObjects: 0
|
||||
m_BlockingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
--- !u!1 &4232056521131536013
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4232056521131536011}
|
||||
- component: {fileID: 4232056521131536012}
|
||||
m_Layer: 0
|
||||
m_Name: NesEmulator
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &4232056521131536011
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4232056521131536013}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children:
|
||||
- {fileID: 4232056520112715745}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &4232056521131536012
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4232056521131536013}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 39557e19783acee499ace6c68549e8f8, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
VideoProvider: {fileID: 4232056520112715744}
|
||||
--- !u!1 &4232056521759880276
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 4232056521759880275}
|
||||
- component: {fileID: 4232056521759880273}
|
||||
- component: {fileID: 4232056521759880274}
|
||||
m_Layer: 5
|
||||
m_Name: RawImage
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &4232056521759880275
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4232056521759880276}
|
||||
m_LocalRotation: {x: 1, y: 0, z: 0, w: 0}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 4232056520494431727}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 180, y: 0, z: 0}
|
||||
m_AnchorMin: {x: 0.5, y: 0.5}
|
||||
m_AnchorMax: {x: 0.5, y: 0.5}
|
||||
m_AnchoredPosition: {x: 0, y: 0}
|
||||
m_SizeDelta: {x: 272, y: 240}
|
||||
m_Pivot: {x: 0.5, y: 0.5}
|
||||
--- !u!222 &4232056521759880273
|
||||
CanvasRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4232056521759880276}
|
||||
m_CullTransparentMesh: 1
|
||||
--- !u!114 &4232056521759880274
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 4232056521759880276}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 1344c3c82d62a2a41a3576d8abb8e3ea, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Material: {fileID: 0}
|
||||
m_Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
m_RaycastTarget: 1
|
||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_Maskable: 1
|
||||
m_OnCullStateChanged:
|
||||
m_PersistentCalls:
|
||||
m_Calls: []
|
||||
m_Texture: {fileID: 8400000, guid: ffe34aaf87e4b9942b4c2ac05943d444, type: 2}
|
||||
m_UVRect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 1
|
||||
height: 1
|
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f8bea3f8aa351bb46ada33b2274729ea
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,38 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!84 &8400000
|
||||
RenderTexture:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: New Render Texture
|
||||
m_ImageContentsHash:
|
||||
serializedVersion: 2
|
||||
Hash: 00000000000000000000000000000000
|
||||
m_ForcedFallbackFormat: 4
|
||||
m_DownscaleFallback: 0
|
||||
m_IsAlphaChannelOptional: 0
|
||||
serializedVersion: 3
|
||||
m_Width: 272
|
||||
m_Height: 240
|
||||
m_AntiAliasing: 1
|
||||
m_MipCount: -1
|
||||
m_DepthFormat: 2
|
||||
m_ColorFormat: 8
|
||||
m_MipMap: 0
|
||||
m_GenerateMips: 1
|
||||
m_SRGB: 0
|
||||
m_UseDynamicScale: 0
|
||||
m_BindMS: 0
|
||||
m_EnableCompatibleFormat: 1
|
||||
m_TextureSettings:
|
||||
serializedVersion: 2
|
||||
m_FilterMode: 1
|
||||
m_Aniso: 0
|
||||
m_MipBias: 0
|
||||
m_WrapU: 1
|
||||
m_WrapV: 1
|
||||
m_WrapW: 1
|
||||
m_Dimension: 2
|
||||
m_VolumeDepth: 1
|
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ffe34aaf87e4b9942b4c2ac05943d444
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 8400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bbd3f54279eb4ae45831a914b13d1cec
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,82 @@
|
||||
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.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Playables;
|
||||
using UnityEngine.UI;
|
||||
using VirtualNes.Core;
|
||||
|
||||
namespace AxibugEmuOnline.Client
|
||||
{
|
||||
public class VideoProvider : MonoBehaviour
|
||||
{
|
||||
public RawImage Image;
|
||||
|
||||
private Color32[] wrapTexBuffer;
|
||||
private IntPtr wrapTexBufferPointer;
|
||||
private Texture2D wrapTex;
|
||||
|
||||
public void SetDrawData(byte[] screenData, byte[] lineColorMode, int screenWidth, int screenHeight)
|
||||
{
|
||||
if (wrapTex == null)
|
||||
{
|
||||
wrapTex = new Texture2D(screenWidth, screenHeight, TextureFormat.BGRA32, false);
|
||||
wrapTexBuffer = new Color32[screenWidth * screenHeight];
|
||||
// 固定数组,防止垃圾回收器移动它
|
||||
GCHandle handle = GCHandle.Alloc(wrapTexBuffer, GCHandleType.Pinned);
|
||||
// 获取数组的指针
|
||||
wrapTexBufferPointer = handle.AddrOfPinnedObject();
|
||||
}
|
||||
|
||||
uint[] pPal;
|
||||
int pScn = 0;
|
||||
int width;
|
||||
|
||||
var Dst = wrapTexBuffer;
|
||||
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)
|
||||
{
|
||||
var edx = screenData[pScn + 8];
|
||||
|
||||
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(wrapTexBuffer);
|
||||
wrapTex.LoadRawTextureData(wrapTexBufferPointer, screenWidth * screenHeight * 4);
|
||||
wrapTex.Apply();
|
||||
|
||||
Graphics.Blit(wrapTex, Image.mainTexture as RenderTexture);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 83fbe375412d1af4482ae76e81c1dda2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -9,22 +9,23 @@ namespace VirtualNes.Core
|
||||
|
||||
public override void Reset(float fClock, int nRate)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
//todo : 实现
|
||||
}
|
||||
|
||||
public override void Setup(float fClock, int nRate)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
//todo : 实现
|
||||
}
|
||||
|
||||
public override void Write(ushort addr, byte data)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
//todo : 实现
|
||||
}
|
||||
|
||||
public override int Process(int channel)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
//todo : 实现
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal void SyncWrite(ushort addr, byte data)
|
||||
@ -34,7 +35,7 @@ namespace VirtualNes.Core
|
||||
|
||||
private void WriteSub(ushort addr, byte data, FDSSOUND ch, double rate)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
//todo : 实现
|
||||
}
|
||||
|
||||
private class FDSSOUND
|
||||
|
@ -6,22 +6,23 @@ namespace VirtualNes.Core
|
||||
{
|
||||
public override void Reset(float fClock, int nRate)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
//todo : 实现
|
||||
}
|
||||
|
||||
public override void Setup(float fClock, int nRate)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
//todo : 实现
|
||||
}
|
||||
|
||||
public override void Write(ushort addr, byte data)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
//todo : 实现
|
||||
}
|
||||
|
||||
public override int Process(int channel)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
//todo : 实现
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -127,22 +127,23 @@ namespace VirtualNes.Core
|
||||
|
||||
public override void Reset(float fClock, int nRate)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
//todo : 实现
|
||||
}
|
||||
|
||||
public override void Setup(float fClock, int nRate)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
//todo : 实现
|
||||
}
|
||||
|
||||
public override void Write(ushort addr, byte data)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
//todo : 实现
|
||||
}
|
||||
|
||||
public override int Process(int channel)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
//todo : 实现
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal byte SyncRead(ushort addr)
|
||||
|
@ -6,27 +6,28 @@ namespace VirtualNes.Core
|
||||
{
|
||||
public override void Reset(float fClock, int nRate)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
//todo : 实现
|
||||
}
|
||||
|
||||
public override void Setup(float fClock, int nRate)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
//todo : 实现
|
||||
}
|
||||
|
||||
public override void Write(ushort addr, byte data)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
//todo : 实现
|
||||
}
|
||||
|
||||
public override int Process(int channel)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
//todo : 实现
|
||||
return 0;
|
||||
}
|
||||
|
||||
internal void SyncWrite(ushort addr, byte data)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
//todo : 实现
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,22 +4,23 @@
|
||||
{
|
||||
public override void Reset(float fClock, int nRate)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
//todo : 实现
|
||||
}
|
||||
|
||||
public override void Setup(float fClock, int nRate)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
//todo : 实现
|
||||
}
|
||||
|
||||
public override void Write(ushort addr, byte data)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
//todo : 实现
|
||||
}
|
||||
|
||||
public override int Process(int channel)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
//todo : 实现
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,22 +4,23 @@
|
||||
{
|
||||
public override void Reset(float fClock, int nRate)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
//todo : 实现
|
||||
}
|
||||
|
||||
public override void Setup(float fClock, int nRate)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
//todo : 实现
|
||||
}
|
||||
|
||||
public override void Write(ushort addr, byte data)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
//todo : 实现
|
||||
}
|
||||
|
||||
public override int Process(int channel)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
//todo : 实现
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#undef DPCM_SYNCCLOCK
|
||||
|
||||
using System;
|
||||
using VirtualNes.Core.Debug;
|
||||
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
@ -42,7 +43,7 @@ namespace VirtualNes.Core
|
||||
private int DMA_cycles;
|
||||
private Mapper mapper;
|
||||
private APU apu;
|
||||
private R6502 R = new R6502();
|
||||
internal R6502 R = new R6502();
|
||||
private byte[] ZN_Table = new byte[256];
|
||||
private Memory<byte> STACK;
|
||||
|
||||
@ -132,75 +133,77 @@ namespace VirtualNes.Core
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
case 0x69:
|
||||
case 0x69: // ADC #$??
|
||||
MR_IM(); ADC();
|
||||
ADD_CYCLE(2);
|
||||
break;
|
||||
case 0x65:
|
||||
case 0x65: // ADC $??
|
||||
MR_ZP(); ADC();
|
||||
ADD_CYCLE(3);
|
||||
break;
|
||||
case 0x75:
|
||||
case 0x75: // ADC $??,X
|
||||
MR_ZX(); ADC();
|
||||
ADD_CYCLE(4);
|
||||
break;
|
||||
case 0x6D:
|
||||
case 0x6D: // ADC $????
|
||||
MR_AB(); ADC();
|
||||
ADD_CYCLE(4);
|
||||
break;
|
||||
case 0x7D:
|
||||
case 0x7D: // ADC $????,X
|
||||
MR_AX(); ADC(); CHECK_EA();
|
||||
ADD_CYCLE(4);
|
||||
break;
|
||||
case 0x79:
|
||||
case 0x79: // ADC $????,Y
|
||||
MR_AY(); ADC(); CHECK_EA();
|
||||
ADD_CYCLE(4);
|
||||
break;
|
||||
case 0x61:
|
||||
case 0x61: // ADC ($??,X)
|
||||
MR_IX(); ADC();
|
||||
ADD_CYCLE(6);
|
||||
break;
|
||||
case 0x71:
|
||||
case 0x71: // ADC ($??),Y
|
||||
MR_IY(); ADC(); CHECK_EA();
|
||||
ADD_CYCLE(4);
|
||||
break;
|
||||
case 0xE9:
|
||||
|
||||
case 0xE9: // SBC #$??
|
||||
MR_IM(); SBC();
|
||||
ADD_CYCLE(2);
|
||||
break;
|
||||
case 0xE5:
|
||||
case 0xE5: // SBC $??
|
||||
MR_ZP(); SBC();
|
||||
ADD_CYCLE(3);
|
||||
break;
|
||||
case 0xF5:
|
||||
case 0xF5: // SBC $??,X
|
||||
MR_ZX(); SBC();
|
||||
ADD_CYCLE(4);
|
||||
break;
|
||||
case 0xED:
|
||||
case 0xED: // SBC $????
|
||||
MR_AB(); SBC();
|
||||
ADD_CYCLE(4);
|
||||
break;
|
||||
case 0xFD:
|
||||
case 0xFD: // SBC $????,X
|
||||
MR_AX(); SBC(); CHECK_EA();
|
||||
ADD_CYCLE(4);
|
||||
break;
|
||||
case 0xF9: // SBC $????Y
|
||||
case 0xF9: // SBC $????,Y
|
||||
MR_AY(); SBC(); CHECK_EA();
|
||||
ADD_CYCLE(4);
|
||||
break;
|
||||
case 0xE1: // SBC ($??X)
|
||||
case 0xE1: // SBC ($??,X)
|
||||
MR_IX(); SBC();
|
||||
ADD_CYCLE(6);
|
||||
break;
|
||||
case 0xF1: // SBC ($??)Y
|
||||
case 0xF1: // SBC ($??),Y
|
||||
MR_IY(); SBC(); CHECK_EA();
|
||||
ADD_CYCLE(5);
|
||||
break;
|
||||
|
||||
case 0xC6: // DEC $??
|
||||
MR_ZP(); DEC(); MW_ZP();
|
||||
ADD_CYCLE(5);
|
||||
break;
|
||||
case 0xD6: // DEC $??X
|
||||
case 0xD6: // DEC $??,X
|
||||
MR_ZX(); DEC(); MW_ZP();
|
||||
ADD_CYCLE(6);
|
||||
break;
|
||||
@ -208,10 +211,11 @@ namespace VirtualNes.Core
|
||||
MR_AB(); DEC(); MW_EA();
|
||||
ADD_CYCLE(6);
|
||||
break;
|
||||
case 0xDE: // DEC $????X
|
||||
case 0xDE: // DEC $????,X
|
||||
MR_AX(); DEC(); MW_EA();
|
||||
ADD_CYCLE(7);
|
||||
break;
|
||||
|
||||
case 0xCA: // DEX
|
||||
DEX();
|
||||
ADD_CYCLE(2);
|
||||
@ -220,11 +224,12 @@ namespace VirtualNes.Core
|
||||
DEY();
|
||||
ADD_CYCLE(2);
|
||||
break;
|
||||
|
||||
case 0xE6: // INC $??
|
||||
MR_ZP(); INC(); MW_ZP();
|
||||
ADD_CYCLE(5);
|
||||
break;
|
||||
case 0xF6: // INC $??X
|
||||
case 0xF6: // INC $??,X
|
||||
MR_ZX(); INC(); MW_ZP();
|
||||
ADD_CYCLE(6);
|
||||
break;
|
||||
@ -232,10 +237,11 @@ namespace VirtualNes.Core
|
||||
MR_AB(); INC(); MW_EA();
|
||||
ADD_CYCLE(6);
|
||||
break;
|
||||
case 0xFE: // INC $????X
|
||||
case 0xFE: // INC $????,X
|
||||
MR_AX(); INC(); MW_EA();
|
||||
ADD_CYCLE(7);
|
||||
break;
|
||||
|
||||
case 0xE8: // INX
|
||||
INX();
|
||||
ADD_CYCLE(2);
|
||||
@ -244,6 +250,7 @@ namespace VirtualNes.Core
|
||||
INY();
|
||||
ADD_CYCLE(2);
|
||||
break;
|
||||
|
||||
case 0x29: // AND #$??
|
||||
MR_IM(); AND();
|
||||
ADD_CYCLE(2);
|
||||
@ -252,7 +259,7 @@ namespace VirtualNes.Core
|
||||
MR_ZP(); AND();
|
||||
ADD_CYCLE(3);
|
||||
break;
|
||||
case 0x35: // AND $??X
|
||||
case 0x35: // AND $??,X
|
||||
MR_ZX(); AND();
|
||||
ADD_CYCLE(4);
|
||||
break;
|
||||
@ -260,22 +267,23 @@ namespace VirtualNes.Core
|
||||
MR_AB(); AND();
|
||||
ADD_CYCLE(4);
|
||||
break;
|
||||
case 0x3D: // AND $????X
|
||||
case 0x3D: // AND $????,X
|
||||
MR_AX(); AND(); CHECK_EA();
|
||||
ADD_CYCLE(4);
|
||||
break;
|
||||
case 0x39: // AND $????Y
|
||||
case 0x39: // AND $????,Y
|
||||
MR_AY(); AND(); CHECK_EA();
|
||||
ADD_CYCLE(4);
|
||||
break;
|
||||
case 0x21: // AND ($??X)
|
||||
case 0x21: // AND ($??,X)
|
||||
MR_IX(); AND();
|
||||
ADD_CYCLE(6);
|
||||
break;
|
||||
case 0x31: // AND ($??)Y
|
||||
case 0x31: // AND ($??),Y
|
||||
MR_IY(); AND(); CHECK_EA();
|
||||
ADD_CYCLE(5);
|
||||
break;
|
||||
|
||||
case 0x0A: // ASL A
|
||||
ASL_A();
|
||||
ADD_CYCLE(2);
|
||||
@ -705,7 +713,7 @@ namespace VirtualNes.Core
|
||||
ADD_CYCLE(6);
|
||||
break;
|
||||
|
||||
// 僼儔僌惂屼宯
|
||||
// フラグ制御系
|
||||
case 0x18: // CLC
|
||||
CLC();
|
||||
ADD_CYCLE(2);
|
||||
@ -736,7 +744,7 @@ namespace VirtualNes.Core
|
||||
ADD_CYCLE(2);
|
||||
break;
|
||||
|
||||
// 僗僞僢僋宯
|
||||
// スタック系
|
||||
case 0x48: // PHA
|
||||
PUSH(R.A);
|
||||
ADD_CYCLE(3);
|
||||
@ -755,7 +763,7 @@ namespace VirtualNes.Core
|
||||
ADD_CYCLE(4);
|
||||
break;
|
||||
|
||||
// 偦偺懠
|
||||
// その他
|
||||
case 0x00: // BRK
|
||||
BRK();
|
||||
ADD_CYCLE(7);
|
||||
@ -765,7 +773,7 @@ namespace VirtualNes.Core
|
||||
ADD_CYCLE(2);
|
||||
break;
|
||||
|
||||
// 枹岞奐柦椷孮
|
||||
// 未公開命令群
|
||||
case 0x0B: // ANC #$??
|
||||
case 0x2B: // ANC #$??
|
||||
MR_IM(); ANC();
|
||||
@ -1105,7 +1113,7 @@ namespace VirtualNes.Core
|
||||
default:
|
||||
if (!Supporter.Config.emulator.bIllegalOp)
|
||||
{
|
||||
throw new Exception("Illegal Opcode");
|
||||
throw new Exception("IllegalOp");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1113,6 +1121,8 @@ namespace VirtualNes.Core
|
||||
ADD_CYCLE(4);
|
||||
}
|
||||
break;
|
||||
// default:
|
||||
// __assume(0);
|
||||
}
|
||||
|
||||
if (nmi_request != 0)
|
||||
@ -1143,7 +1153,6 @@ namespace VirtualNes.Core
|
||||
#endif
|
||||
return TOTAL_cycles - OLD_cycles;
|
||||
}
|
||||
|
||||
private void _IRQ()
|
||||
{
|
||||
PUSH((byte)(R.PC >> 8));
|
||||
@ -1169,7 +1178,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 +1725,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 +1753,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()
|
||||
@ -1836,7 +1845,7 @@ namespace VirtualNes.Core
|
||||
{
|
||||
ET = OP6502W(R.PC);
|
||||
R.PC += 2;
|
||||
EA = (byte)(ET + R.X);
|
||||
EA = (ushort)(ET + R.X);
|
||||
DT = RD6502(EA);
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,22 @@
|
||||
{
|
||||
public class CHEATCODE
|
||||
{
|
||||
// 埲壓偺俀偮偼OR儅僗僋
|
||||
public const int CHEAT_ENABLE = 1 << 0;
|
||||
public const int CHEAT_KEYDISABLE = 1 << 1;
|
||||
|
||||
// 彂偒崬傒庬椶
|
||||
public const int CHEAT_TYPE_ALWAYS = 0; // 忢偵彂偒崬傒
|
||||
public const int CHEAT_TYPE_ONCE = 1; // 侾夞偩偗彂偒崬傒
|
||||
public const int CHEAT_TYPE_GREATER = 2; // 僨乕僞傛傝戝偒偄帪
|
||||
public const int CHEAT_TYPE_LESS = 3; // 僨乕僞傛傝彫偝偄帪
|
||||
|
||||
// 僨乕僞挿
|
||||
public const int CHEAT_LENGTH_1BYTE = 0;
|
||||
public const int CHEAT_LENGTH_2BYTE = 1;
|
||||
public const int CHEAT_LENGTH_3BYTE = 2;
|
||||
public const int CHEAT_LENGTH_4BYTE = 3;
|
||||
|
||||
public byte enable;
|
||||
public byte type;
|
||||
public byte length;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fe59f85b299db6f498a7e87a5125df58
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -1,17 +1,26 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
public static class MemoryUtility
|
||||
{
|
||||
public static void ZEROMEMORY(byte[] array, uint length)
|
||||
public static void ZEROMEMORY(byte[] array, int length)
|
||||
{
|
||||
memset(array, 0, length);
|
||||
Array.Clear(array, 0, array.Length);
|
||||
}
|
||||
|
||||
public static void memset(byte[] array, byte value, uint length)
|
||||
public static void memset(byte[] array, byte value, int length)
|
||||
{
|
||||
Unsafe.InitBlock(ref array[0], value, length);
|
||||
memset(array, 0, value, length);
|
||||
}
|
||||
|
||||
public static void memset(byte[] array, int offset, byte value, int length)
|
||||
{
|
||||
for (int i = offset; i < length; i++)
|
||||
{
|
||||
array[i] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
namespace VirtualNes.Core.Debug
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace VirtualNes.Core.Debug
|
||||
{
|
||||
public static class Debuger
|
||||
{
|
||||
|
@ -1,15 +1,16 @@
|
||||
using System;
|
||||
using VirtualNes.Core;
|
||||
|
||||
namespace VirtualNes
|
||||
{
|
||||
public static class MMU
|
||||
{
|
||||
// CPU 儊儌儕僶儞僋
|
||||
public static Memory<byte>[] CPU_MEM_BANK = new Memory<byte>[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<byte>[] PPU_MEM_BANK = new Memory<byte>[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]; // 僗僥乕僩僙乕僽梡
|
||||
@ -67,9 +68,12 @@ namespace VirtualNes
|
||||
public const byte VRAM_MIRROR4L = 0x03; // PA10 L屌掕 $2000-$23FF偺儈儔乕
|
||||
public const byte VRAM_MIRROR4H = 0x04; // PA10 H屌掕 $2400-$27FF偺儈儔乕
|
||||
|
||||
internal static void SetPROM_Bank(byte page, Memory<byte> ptr, byte type)
|
||||
// Frame-IRQ儗僕僗僞($4017)
|
||||
public static int FrameIRQ;
|
||||
|
||||
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;
|
||||
}
|
||||
@ -77,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<byte>(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;
|
||||
}
|
||||
@ -105,7 +109,7 @@ namespace VirtualNes
|
||||
}
|
||||
|
||||
// PPU VROM bank
|
||||
internal static void SetVROM_Bank(byte page, Memory<byte> ptr, byte type)
|
||||
internal static void SetVROM_Bank(byte page, ByteArrayRef ptr, byte type)
|
||||
{
|
||||
PPU_MEM_BANK[page] = ptr;
|
||||
PPU_MEM_TYPE[page] = type;
|
||||
@ -115,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<byte>(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;
|
||||
}
|
||||
@ -158,7 +162,7 @@ namespace VirtualNes
|
||||
internal static void SetCRAM_1K_Bank(byte page, int bank)
|
||||
{
|
||||
bank &= 0x1F;
|
||||
PPU_MEM_BANK[page] = new Memory<byte>(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;
|
||||
|
||||
@ -190,7 +194,7 @@ namespace VirtualNes
|
||||
internal static void SetVRAM_1K_Bank(byte page, int bank)
|
||||
{
|
||||
bank &= 3;
|
||||
PPU_MEM_BANK[page] = new Memory<byte>(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;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ namespace VirtualNes.Core
|
||||
public abstract class Mapper
|
||||
{
|
||||
protected NES nes;
|
||||
|
||||
public Mapper(NES parent)
|
||||
{
|
||||
nes = parent;
|
||||
@ -25,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);
|
||||
@ -34,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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,10 +79,13 @@ namespace VirtualNes.Core
|
||||
|
||||
public static Mapper CreateMapper(NES parent, int no)
|
||||
{
|
||||
//todo : 实现加载mapper
|
||||
switch (no)
|
||||
{
|
||||
case 4:
|
||||
return new Mapper004(parent);
|
||||
default:
|
||||
throw new NotImplementedException($"Mapper#{no} is not Impl");
|
||||
throw new NotImplementedException($"Mapper#{no:000} is not Impl");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,576 @@
|
||||
using Codice.CM.Client.Differences;
|
||||
using System;
|
||||
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
public class Mapper004 : Mapper
|
||||
{
|
||||
private const int MMC3_IRQ_KLAX = 1;
|
||||
private const int MMC3_IRQ_SHOUGIMEIKAN = 2;
|
||||
private const int MMC3_IRQ_DAI2JISUPER = 3;
|
||||
private const int MMC3_IRQ_DBZ2 = 4;
|
||||
private const int MMC3_IRQ_ROCKMAN3 = 5;
|
||||
|
||||
protected byte[] reg = new byte[8];
|
||||
protected byte prg0, prg1;
|
||||
protected byte chr01, chr23, chr4, chr5, chr6, chr7;
|
||||
protected byte we_sram;
|
||||
|
||||
protected byte irq_type;
|
||||
protected byte irq_enable;
|
||||
protected byte irq_counter;
|
||||
protected byte irq_latch;
|
||||
protected byte irq_request;
|
||||
protected byte irq_preset;
|
||||
protected byte irq_preset_vbl;
|
||||
|
||||
protected byte vs_patch;
|
||||
protected byte vs_index;
|
||||
|
||||
private byte[] VS_TKO_Security = new byte[32]
|
||||
{
|
||||
0xff, 0xbf, 0xb7, 0x97, 0x97, 0x17, 0x57, 0x4f,
|
||||
0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90, 0x94, 0x14,
|
||||
0x56, 0x4e, 0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90,
|
||||
0xd4, 0x5c, 0x3e, 0x26, 0x87, 0x83, 0x13, 0x00
|
||||
};
|
||||
|
||||
public Mapper004(NES parent) : base(parent) { }
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
reg[i] = 0x00;
|
||||
}
|
||||
|
||||
prg0 = 0;
|
||||
prg1 = 1;
|
||||
SetBank_CPU();
|
||||
|
||||
chr01 = 0;
|
||||
chr23 = 2;
|
||||
chr4 = 4;
|
||||
chr5 = 5;
|
||||
chr6 = 6;
|
||||
chr7 = 7;
|
||||
SetBank_PPU();
|
||||
|
||||
we_sram = 0; // Disable
|
||||
irq_enable = 0; // Disable
|
||||
irq_counter = 0;
|
||||
irq_latch = 0xFF;
|
||||
irq_request = 0;
|
||||
irq_preset = 0;
|
||||
irq_preset_vbl = 0;
|
||||
|
||||
// IRQ僞僀僾愝掕
|
||||
nes.SetIrqType(NES.IRQMETHOD.IRQ_CLOCK);
|
||||
irq_type = 0;
|
||||
|
||||
uint crc = nes.rom.GetPROM_CRC();
|
||||
|
||||
if (crc == 0x5c707ac4)
|
||||
{ // Mother(J)
|
||||
nes.SetIrqType(NES.IRQMETHOD.IRQ_HSYNC);
|
||||
nes.SetRenderMethod(EnumRenderMethod.TILE_RENDER);
|
||||
}
|
||||
if (crc == 0xcb106f49)
|
||||
{ // F-1 Sensation(J)
|
||||
nes.SetRenderMethod(EnumRenderMethod.TILE_RENDER);
|
||||
}
|
||||
if (crc == 0x1170392a)
|
||||
{ // Karakuri Kengou Den - Musashi Road - Karakuri Nin Hashiru!(J)
|
||||
nes.SetIrqType(NES.IRQMETHOD.IRQ_HSYNC);
|
||||
}
|
||||
if (crc == 0x14a01c70)
|
||||
{ // Gun-Dec(J)
|
||||
nes.SetRenderMethod(EnumRenderMethod.TILE_RENDER);
|
||||
}
|
||||
if (crc == 0xeffeea40)
|
||||
{ // For Klax(J)
|
||||
irq_type = MMC3_IRQ_KLAX;
|
||||
nes.SetIrqType(NES.IRQMETHOD.IRQ_HSYNC);
|
||||
nes.SetRenderMethod(EnumRenderMethod.TILE_RENDER);
|
||||
}
|
||||
if (crc == 0xc17ae2dc)
|
||||
{ // God Slayer - Haruka Tenkuu no Sonata(J)
|
||||
nes.SetRenderMethod(EnumRenderMethod.TILE_RENDER);
|
||||
}
|
||||
if (crc == 0x126ea4a0)
|
||||
{ // Summer Carnival '92 - Recca(J)
|
||||
nes.SetIrqType(NES.IRQMETHOD.IRQ_HSYNC);
|
||||
}
|
||||
if (crc == 0x1f2f4861)
|
||||
{ // J League Fighting Soccer - The King of Ace Strikers(J)
|
||||
nes.SetIrqType(NES.IRQMETHOD.IRQ_HSYNC);
|
||||
}
|
||||
if (crc == 0x5a6860f1)
|
||||
{ // Shougi Meikan '92(J)
|
||||
irq_type = MMC3_IRQ_SHOUGIMEIKAN;
|
||||
nes.SetIrqType(NES.IRQMETHOD.IRQ_HSYNC);
|
||||
}
|
||||
if (crc == 0xae280e20)
|
||||
{ // Shougi Meikan '93(J)
|
||||
irq_type = MMC3_IRQ_SHOUGIMEIKAN;
|
||||
nes.SetIrqType(NES.IRQMETHOD.IRQ_HSYNC);
|
||||
}
|
||||
if (crc == 0xe19a2473)
|
||||
{ // Sugoro Quest - Dice no Senshi Tachi(J)
|
||||
nes.SetIrqType(NES.IRQMETHOD.IRQ_HSYNC);
|
||||
nes.SetRenderMethod(EnumRenderMethod.TILE_RENDER);
|
||||
}
|
||||
if (crc == 0x702d9b33)
|
||||
{ // Star Wars - The Empire Strikes Back(Victor)(J)
|
||||
nes.SetIrqType(NES.IRQMETHOD.IRQ_HSYNC);
|
||||
}
|
||||
if (crc == 0xa9a0d729)
|
||||
{ // Dai Kaijuu - Deburas(J)
|
||||
nes.SetRenderMethod(EnumRenderMethod.TILE_RENDER);
|
||||
}
|
||||
if (crc == 0xc5fea9f2)
|
||||
{ // Dai 2 Ji - Super Robot Taisen(J)
|
||||
irq_type = MMC3_IRQ_DAI2JISUPER;
|
||||
}
|
||||
if (crc == 0xd852c2f7)
|
||||
{ // Time Zone(J)
|
||||
nes.SetRenderMethod(EnumRenderMethod.TILE_RENDER);
|
||||
}
|
||||
if (crc == 0xecfd3c69)
|
||||
{ // Taito Chase H.Q.(J)
|
||||
nes.SetRenderMethod(EnumRenderMethod.TILE_RENDER);
|
||||
}
|
||||
if (crc == 0x7a748058)
|
||||
{ // Tom & Jerry (and Tuffy)(J)
|
||||
nes.SetIrqType(NES.IRQMETHOD.IRQ_HSYNC);
|
||||
}
|
||||
if (crc == 0xaafe699c)
|
||||
{ // Ninja Ryukenden 3 - Yomi no Hakobune(J)
|
||||
nes.SetRenderMethod(EnumRenderMethod.TILE_RENDER);
|
||||
}
|
||||
if (crc == 0x6cc62c06)
|
||||
{ // Hoshi no Kirby - Yume no Izumi no Monogatari(J)
|
||||
nes.SetRenderMethod(EnumRenderMethod.TILE_RENDER);
|
||||
}
|
||||
if (crc == 0x877dba77)
|
||||
{ // My Life My Love - Boku no Yume - Watashi no Negai(J)
|
||||
nes.SetIrqType(NES.IRQMETHOD.IRQ_HSYNC);
|
||||
}
|
||||
if (crc == 0x6f96ed15)
|
||||
{ // Max Warrior - Wakusei Kaigenrei(J)
|
||||
nes.SetIrqType(NES.IRQMETHOD.IRQ_HSYNC);
|
||||
}
|
||||
if (crc == 0x8685f366)
|
||||
{ // Matendouji(J)
|
||||
nes.SetRenderMethod(EnumRenderMethod.TILE_RENDER);
|
||||
}
|
||||
if (crc == 0x8635fed1)
|
||||
{ // Mickey Mouse 3 - Yume Fuusen(J)
|
||||
nes.SetRenderMethod(EnumRenderMethod.TILE_RENDER);
|
||||
}
|
||||
if (crc == 0x26ff3ea2)
|
||||
{ // Yume Penguin Monogatari(J)
|
||||
nes.SetIrqType(NES.IRQMETHOD.IRQ_HSYNC);
|
||||
}
|
||||
if (crc == 0x7671bc51)
|
||||
{ // Red Ariimaa 2(J)
|
||||
nes.SetIrqType(NES.IRQMETHOD.IRQ_HSYNC);
|
||||
}
|
||||
if (crc == 0xade11141)
|
||||
{ // Wanpaku Kokkun no Gourmet World(J)
|
||||
nes.SetIrqType(NES.IRQMETHOD.IRQ_HSYNC);
|
||||
}
|
||||
if (crc == 0x7c7ab58e)
|
||||
{ // Walkuere no Bouken - Toki no Kagi Densetsu(J)
|
||||
nes.SetRenderMethod(EnumRenderMethod.POST_RENDER);
|
||||
}
|
||||
if (crc == 0x26ff3ea2)
|
||||
{ // Yume Penguin Monogatari(J)
|
||||
nes.SetRenderMethod(EnumRenderMethod.TILE_RENDER);
|
||||
}
|
||||
if (crc == 0x126ea4a0)
|
||||
{ // Summer Carnival '92 Recca(J)
|
||||
nes.SetRenderMethod(EnumRenderMethod.TILE_RENDER);
|
||||
}
|
||||
|
||||
if (crc == 0x1d2e5018 // Rockman 3(J)
|
||||
|| crc == 0x6b999aaf)
|
||||
{ // Megaman 3(U)
|
||||
irq_type = MMC3_IRQ_ROCKMAN3;
|
||||
}
|
||||
|
||||
if (crc == 0xd88d48d7)
|
||||
{ // Kick Master(U)
|
||||
irq_type = MMC3_IRQ_ROCKMAN3;
|
||||
}
|
||||
|
||||
if (crc == 0xA67EA466)
|
||||
{ // Alien 3(U)
|
||||
nes.SetRenderMethod(EnumRenderMethod.TILE_RENDER);
|
||||
}
|
||||
|
||||
if (crc == 0xe763891b)
|
||||
{ // DBZ2
|
||||
irq_type = MMC3_IRQ_DBZ2;
|
||||
}
|
||||
|
||||
// VS-Unisystem
|
||||
vs_patch = 0;
|
||||
vs_index = 0;
|
||||
|
||||
if (crc == 0xeb2dba63 // VS TKO Boxing
|
||||
|| crc == 0x98cfe016)
|
||||
{ // VS TKO Boxing (Alt)
|
||||
vs_patch = 1;
|
||||
}
|
||||
if (crc == 0x135adf7c)
|
||||
{ // VS Atari RBI Baseball
|
||||
vs_patch = 2;
|
||||
}
|
||||
if (crc == 0xf9d3b0a3 // VS Super Xevious
|
||||
|| crc == 0x9924980a // VS Super Xevious (b1)
|
||||
|| crc == 0x66bb838f)
|
||||
{ // VS Super Xevious (b2)
|
||||
vs_patch = 3;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetBank_PPU()
|
||||
{
|
||||
if (MMU.VROM_1K_SIZE != 0)
|
||||
{
|
||||
if ((reg[0] & 0x80) != 0)
|
||||
{
|
||||
MMU.SetVROM_8K_Bank(chr4, chr5, chr6, chr7,
|
||||
chr01, chr01 + 1, chr23, chr23 + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
MMU.SetVROM_8K_Bank(chr01, chr01 + 1, chr23, chr23 + 1,
|
||||
chr4, chr5, chr6, chr7);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((reg[0] & 0x80) != 0)
|
||||
{
|
||||
MMU.SetCRAM_1K_Bank(4, (chr01 + 0) & 0x07);
|
||||
MMU.SetCRAM_1K_Bank(5, (chr01 + 1) & 0x07);
|
||||
MMU.SetCRAM_1K_Bank(6, (chr23 + 0) & 0x07);
|
||||
MMU.SetCRAM_1K_Bank(7, (chr23 + 1) & 0x07);
|
||||
MMU.SetCRAM_1K_Bank(0, chr4 & 0x07);
|
||||
MMU.SetCRAM_1K_Bank(1, chr5 & 0x07);
|
||||
MMU.SetCRAM_1K_Bank(2, chr6 & 0x07);
|
||||
MMU.SetCRAM_1K_Bank(3, chr7 & 0x07);
|
||||
}
|
||||
else
|
||||
{
|
||||
MMU.SetCRAM_1K_Bank(0, (chr01 + 0) & 0x07);
|
||||
MMU.SetCRAM_1K_Bank(1, (chr01 + 1) & 0x07);
|
||||
MMU.SetCRAM_1K_Bank(2, (chr23 + 0) & 0x07);
|
||||
MMU.SetCRAM_1K_Bank(3, (chr23 + 1) & 0x07);
|
||||
MMU.SetCRAM_1K_Bank(4, chr4 & 0x07);
|
||||
MMU.SetCRAM_1K_Bank(5, chr5 & 0x07);
|
||||
MMU.SetCRAM_1K_Bank(6, chr6 & 0x07);
|
||||
MMU.SetCRAM_1K_Bank(7, chr7 & 0x07);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override byte ReadLow(ushort addr)
|
||||
{
|
||||
if (vs_patch == 0)
|
||||
{
|
||||
if (addr >= 0x5000 && addr <= 0x5FFF)
|
||||
{
|
||||
return MMU.XRAM[addr - 0x4000];
|
||||
}
|
||||
}
|
||||
else if (vs_patch == 1)
|
||||
{
|
||||
// VS TKO Boxing Security
|
||||
if (addr == 0x5E00)
|
||||
{
|
||||
vs_index = 0;
|
||||
return 0x00;
|
||||
}
|
||||
else if (addr == 0x5E01)
|
||||
{
|
||||
return VS_TKO_Security[(vs_index++) & 0x1F];
|
||||
}
|
||||
}
|
||||
else if (vs_patch == 2)
|
||||
{
|
||||
// VS Atari RBI Baseball Security
|
||||
if (addr == 0x5E00)
|
||||
{
|
||||
vs_index = 0;
|
||||
return 0x00;
|
||||
}
|
||||
else if (addr == 0x5E01)
|
||||
{
|
||||
if (vs_index++ == 9)
|
||||
return 0x6F;
|
||||
else
|
||||
return 0xB4;
|
||||
}
|
||||
}
|
||||
else if (vs_patch == 3)
|
||||
{
|
||||
// VS Super Xevious
|
||||
switch (addr)
|
||||
{
|
||||
case 0x54FF:
|
||||
return 0x05;
|
||||
case 0x5678:
|
||||
if (vs_index != 0)
|
||||
return 0x00;
|
||||
else
|
||||
return 0x01;
|
||||
case 0x578f:
|
||||
if (vs_index != 0)
|
||||
return 0xD1;
|
||||
else
|
||||
return 0x89;
|
||||
case 0x5567:
|
||||
if (vs_index != 0)
|
||||
{
|
||||
vs_index = 0;
|
||||
return 0x3E;
|
||||
}
|
||||
else
|
||||
{
|
||||
vs_index = 1;
|
||||
return 0x37;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return base.ReadLow(addr);
|
||||
}
|
||||
|
||||
public override void WriteLow(ushort addr, byte data)
|
||||
{
|
||||
if (addr >= 0x5000 && addr <= 0x5FFF)
|
||||
{
|
||||
MMU.XRAM[addr - 0x4000] = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
base.WriteLow(addr, data);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(ushort addr, byte data)
|
||||
{
|
||||
switch (addr & 0xE001)
|
||||
{
|
||||
case 0x8000:
|
||||
reg[0] = data;
|
||||
SetBank_CPU();
|
||||
SetBank_PPU();
|
||||
break;
|
||||
case 0x8001:
|
||||
reg[1] = data;
|
||||
|
||||
switch (reg[0] & 0x07)
|
||||
{
|
||||
case 0x00:
|
||||
chr01 = (byte)(data & 0xFE);
|
||||
SetBank_PPU();
|
||||
break;
|
||||
case 0x01:
|
||||
chr23 = (byte)(data & 0xFE);
|
||||
SetBank_PPU();
|
||||
break;
|
||||
case 0x02:
|
||||
chr4 = data;
|
||||
SetBank_PPU();
|
||||
break;
|
||||
case 0x03:
|
||||
chr5 = data;
|
||||
SetBank_PPU();
|
||||
break;
|
||||
case 0x04:
|
||||
chr6 = data;
|
||||
SetBank_PPU();
|
||||
break;
|
||||
case 0x05:
|
||||
chr7 = data;
|
||||
SetBank_PPU();
|
||||
break;
|
||||
case 0x06:
|
||||
prg0 = data;
|
||||
SetBank_CPU();
|
||||
break;
|
||||
case 0x07:
|
||||
prg1 = data;
|
||||
SetBank_CPU();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xA000:
|
||||
reg[2] = data;
|
||||
if (!nes.rom.Is4SCREEN())
|
||||
{
|
||||
if ((data & 0x01) != 0) MMU.SetVRAM_Mirror(MMU.VRAM_HMIRROR);
|
||||
else MMU.SetVRAM_Mirror(MMU.VRAM_VMIRROR);
|
||||
}
|
||||
break;
|
||||
case 0xA001:
|
||||
reg[3] = data;
|
||||
//DEBUGOUT( "MPRWR A=%04X D=%02X L=%3d CYC=%d\n", addr&0xFFFF, data&0xFF, nes->GetScanline(), nes->cpu->GetTotalCycles() );
|
||||
break;
|
||||
case 0xC000:
|
||||
//DEBUGOUT( "MPRWR A=%04X D=%02X L=%3d CYC=%d\n", addr&0xFFFF, data&0xFF, nes->GetScanline(), nes->cpu->GetTotalCycles() );
|
||||
reg[4] = data;
|
||||
if (irq_type == MMC3_IRQ_KLAX || irq_type == MMC3_IRQ_ROCKMAN3)
|
||||
{
|
||||
irq_counter = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
irq_latch = data;
|
||||
}
|
||||
if (irq_type == MMC3_IRQ_DBZ2)
|
||||
{
|
||||
irq_latch = 0x07;
|
||||
}
|
||||
break;
|
||||
case 0xC001:
|
||||
reg[5] = data;
|
||||
if (irq_type == MMC3_IRQ_KLAX || irq_type == MMC3_IRQ_ROCKMAN3)
|
||||
{
|
||||
irq_latch = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((nes.GetScanline() < 240) || (irq_type == MMC3_IRQ_SHOUGIMEIKAN))
|
||||
{
|
||||
irq_counter |= 0x80;
|
||||
irq_preset = 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
irq_counter |= 0x80;
|
||||
irq_preset_vbl = 0xFF;
|
||||
irq_preset = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xE000:
|
||||
reg[6] = data;
|
||||
irq_enable = 0;
|
||||
irq_request = 0;
|
||||
|
||||
nes.cpu.ClrIRQ(CPU.IRQ_MAPPER);
|
||||
break;
|
||||
case 0xE001:
|
||||
reg[7] = data;
|
||||
irq_enable = 1;
|
||||
irq_request = 0;
|
||||
|
||||
// nes->cpu->ClrIRQ( IRQ_MAPPER );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Clock(int cycles)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void HSync(int scanline)
|
||||
{
|
||||
if (irq_type == MMC3_IRQ_KLAX)
|
||||
{
|
||||
if ((scanline >= 0 && scanline <= 239) && nes.ppu.IsDispON())
|
||||
{
|
||||
if (irq_enable != 0)
|
||||
{
|
||||
if (irq_counter == 0)
|
||||
{
|
||||
irq_counter = irq_latch;
|
||||
irq_request = 0xFF;
|
||||
}
|
||||
if (irq_counter > 0)
|
||||
{
|
||||
irq_counter--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (irq_request != 0)
|
||||
{
|
||||
nes.cpu.SetIRQ(CPU.IRQ_MAPPER);
|
||||
}
|
||||
}
|
||||
else if (irq_type == MMC3_IRQ_ROCKMAN3)
|
||||
{
|
||||
if ((scanline >= 0 && scanline <= 239) && nes.ppu.IsDispON())
|
||||
{
|
||||
if (irq_enable != 0)
|
||||
{
|
||||
if ((--irq_counter) == 0)
|
||||
{
|
||||
irq_request = 0xFF;
|
||||
irq_counter = irq_latch;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (irq_request != 0)
|
||||
{
|
||||
nes.cpu.SetIRQ(CPU.IRQ_MAPPER);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((scanline >= 0 && scanline <= 239) && nes.ppu.IsDispON())
|
||||
{
|
||||
if (irq_preset_vbl != 0)
|
||||
{
|
||||
irq_counter = irq_latch;
|
||||
irq_preset_vbl = 0;
|
||||
}
|
||||
if (irq_preset != 0)
|
||||
{
|
||||
irq_counter = irq_latch;
|
||||
irq_preset = 0;
|
||||
if (irq_type == MMC3_IRQ_DAI2JISUPER && scanline == 0)
|
||||
{
|
||||
irq_counter--;
|
||||
}
|
||||
}
|
||||
else if (irq_counter > 0)
|
||||
{
|
||||
irq_counter--;
|
||||
}
|
||||
|
||||
if (irq_counter == 0)
|
||||
{
|
||||
if (irq_enable != 0)
|
||||
{
|
||||
irq_request = 0xFF;
|
||||
|
||||
nes.cpu.SetIRQ(CPU.IRQ_MAPPER);
|
||||
}
|
||||
irq_preset = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetBank_CPU()
|
||||
{
|
||||
if ((reg[0] & 0x40) != 0)
|
||||
{
|
||||
MMU.SetPROM_32K_Bank(MMU.PROM_8K_SIZE - 2, prg1, prg0, MMU.PROM_8K_SIZE - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
MMU.SetPROM_32K_Bank(prg0, prg1, MMU.PROM_8K_SIZE - 2, MMU.PROM_8K_SIZE - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1be6fcc00c619e84cbf0d5d92701b2e3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@ -330,7 +330,7 @@ namespace VirtualNes.Core
|
||||
}
|
||||
}
|
||||
|
||||
private void SetExController(EXCONTROLLER type)
|
||||
internal void SetExController(EXCONTROLLER type)
|
||||
{
|
||||
excontroller_select = (int)type;
|
||||
|
||||
@ -404,6 +404,42 @@ namespace VirtualNes.Core
|
||||
expad.Reset();
|
||||
}
|
||||
}
|
||||
|
||||
internal bool IsZapperMode()
|
||||
{
|
||||
return bZapperMode;
|
||||
}
|
||||
|
||||
internal void VSync()
|
||||
{
|
||||
padbitsync[0] = padbit[0];
|
||||
padbitsync[1] = padbit[1];
|
||||
padbitsync[2] = padbit[2];
|
||||
padbitsync[3] = padbit[3];
|
||||
micbitsync = micbit;
|
||||
}
|
||||
|
||||
internal uint GetSyncData()
|
||||
{
|
||||
uint ret;
|
||||
ret = (uint)(padbit[0] | (padbit[1] << 8) | (padbit[2] << 16) | (padbit[3] << 24));
|
||||
ret |= (uint)(micbit << 8);
|
||||
return ret;
|
||||
}
|
||||
|
||||
internal void SetSyncData(uint data)
|
||||
{
|
||||
micbit = (byte)((data & 0x00000400) >> 8);
|
||||
padbit[0] = (byte)data;
|
||||
padbit[1] = (byte)(data >> 8);
|
||||
padbit[2] = (byte)(data >> 16);
|
||||
padbit[3] = (byte)(data >> 24);
|
||||
}
|
||||
|
||||
internal int GetExController()
|
||||
{
|
||||
return excontroller_select;
|
||||
}
|
||||
}
|
||||
|
||||
public enum VSType
|
||||
|
@ -1,10 +1,10 @@
|
||||
using Codice.CM.Client.Differences;
|
||||
using System;
|
||||
|
||||
namespace VirtualNes.Core
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
public class PPU
|
||||
{
|
||||
public const int SCREEN_WIDTH = 256 + 16;
|
||||
public const int SCREEN_HEIGHT = 240;
|
||||
|
||||
private static byte[][] CreateCOLORMAP()
|
||||
{
|
||||
byte[][] res = new byte[5][];
|
||||
@ -187,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;
|
||||
}
|
||||
|
||||
@ -199,7 +199,7 @@ namespace VirtualNes.Core
|
||||
ScanlineNo = scanline;
|
||||
if (scanline < 240)
|
||||
{
|
||||
lpScanline = (int)(Screen.SCREEN_WIDTH) * scanline;
|
||||
lpScanline = (SCREEN_WIDTH) * scanline;
|
||||
}
|
||||
}
|
||||
|
||||
@ -323,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;
|
||||
}
|
||||
@ -358,15 +358,810 @@ namespace VirtualNes.Core
|
||||
loopy_shift = 0;
|
||||
|
||||
if (lpScreen != null)
|
||||
MemoryUtility.memset(lpScreen, 0x3F, (int)(Screen.SCREEN_WIDTH) * (int)(Screen.SCREEN_HEIGHT));
|
||||
MemoryUtility.memset(lpScreen, 0x3F, SCREEN_WIDTH * SCREEN_HEIGHT);
|
||||
if (lpColormode != null)
|
||||
MemoryUtility.memset(lpColormode, 0, (int)(Screen.SCREEN_HEIGHT));
|
||||
MemoryUtility.memset(lpColormode, 0, SCREEN_HEIGHT);
|
||||
}
|
||||
|
||||
private enum Screen
|
||||
internal void FrameStart()
|
||||
{
|
||||
SCREEN_WIDTH = 256 + 16,
|
||||
SCREEN_HEIGHT = 240
|
||||
if ((MMU.PPUREG[1] & (PPU_SPDISP_BIT | PPU_BGDISP_BIT)) != 0)
|
||||
{
|
||||
MMU.loopy_v = MMU.loopy_t;
|
||||
loopy_shift = MMU.loopy_x;
|
||||
loopy_y = (ushort)((MMU.loopy_v & 0x7000) >> 12);
|
||||
}
|
||||
|
||||
if (lpScreen != null)
|
||||
{
|
||||
MemoryUtility.memset(lpScreen, 0x3F, SCREEN_WIDTH);
|
||||
}
|
||||
if (lpColormode != null)
|
||||
{
|
||||
lpColormode[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
internal void ScanlineNext()
|
||||
{
|
||||
if ((MMU.PPUREG[1] & (PPU_BGDISP_BIT | PPU_SPDISP_BIT)) != 0)
|
||||
{
|
||||
if ((MMU.loopy_v & 0x7000) == 0x7000)
|
||||
{
|
||||
MMU.loopy_v &= 0x8FFF;
|
||||
if ((MMU.loopy_v & 0x03E0) == 0x03A0)
|
||||
{
|
||||
MMU.loopy_v ^= 0x0800;
|
||||
MMU.loopy_v &= 0xFC1F;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((MMU.loopy_v & 0x03E0) == 0x03E0)
|
||||
{
|
||||
MMU.loopy_v &= 0xFC1F;
|
||||
}
|
||||
else
|
||||
{
|
||||
MMU.loopy_v += 0x0020;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MMU.loopy_v += 0x1000;
|
||||
}
|
||||
loopy_y = (ushort)((MMU.loopy_v & 0x7000) >> 12);
|
||||
}
|
||||
}
|
||||
|
||||
internal void ScanlineStart()
|
||||
{
|
||||
if ((MMU.PPUREG[1] & (PPU_BGDISP_BIT | PPU_SPDISP_BIT)) != 0)
|
||||
{
|
||||
MMU.loopy_v = (ushort)((MMU.loopy_v & 0xFBE0) | (MMU.loopy_t & 0x041F));
|
||||
loopy_shift = MMU.loopy_x;
|
||||
loopy_y = (ushort)((MMU.loopy_v & 0x7000) >> 12);
|
||||
nes.mapper.PPU_Latch((ushort)(0x2000 + (MMU.loopy_v & 0x0FFF)));
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] BGwrite = new byte[33 + 1];
|
||||
private byte[] BGmono = new byte[33 + 1];
|
||||
private byte[] SPwrite = new byte[33 + 1];
|
||||
|
||||
internal void Scanline(int scanline, bool bMax, bool bLeftClip)
|
||||
{
|
||||
int pScn = 0;
|
||||
int pBGw = 0;
|
||||
byte chr_h = 0, chr_l = 0, attr = 0;
|
||||
|
||||
MemoryUtility.ZEROMEMORY(BGwrite, BGwrite.Length);
|
||||
MemoryUtility.ZEROMEMORY(BGmono, BGmono.Length);
|
||||
|
||||
// Linecolor mode
|
||||
lpColormode[scanline] = (byte)(((MMU.PPUREG[1] & PPU_BGCOLOR_BIT) >> 5) | ((MMU.PPUREG[1] & PPU_COLORMODE_BIT) << 7));
|
||||
|
||||
// Render BG
|
||||
if ((MMU.PPUREG[1] & PPU_BGDISP_BIT) == 0)
|
||||
{
|
||||
MemoryUtility.memset(lpScreen, lpScanline, MMU.BGPAL[0], SCREEN_WIDTH);
|
||||
if (nes.GetRenderMethod() == EnumRenderMethod.TILE_RENDER)
|
||||
{
|
||||
nes.EmulationCPU(NES.FETCH_CYCLES * 4 * 32);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nes.GetRenderMethod() != EnumRenderMethod.TILE_RENDER)
|
||||
{
|
||||
if (!bExtLatch)
|
||||
{
|
||||
// Without Extension Latch
|
||||
pScn = lpScanline + (8 - loopy_shift);
|
||||
pBGw = 0;
|
||||
|
||||
int tileofs = (MMU.PPUREG[0] & PPU_BGTBL_BIT) << 8;
|
||||
int ntbladr = 0x2000 + (MMU.loopy_v & 0x0FFF);
|
||||
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];
|
||||
|
||||
int tileadr;
|
||||
int cache_tile = unchecked((int)(0xFFFF0000));
|
||||
byte cache_attr = 0xFF;
|
||||
|
||||
chr_h = chr_l = attr = 0;
|
||||
|
||||
attradr &= 0x3FF;
|
||||
|
||||
|
||||
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);
|
||||
|
||||
if (cache_tile == tileadr && cache_attr == attr)
|
||||
{
|
||||
lpScreen[pScn + 0] = lpScreen[pScn - 8];
|
||||
lpScreen[pScn + 0 + 1] = lpScreen[pScn - 8 + 1];
|
||||
lpScreen[pScn + 0 + 2] = lpScreen[pScn - 8 + 2];
|
||||
lpScreen[pScn + 0 + 3] = lpScreen[pScn - 8 + 3];
|
||||
|
||||
lpScreen[pScn + 4] = lpScreen[pScn - 4];
|
||||
lpScreen[pScn + 4 + 1] = lpScreen[pScn - 4 + 1];
|
||||
lpScreen[pScn + 4 + 2] = lpScreen[pScn - 4 + 2];
|
||||
lpScreen[pScn + 4 + 3] = lpScreen[pScn - 4 + 3];
|
||||
|
||||
BGwrite[pBGw + 0] = BGwrite[pBGw - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
cache_tile = tileadr;
|
||||
cache_attr = attr;
|
||||
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;
|
||||
{
|
||||
int c1 = ((chr_l >> 1) & 0x55) | (chr_h & 0xAA);
|
||||
int c2 = (chr_l & 0x55) | ((chr_h << 1) & 0xAA);
|
||||
lpScreen[pScn + 0] = MMU.BGPAL[pBGPAL + (c1 >> 6)];
|
||||
lpScreen[pScn + 4] = MMU.BGPAL[pBGPAL + ((c1 >> 2) & 3)];
|
||||
lpScreen[pScn + 1] = MMU.BGPAL[pBGPAL + ((c1 >> 6))];
|
||||
lpScreen[pScn + 5] = MMU.BGPAL[pBGPAL + ((c2 >> 2) & 3)];
|
||||
lpScreen[pScn + 2] = MMU.BGPAL[pBGPAL + ((c1 >> 4) & 3)];
|
||||
lpScreen[pScn + 6] = MMU.BGPAL[pBGPAL + (c1 & 3)];
|
||||
lpScreen[pScn + 3] = MMU.BGPAL[pBGPAL + ((c2 >> 4) & 3)];
|
||||
lpScreen[pScn + 7] = MMU.BGPAL[pBGPAL + (c2 & 3)];
|
||||
}
|
||||
}
|
||||
pScn += 8;
|
||||
pBGw++;
|
||||
|
||||
// Character latch(For MMC2/MMC4)
|
||||
if (bChrLatch)
|
||||
{
|
||||
nes.mapper.PPU_ChrLatch((ushort)(tileadr));
|
||||
}
|
||||
|
||||
if (++ntbl_x == 32)
|
||||
{
|
||||
ntbl_x = 0;
|
||||
ntbladr ^= 0x41F;
|
||||
attradr = 0x03C0 + ((ntbladr & 0x0380) >> 4);
|
||||
pNTBL = MMU.PPU_MEM_BANK[ntbladr >> 10];
|
||||
}
|
||||
else
|
||||
{
|
||||
ntbladr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// With Extension Latch(For MMC5)
|
||||
pScn = lpScanline + (8 - loopy_shift);
|
||||
pBGw = 0;
|
||||
|
||||
int ntbladr = 0x2000 + (MMU.loopy_v & 0x0FFF);
|
||||
int ntbl_x = ntbladr & 0x1F;
|
||||
|
||||
int cache_tile = unchecked((int)(0xFFFF0000));
|
||||
byte cache_attr = 0xFF;
|
||||
|
||||
byte exattr = 0;
|
||||
chr_h = chr_l = attr = 0;
|
||||
|
||||
for (int i = 0; i < 33; i++)
|
||||
{
|
||||
nes.mapper.PPU_ExtLatchX(i);
|
||||
nes.mapper.PPU_ExtLatch((ushort)ntbladr, ref chr_l, ref chr_h, ref exattr);
|
||||
attr = (byte)(exattr & 0x0C);
|
||||
|
||||
if (cache_tile != ((chr_h << 8) + chr_l) || cache_attr != attr)
|
||||
{
|
||||
cache_tile = ((chr_h << 8) + chr_l);
|
||||
cache_attr = attr;
|
||||
BGwrite[pBGw] = (byte)(chr_h | chr_l);
|
||||
|
||||
int pBGPAL = attr;
|
||||
{
|
||||
int c1 = ((chr_l >> 1) & 0x55) | (chr_h & 0xAA);
|
||||
int c2 = (chr_l & 0x55) | ((chr_h << 1) & 0xAA);
|
||||
lpScreen[pScn + 0] = MMU.BGPAL[pBGPAL + (c1 >> 6)];
|
||||
lpScreen[pScn + 4] = MMU.BGPAL[pBGPAL + ((c1 >> 2) & 3)];
|
||||
lpScreen[pScn + 1] = MMU.BGPAL[pBGPAL + (c2 >> 6)];
|
||||
lpScreen[pScn + 5] = MMU.BGPAL[pBGPAL + ((c2 >> 2) & 3)];
|
||||
lpScreen[pScn + 2] = MMU.BGPAL[pBGPAL + ((c1 >> 4) & 3)];
|
||||
lpScreen[pScn + 6] = MMU.BGPAL[pBGPAL + (c1 & 3)];
|
||||
lpScreen[pScn + 3] = MMU.BGPAL[pBGPAL + ((c2 >> 4) & 3)];
|
||||
lpScreen[pScn + 7] = MMU.BGPAL[pBGPAL + (c2 & 3)];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lpScreen[pScn + 0] = lpScreen[pScn - 8];
|
||||
lpScreen[pScn + 0 + 1] = lpScreen[pScn - 8 + 1];
|
||||
lpScreen[pScn + 0 + 2] = lpScreen[pScn - 8 + 2];
|
||||
lpScreen[pScn + 0 + 3] = lpScreen[pScn - 8 + 3];
|
||||
|
||||
lpScreen[pScn + 4] = lpScreen[pScn - 4];
|
||||
lpScreen[pScn + 4 + 1] = lpScreen[pScn - 4 + 1];
|
||||
lpScreen[pScn + 4 + 2] = lpScreen[pScn - 4 + 2];
|
||||
lpScreen[pScn + 4 + 3] = lpScreen[pScn - 4 + 3];
|
||||
|
||||
BGwrite[pBGw + 0] = BGwrite[pBGw - 1];
|
||||
}
|
||||
pScn += 8;
|
||||
pBGw++;
|
||||
|
||||
if (++ntbl_x == 32)
|
||||
{
|
||||
ntbl_x = 0;
|
||||
ntbladr ^= 0x41F;
|
||||
}
|
||||
else
|
||||
{
|
||||
ntbladr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!bExtLatch)
|
||||
{
|
||||
// Without Extension Latch
|
||||
if (!bExtNameTable)
|
||||
{
|
||||
pScn = lpScanline + (8 - loopy_shift);
|
||||
pBGw = 0;
|
||||
|
||||
int ntbladr = 0x2000 + (MMU.loopy_v & 0x0FFF);
|
||||
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];
|
||||
|
||||
int tileadr = 0;
|
||||
int cache_tile = unchecked((int)(0xFFFF0000));
|
||||
byte cache_attr = 0xFF;
|
||||
|
||||
chr_h = chr_l = attr = 0;
|
||||
|
||||
for (int i = 0; i < 33; i++)
|
||||
{
|
||||
tileadr = ((MMU.PPUREG[0] & PPU_BGTBL_BIT) << 8) + pNTBL[ntbladr & 0x03FF] * 0x10 + loopy_y;
|
||||
|
||||
if (i != 0)
|
||||
{
|
||||
nes.EmulationCPU(NES.FETCH_CYCLES * 4);
|
||||
}
|
||||
|
||||
attr = (byte)(((pNTBL[attradr + (ntbl_x >> 2)] >> ((ntbl_x & 2) + attrsft)) & 3) << 2);
|
||||
|
||||
if (cache_tile != tileadr || cache_attr != attr)
|
||||
{
|
||||
cache_tile = tileadr;
|
||||
cache_attr = attr;
|
||||
|
||||
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;
|
||||
{
|
||||
int c1 = ((chr_l >> 1) & 0x55) | (chr_h & 0xAA);
|
||||
int c2 = (chr_l & 0x55) | ((chr_h << 1) & 0xAA);
|
||||
lpScreen[pScn + 0] = MMU.BGPAL[pBGPAL + (c1 >> 6)];
|
||||
lpScreen[pScn + 4] = MMU.BGPAL[pBGPAL + ((c1 >> 2) & 3)];
|
||||
lpScreen[pScn + 1] = MMU.BGPAL[pBGPAL + ((c2 >> 6))];
|
||||
lpScreen[pScn + 5] = MMU.BGPAL[pBGPAL + ((c2 >> 2) & 3)];
|
||||
lpScreen[pScn + 2] = MMU.BGPAL[pBGPAL + ((c1 >> 4) & 3)];
|
||||
lpScreen[pScn + 6] = MMU.BGPAL[pBGPAL + (c1 & 3)];
|
||||
lpScreen[pScn + 3] = MMU.BGPAL[pBGPAL + ((c2 >> 4) & 3)];
|
||||
lpScreen[pScn + 7] = MMU.BGPAL[pBGPAL + (c2 & 3)];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lpScreen[pScn + 0] = lpScreen[pScn - 8];
|
||||
lpScreen[pScn + 0 + 1] = lpScreen[pScn - 8 + 1];
|
||||
lpScreen[pScn + 0 + 2] = lpScreen[pScn - 8 + 2];
|
||||
lpScreen[pScn + 0 + 3] = lpScreen[pScn - 8 + 3];
|
||||
|
||||
lpScreen[pScn + 4] = lpScreen[pScn - 4];
|
||||
lpScreen[pScn + 4 + 1] = lpScreen[pScn - 4 + 1];
|
||||
lpScreen[pScn + 4 + 2] = lpScreen[pScn - 4 + 2];
|
||||
lpScreen[pScn + 4 + 3] = lpScreen[pScn - 4 + 3];
|
||||
|
||||
BGwrite[pBGw + 0] = BGwrite[pBGw - 1];
|
||||
}
|
||||
pScn += 8;
|
||||
pBGw++;
|
||||
|
||||
// Character latch(For MMC2/MMC4)
|
||||
if (bChrLatch)
|
||||
{
|
||||
nes.mapper.PPU_ChrLatch((ushort)(tileadr));
|
||||
}
|
||||
|
||||
if (++ntbl_x == 32)
|
||||
{
|
||||
ntbl_x = 0;
|
||||
ntbladr ^= 0x41F;
|
||||
attradr = 0x03C0 + ((ntbladr & 0x0380) >> 4);
|
||||
pNTBL = MMU.PPU_MEM_BANK[ntbladr >> 10];
|
||||
}
|
||||
else
|
||||
{
|
||||
ntbladr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pScn = lpScanline + (8 - loopy_shift);
|
||||
pBGw = 0;
|
||||
|
||||
int ntbladr;
|
||||
int tileadr;
|
||||
int cache_tile = unchecked((int)(0xFFFF0000));
|
||||
byte cache_attr = 0xFF;
|
||||
|
||||
chr_h = chr_l = attr = 0;
|
||||
|
||||
ushort loopy_v_tmp = MMU.loopy_v;
|
||||
|
||||
for (int i = 0; i < 33; i++)
|
||||
{
|
||||
if (i != 0)
|
||||
{
|
||||
nes.EmulationCPU(NES.FETCH_CYCLES * 4);
|
||||
}
|
||||
|
||||
ntbladr = 0x2000 + (MMU.loopy_v & 0x0FFF);
|
||||
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][tileadr & 0x03FF];
|
||||
chr_h = MMU.PPU_MEM_BANK[tileadr >> 10][(tileadr & 0x03FF) + 8];
|
||||
BGwrite[pBGw] = (byte)(chr_l | chr_h);
|
||||
|
||||
int pBGPAL = attr;
|
||||
{
|
||||
int c1 = ((chr_l >> 1) & 0x55) | (chr_h & 0xAA);
|
||||
int c2 = (chr_l & 0x55) | ((chr_h << 1) & 0xAA);
|
||||
lpScreen[pScn + 0] = MMU.BGPAL[pBGPAL + (c1 >> 6)];
|
||||
lpScreen[pScn + 4] = MMU.BGPAL[pBGPAL + ((c1 >> 2) & 3)];
|
||||
lpScreen[pScn + 1] = MMU.BGPAL[pBGPAL + (c2 >> 6)];
|
||||
lpScreen[pScn + 5] = MMU.BGPAL[pBGPAL + ((c2 >> 2) & 3)];
|
||||
lpScreen[pScn + 2] = MMU.BGPAL[pBGPAL + ((c1 >> 4) & 3)];
|
||||
lpScreen[pScn + 6] = MMU.BGPAL[pBGPAL + (c1 & 3)];
|
||||
lpScreen[pScn + 3] = MMU.BGPAL[pBGPAL + ((c2 >> 4) & 3)];
|
||||
lpScreen[pScn + 7] = MMU.BGPAL[pBGPAL + (c2 & 3)];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lpScreen[pScn + 0] = lpScreen[pScn - 8];
|
||||
lpScreen[pScn + 0 + 1] = lpScreen[pScn - 8 + 1];
|
||||
lpScreen[pScn + 0 + 2] = lpScreen[pScn - 8 + 2];
|
||||
lpScreen[pScn + 0 + 3] = lpScreen[pScn - 8 + 3];
|
||||
|
||||
lpScreen[pScn + 4] = lpScreen[pScn - 4];
|
||||
lpScreen[pScn + 4 + 1] = lpScreen[pScn - 4 + 1];
|
||||
lpScreen[pScn + 4 + 2] = lpScreen[pScn - 4 + 2];
|
||||
lpScreen[pScn + 4 + 3] = lpScreen[pScn - 4 + 3];
|
||||
|
||||
BGwrite[pBGw + 0] = BGwrite[pBGw - 1];
|
||||
}
|
||||
pScn += 8;
|
||||
pBGw++;
|
||||
|
||||
// Character latch(For MMC2/MMC4)
|
||||
if (bChrLatch)
|
||||
{
|
||||
nes.mapper.PPU_ChrLatch((ushort)tileadr);
|
||||
}
|
||||
|
||||
if ((MMU.loopy_v & 0x1F) == 0x1F)
|
||||
{
|
||||
MMU.loopy_v ^= 0x041F;
|
||||
}
|
||||
else
|
||||
{
|
||||
MMU.loopy_v++;
|
||||
}
|
||||
}
|
||||
MMU.loopy_v = loopy_v_tmp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// With Extension Latch(For MMC5)
|
||||
pScn = lpScanline + (8 - loopy_shift);
|
||||
pBGw = 0;
|
||||
|
||||
int ntbladr = 0x2000 + (MMU.loopy_v & 0x0FFF);
|
||||
int ntbl_x = ntbladr & 0x1F;
|
||||
|
||||
int cache_tile = unchecked((int)0xFFFF0000);
|
||||
byte cache_attr = 0xFF;
|
||||
|
||||
byte exattr = 0;
|
||||
chr_h = chr_l = attr = 0;
|
||||
|
||||
for (int i = 0; i < 33; i++)
|
||||
{
|
||||
if (i != 0)
|
||||
{
|
||||
nes.EmulationCPU(NES.FETCH_CYCLES * 4);
|
||||
}
|
||||
nes.mapper.PPU_ExtLatchX(i);
|
||||
nes.mapper.PPU_ExtLatch((ushort)ntbladr, ref chr_l, ref chr_h, ref exattr);
|
||||
attr = (byte)(exattr & 0x0C);
|
||||
|
||||
if (cache_tile != ((chr_h << 8) + chr_l) || cache_attr != attr)
|
||||
{
|
||||
cache_tile = ((chr_h << 8) + chr_l);
|
||||
cache_attr = attr;
|
||||
BGwrite[pBGw] = (byte)(chr_l | chr_h);
|
||||
|
||||
int pBGPAL = attr;
|
||||
{
|
||||
int c1 = ((chr_l >> 1) & 0x55) | (chr_h & 0xAA);
|
||||
int c2 = (chr_l & 0x55) | ((chr_h << 1) & 0xAA);
|
||||
lpScreen[pScn + 0] = MMU.BGPAL[pBGPAL + ((c1 >> 6))];
|
||||
lpScreen[pScn + 4] = MMU.BGPAL[pBGPAL + ((c1 >> 2) & 3)];
|
||||
lpScreen[pScn + 1] = MMU.BGPAL[pBGPAL + ((c2 >> 6))];
|
||||
lpScreen[pScn + 5] = MMU.BGPAL[pBGPAL + ((c2 >> 2) & 3)];
|
||||
lpScreen[pScn + 2] = MMU.BGPAL[pBGPAL + ((c1 >> 4) & 3)];
|
||||
lpScreen[pScn + 6] = MMU.BGPAL[pBGPAL + (c1 & 3)];
|
||||
lpScreen[pScn + 3] = MMU.BGPAL[pBGPAL + ((c2 >> 4) & 3)];
|
||||
lpScreen[pScn + 7] = MMU.BGPAL[pBGPAL + (c2 & 3)];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lpScreen[pScn + 0] = lpScreen[pScn - 8];
|
||||
lpScreen[pScn + 0 + 1] = lpScreen[pScn - 8 + 1];
|
||||
lpScreen[pScn + 0 + 2] = lpScreen[pScn - 8 + 2];
|
||||
lpScreen[pScn + 0 + 3] = lpScreen[pScn - 8 + 3];
|
||||
|
||||
lpScreen[pScn + 4] = lpScreen[pScn - 4];
|
||||
lpScreen[pScn + 4 + 1] = lpScreen[pScn - 4 + 1];
|
||||
lpScreen[pScn + 4 + 2] = lpScreen[pScn - 4 + 2];
|
||||
lpScreen[pScn + 4 + 3] = lpScreen[pScn - 4 + 3];
|
||||
|
||||
BGwrite[pBGw + 0] = BGwrite[pBGw - 1];
|
||||
}
|
||||
pScn += 8;
|
||||
pBGw++;
|
||||
|
||||
if (++ntbl_x == 32)
|
||||
{
|
||||
ntbl_x = 0;
|
||||
ntbladr ^= 0x41F;
|
||||
}
|
||||
else
|
||||
{
|
||||
ntbladr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((MMU.PPUREG[1] & PPU_BGCLIP_BIT) == 0 && bLeftClip)
|
||||
{
|
||||
pScn = lpScanline + 8;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
lpScreen[i] = MMU.BGPAL[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Render sprites
|
||||
var temp = ~PPU_SPMAX_FLAG;
|
||||
MMU.PPUREG[2] = (byte)(MMU.PPUREG[2] & temp);
|
||||
|
||||
// 昞帵婜娫奜偱偁傟偽僉儍儞僙儖
|
||||
if (scanline > 239)
|
||||
return;
|
||||
|
||||
if ((MMU.PPUREG[1] & PPU_SPDISP_BIT) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int spmax = 0;
|
||||
int spraddr = 0, sp_y = 0, sp_h = 0;
|
||||
chr_h = chr_l = 0;
|
||||
|
||||
|
||||
pBGw = 0;
|
||||
int pSPw = 0;
|
||||
int pBit2Rev = 0;
|
||||
|
||||
MemoryUtility.ZEROMEMORY(SPwrite, SPwrite.Length);
|
||||
|
||||
spmax = 0;
|
||||
Sprite sp = new Sprite(MMU.SPRAM, 0);
|
||||
sp_h = (MMU.PPUREG[0] & PPU_SP16_BIT) != 0 ? 15 : 7;
|
||||
|
||||
// Left clip
|
||||
if (bLeftClip && ((MMU.PPUREG[1] & PPU_SPCLIP_BIT) == 0))
|
||||
{
|
||||
SPwrite[0] = 0xFF;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 64; i++, sp.AddOffset(1))
|
||||
{
|
||||
sp_y = scanline - (sp.y + 1);
|
||||
// 僗僉儍儞儔僀儞撪偵SPRITE偑懚嵼偡傞偐傪僠僃僢僋
|
||||
if (sp_y != (sp_y & sp_h))
|
||||
continue;
|
||||
|
||||
if ((MMU.PPUREG[0] & PPU_SP16_BIT) == 0)
|
||||
{
|
||||
// 8x8 Sprite
|
||||
spraddr = ((MMU.PPUREG[0] & PPU_SPTBL_BIT) << 9) + (sp.tile << 4);
|
||||
if ((sp.attr & SP_VMIRROR_BIT) == 0)
|
||||
spraddr += sp_y;
|
||||
else
|
||||
spraddr += 7 - sp_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 8x16 Sprite
|
||||
spraddr = ((sp.tile & 1) << 12) + ((sp.tile & 0xFE) << 4);
|
||||
if ((sp.attr & SP_VMIRROR_BIT) == 0)
|
||||
spraddr += ((sp_y & 8) << 1) + (sp_y & 7);
|
||||
else
|
||||
spraddr += ((~sp_y & 8) << 1) + (7 - (sp_y & 7));
|
||||
}
|
||||
// Character pattern
|
||||
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)
|
||||
{
|
||||
nes.mapper.PPU_ChrLatch((ushort)spraddr);
|
||||
}
|
||||
|
||||
// pattern mask
|
||||
if ((sp.attr & SP_HMIRROR_BIT) != 0)
|
||||
{
|
||||
chr_l = Bit2Rev[pBit2Rev + chr_l];
|
||||
chr_h = Bit2Rev[pBit2Rev + chr_h];
|
||||
}
|
||||
byte SPpat = (byte)(chr_l | chr_h);
|
||||
|
||||
// Sprite hitcheck
|
||||
if (i == 0 && (MMU.PPUREG[2] & PPU_SPHIT_FLAG) == 0)
|
||||
{
|
||||
int BGpos = ((sp.x & 0xF8) + ((loopy_shift + (sp.x & 7)) & 8)) >> 3;
|
||||
int BGsft = 8 - ((loopy_shift + sp.x) & 7);
|
||||
|
||||
var temp1 = BGwrite[pBGw + BGpos + 0] << 8;
|
||||
var temp2 = BGwrite[pBGw + BGpos + 1];
|
||||
byte BGmsk = (byte)((temp1 | temp2) >> BGsft);
|
||||
|
||||
if ((SPpat & BGmsk) != 0)
|
||||
{
|
||||
MMU.PPUREG[2] |= PPU_SPHIT_FLAG;
|
||||
}
|
||||
}
|
||||
|
||||
// Sprite mask
|
||||
int SPpos = sp.x / 8;
|
||||
int SPsft = 8 - (sp.x & 7);
|
||||
byte SPmsk = (byte)((SPwrite[pSPw + SPpos + 0] << 8 | SPwrite[pSPw + SPpos + 1]) >> SPsft);
|
||||
ushort SPwrt = (ushort)(SPpat << SPsft);
|
||||
SPwrite[pSPw + SPpos + 0] = (byte)(SPwrite[pSPw + SPpos + 0] | SPwrt >> 8);
|
||||
SPwrite[pSPw + SPpos + 1] = (byte)(SPwrite[pSPw + SPpos + 1] | SPwrt & 0xFF);
|
||||
SPpat = (byte)(SPpat & ~SPmsk);
|
||||
|
||||
if ((sp.attr & SP_PRIORITY_BIT) != 0)
|
||||
{
|
||||
// BG > SP priority
|
||||
int BGpos = ((sp.x & 0xF8) + ((loopy_shift + (sp.x & 7)) & 8)) >> 3;
|
||||
int BGsft = 8 - ((loopy_shift + sp.x) & 7);
|
||||
byte BGmsk = (byte)(((BGwrite[pBGw + BGpos + 0] << 8) | BGwrite[pBGw + BGpos + 1]) >> BGsft);
|
||||
|
||||
SPpat = (byte)(SPpat & ~BGmsk);
|
||||
}
|
||||
|
||||
// Attribute
|
||||
int pSPPAL = (sp.attr & SP_COLOR_BIT) << 2;
|
||||
// Ptr
|
||||
pScn = lpScanline + sp.x + 8;
|
||||
|
||||
if (!bExtMono)
|
||||
{
|
||||
int c1 = ((chr_l >> 1) & 0x55) | (chr_h & 0xAA);
|
||||
int c2 = (chr_l & 0x55) | ((chr_h << 1) & 0xAA);
|
||||
if ((SPpat & 0x80) != 0) lpScreen[pScn + 0] = MMU.SPPAL[pSPPAL + (c1 >> 6)];
|
||||
if ((SPpat & 0x08) != 0) lpScreen[pScn + 4] = MMU.SPPAL[pSPPAL + ((c1 >> 2) & 3)];
|
||||
if ((SPpat & 0x40) != 0) lpScreen[pScn + 1] = MMU.SPPAL[pSPPAL + ((c2 >> 6))];
|
||||
if ((SPpat & 0x04) != 0) lpScreen[pScn + 5] = MMU.SPPAL[pSPPAL + ((c2 >> 2) & 3)];
|
||||
if ((SPpat & 0x20) != 0) lpScreen[pScn + 2] = MMU.SPPAL[pSPPAL + ((c1 >> 4) & 3)];
|
||||
if ((SPpat & 0x02) != 0) lpScreen[pScn + 6] = MMU.SPPAL[pSPPAL + (c1 & 3)];
|
||||
if ((SPpat & 0x10) != 0) lpScreen[pScn + 3] = MMU.SPPAL[pSPPAL + ((c2 >> 4) & 3)];
|
||||
if ((SPpat & 0x01) != 0) lpScreen[pScn + 7] = MMU.SPPAL[pSPPAL + (c2 & 3)];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Monocrome effect (for Final Fantasy)
|
||||
byte mono = BGmono[((sp.x & 0xF8) + ((loopy_shift + (sp.x & 7)) & 8)) >> 3];
|
||||
|
||||
int c1 = ((chr_l >> 1) & 0x55) | (chr_h & 0xAA);
|
||||
int c2 = (chr_l & 0x55) | ((chr_h << 1) & 0xAA);
|
||||
if ((SPpat & 0x80) != 0) lpScreen[pScn + 0] = (byte)(MMU.SPPAL[pSPPAL + (c1 >> 6)] | mono);
|
||||
if ((SPpat & 0x08) != 0) lpScreen[pScn + 4] = (byte)(MMU.SPPAL[pSPPAL + ((c1 >> 2) & 3)] | mono);
|
||||
if ((SPpat & 0x40) != 0) lpScreen[pScn + 1] = (byte)(MMU.SPPAL[pSPPAL + (c2 >> 6)] | mono);
|
||||
if ((SPpat & 0x04) != 0) lpScreen[pScn + 5] = (byte)(MMU.SPPAL[pSPPAL + ((c2 >> 2) & 3)] | mono);
|
||||
if ((SPpat & 0x20) != 0) lpScreen[pScn + 2] = (byte)(MMU.SPPAL[pSPPAL + ((c1 >> 4) & 3)] | mono);
|
||||
if ((SPpat & 0x02) != 0) lpScreen[pScn + 6] = (byte)(MMU.SPPAL[pSPPAL + (c1 & 3)] | mono);
|
||||
if ((SPpat & 0x10) != 0) lpScreen[pScn + 3] = (byte)(MMU.SPPAL[pSPPAL + ((c2 >> 4) & 3)] | mono);
|
||||
if ((SPpat & 0x01) != 0) lpScreen[pScn + 7] = (byte)(MMU.SPPAL[pSPPAL + (c2 & 3)] | mono);
|
||||
}
|
||||
|
||||
if (++spmax > 8 - 1)
|
||||
{
|
||||
if (!bMax)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (spmax > 8 - 1)
|
||||
{
|
||||
MMU.PPUREG[2] |= PPU_SPMAX_FLAG;
|
||||
}
|
||||
}
|
||||
|
||||
internal bool IsSprite0(int scanline)
|
||||
{
|
||||
// 僗僾儔僀僩orBG旕昞帵偼僉儍儞僙儖(僸僢僩偟側偄)
|
||||
if ((MMU.PPUREG[1] & (PPU_SPDISP_BIT | PPU_BGDISP_BIT)) != (PPU_SPDISP_BIT | PPU_BGDISP_BIT))
|
||||
return false;
|
||||
|
||||
// 婛偵僸僢僩偟偰偄偨傜僉儍儞僙儖
|
||||
if ((MMU.PPUREG[2] & PPU_SPHIT_FLAG) != 0)
|
||||
return false;
|
||||
|
||||
if ((MMU.PPUREG[0] & PPU_SP16_BIT) == 0)
|
||||
{
|
||||
// 8x8
|
||||
if ((scanline < MMU.SPRAM[0] + 1) || (scanline > (MMU.SPRAM[0] + 7 + 1)))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 8x16
|
||||
if ((scanline < MMU.SPRAM[0] + 1) || (scanline > (MMU.SPRAM[0] + 15 + 1)))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal void DummyScanline(int scanline)
|
||||
{
|
||||
int i;
|
||||
int spmax;
|
||||
int sp_h;
|
||||
|
||||
MMU.PPUREG[2] = (byte)(MMU.PPUREG[2] & ~PPU_SPMAX_FLAG);
|
||||
|
||||
// 僗僾儔僀僩旕昞帵偼僉儍儞僙儖
|
||||
if ((MMU.PPUREG[1] & PPU_SPDISP_BIT) == 0)
|
||||
return;
|
||||
|
||||
// 昞帵婜娫奜偱偁傟偽僉儍儞僙儖
|
||||
if (scanline < 0 || scanline > 239)
|
||||
return;
|
||||
|
||||
Sprite sp = new Sprite(MMU.SPRAM, 0);
|
||||
sp_h = (MMU.PPUREG[0] & PPU_SP16_BIT) != 0 ? 15 : 7;
|
||||
|
||||
spmax = 0;
|
||||
// Sprite Max check
|
||||
for (i = 0; i < 64; i++, sp.AddOffset(1))
|
||||
{
|
||||
// 僗僉儍儞儔僀儞撪偵SPRITE偑懚嵼偡傞偐傪僠僃僢僋
|
||||
if ((scanline < sp.y + 1) || (scanline > (sp.y + sp_h + 1)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (++spmax > 8 - 1)
|
||||
{
|
||||
MMU.PPUREG[2] |= PPU_SPMAX_FLAG;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void VBlankEnd()
|
||||
{
|
||||
MMU.PPUREG[2] = (byte)(MMU.PPUREG[2] & ~PPU_VBLANK_FLAG);
|
||||
// VBlank扙弌帪偵僋儕傾偝傟傞
|
||||
// 僄僉僒僀僩僶僀僋偱廳梫
|
||||
MMU.PPUREG[2] = (byte)(MMU.PPUREG[2] & ~PPU_SPHIT_FLAG);
|
||||
}
|
||||
|
||||
internal void VBlankStart()
|
||||
{
|
||||
MMU.PPUREG[2] |= PPU_VBLANK_FLAG;
|
||||
}
|
||||
|
||||
public byte[] GetScreenPtr()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
public struct Sprite
|
||||
{
|
||||
public byte y
|
||||
{
|
||||
get => raw[offset + 0];
|
||||
set => raw[offset + 0] = value;
|
||||
}
|
||||
|
||||
public byte tile
|
||||
{
|
||||
get => raw[offset + 1];
|
||||
set => raw[offset + 1] = value;
|
||||
}
|
||||
public byte attr
|
||||
{
|
||||
get => raw[offset + 2];
|
||||
set => raw[offset + 2] = value;
|
||||
}
|
||||
public byte x
|
||||
{
|
||||
get => raw[offset + 3];
|
||||
set => raw[offset + 3] = value;
|
||||
}
|
||||
|
||||
private byte[] raw;
|
||||
private int offset;
|
||||
|
||||
public Sprite(byte[] raw, int offset)
|
||||
{
|
||||
this.raw = raw;
|
||||
this.offset = offset * 4;
|
||||
}
|
||||
|
||||
public void AddOffset(int offset)
|
||||
{
|
||||
this.offset += offset * 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ namespace VirtualNes.Core
|
||||
}
|
||||
|
||||
Supporter.GetFilePathInfo(fname, out fullpath, out path);
|
||||
|
||||
name = Path.GetFileNameWithoutExtension(fullpath);
|
||||
if (!bNSF)
|
||||
{
|
||||
mapper = (header.control1 >> 4) | (header.control2 & 0xF0);
|
||||
@ -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;
|
||||
}
|
||||
@ -396,6 +396,11 @@ namespace VirtualNes.Core
|
||||
{
|
||||
return nsfheader;
|
||||
}
|
||||
|
||||
internal string GetRomPath()
|
||||
{
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -2,5 +2,38 @@
|
||||
{
|
||||
public class CfgGraphics
|
||||
{
|
||||
public bool bAspect = false;
|
||||
public bool bAllSprite = true;
|
||||
public bool bAllLine = false;
|
||||
public bool bFPSDisp = false;
|
||||
public bool bTVFrame = false;
|
||||
public bool bScanline = false;
|
||||
public int nScanlineColor = 75;
|
||||
public bool bSyncDraw = false;
|
||||
public bool bFitZoom = false;
|
||||
|
||||
public bool bLeftClip = true;
|
||||
|
||||
public bool bWindowVSync = false;
|
||||
|
||||
public bool bSyncNoSleep = false;
|
||||
|
||||
public bool bDiskAccessLamp = false;
|
||||
|
||||
public bool bDoubleSize = false;
|
||||
public bool bSystemMemory = false;
|
||||
public bool bUseHEL = false;
|
||||
|
||||
public bool bNoSquareList = false;
|
||||
|
||||
public int nGraphicsFilter = 0;
|
||||
|
||||
public uint dwDisplayWidth = 640;
|
||||
public uint dwDisplayHeight = 480;
|
||||
public uint dwDisplayDepth = 16;
|
||||
public uint dwDisplayRate = 0;
|
||||
|
||||
public bool bPaletteFile = false;
|
||||
public char[] szPaletteFile = new char[260];
|
||||
}
|
||||
}
|
@ -1,6 +1,14 @@
|
||||
namespace VirtualNes.Core
|
||||
using System;
|
||||
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
public class CfgMovie
|
||||
{
|
||||
public byte[] bUsePlayer = new byte[4] { 0xFF, 0x00, 0x00, 0x00 };
|
||||
public bool bRerecord = true;
|
||||
public bool bLoopPlay = false;
|
||||
public bool bResetRec = false;
|
||||
public bool bPadDisplay = false;
|
||||
public bool bTimeDisplay = false;
|
||||
}
|
||||
}
|
@ -1,6 +1,25 @@
|
||||
namespace VirtualNes.Core
|
||||
using System;
|
||||
|
||||
namespace VirtualNes.Core
|
||||
{
|
||||
public class CfgPath
|
||||
{
|
||||
public bool bRomPath = true;
|
||||
public bool bSavePath = true;
|
||||
public bool bStatePath = true;
|
||||
public bool bSnapshotPath = true;
|
||||
public bool bMoviePath = true;
|
||||
public bool bWavePath = true;
|
||||
public bool bCheatPath = true;
|
||||
public bool bIpsPath = true;
|
||||
|
||||
public string szRomPath = "roms";
|
||||
public string szSavePath = "save";
|
||||
public string szStatePath = "state";
|
||||
public string szSnapshotPath = "snapshot";
|
||||
public string szMoviePath = "movie";
|
||||
public string szWavePath = "wave";
|
||||
public string szCheatPath = "cheatcode";
|
||||
public string szIpsPath = "ips";
|
||||
}
|
||||
}
|
@ -17,4 +17,35 @@
|
||||
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)
|
||||
{
|
||||
nRenderMethod = defRenderMethod;
|
||||
nIRQtype = defIRQtype;
|
||||
bFrameIRQ = defFrameIRQ;
|
||||
bVideoMode = defVideoMode;
|
||||
}
|
||||
|
||||
public static void Load(uint gid, uint mid)
|
||||
{
|
||||
nRenderMethod = defRenderMethod;
|
||||
nIRQtype = defIRQtype;
|
||||
bFrameIRQ = defFrameIRQ;
|
||||
bVideoMode = defVideoMode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,20 @@ namespace VirtualNes.Core
|
||||
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 EmulatorConfig Config => s_support.Config;
|
||||
}
|
||||
|
||||
@ -46,5 +60,9 @@ 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);
|
||||
}
|
||||
}
|
||||
|
49
AxibugEmuOnline.Client/Assets/VirtualNes.Core/VsUnisystem.cs
Normal file
49
AxibugEmuOnline.Client/Assets/VirtualNes.Core/VsUnisystem.cs
Normal file
@ -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 },
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: db82d3b2d60f2c14fa3c5582acc439c6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
167
virtuanessrc097-master/.gitignore
vendored
Normal file
167
virtuanessrc097-master/.gitignore
vendored
Normal file
@ -0,0 +1,167 @@
|
||||
VirtuaNES.exe
|
||||
VirtuaNES.ini
|
||||
|
||||
#################
|
||||
## Eclipse
|
||||
#################
|
||||
.vs/
|
||||
debug/
|
||||
*.pydevproject
|
||||
.project
|
||||
.metadata
|
||||
bin/
|
||||
tmp/
|
||||
*.tmp
|
||||
*.bak
|
||||
*.swp
|
||||
*~.nib
|
||||
local.properties
|
||||
.classpath
|
||||
.settings/
|
||||
.loadpath
|
||||
|
||||
# External tool builders
|
||||
.externalToolBuilders/
|
||||
|
||||
# Locally stored "Eclipse launch configurations"
|
||||
*.launch
|
||||
|
||||
# CDT-specific
|
||||
.cproject
|
||||
|
||||
# PDT-specific
|
||||
.buildpath
|
||||
|
||||
|
||||
#################
|
||||
## Visual Studio
|
||||
#################
|
||||
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.sln.docstates
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Rr]elease/
|
||||
*_i.c
|
||||
*_p.c
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.vspscc
|
||||
.builds
|
||||
*.dotCover
|
||||
|
||||
## TODO: If you have NuGet Package Restore enabled, uncomment this
|
||||
#packages/
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish
|
||||
|
||||
# Others
|
||||
[Bb]in
|
||||
[Oo]bj
|
||||
sql
|
||||
TestResults
|
||||
*.Cache
|
||||
ClientBin
|
||||
stylecop.*
|
||||
~$*
|
||||
*.dbmdl
|
||||
Generated_Code #added for RIA/Silverlight projects
|
||||
|
||||
# Backup & report files from converting an old project file to a newer
|
||||
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
|
||||
|
||||
|
||||
############
|
||||
## Windows
|
||||
############
|
||||
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
|
||||
#############
|
||||
## Python
|
||||
#############
|
||||
|
||||
*.py[co]
|
||||
|
||||
# Packages
|
||||
*.egg
|
||||
*.egg-info
|
||||
dist
|
||||
build
|
||||
eggs
|
||||
parts
|
||||
bin
|
||||
var
|
||||
sdist
|
||||
develop-eggs
|
||||
.installed.cfg
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
.coverage
|
||||
.tox
|
||||
|
||||
#Translations
|
||||
*.mo
|
||||
|
||||
#Mr Developer
|
||||
.mr.developer.cfg
|
||||
|
||||
# Mac crap
|
||||
.DS_Store
|
BIN
virtuanessrc097-master/AboutDlg.cpp
Normal file
BIN
virtuanessrc097-master/AboutDlg.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/AboutDlg.h
Normal file
BIN
virtuanessrc097-master/AboutDlg.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/App.cpp
Normal file
BIN
virtuanessrc097-master/App.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/App.h
Normal file
BIN
virtuanessrc097-master/App.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/Archive.cpp
Normal file
BIN
virtuanessrc097-master/Archive.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/Archive.h
Normal file
BIN
virtuanessrc097-master/Archive.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/AviConvDlg.cpp
Normal file
BIN
virtuanessrc097-master/AviConvDlg.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/AviConvDlg.h
Normal file
BIN
virtuanessrc097-master/AviConvDlg.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/AviWriter.cpp
Normal file
BIN
virtuanessrc097-master/AviWriter.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/AviWriter.h
Normal file
BIN
virtuanessrc097-master/AviWriter.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/CHyperLink.h
Normal file
BIN
virtuanessrc097-master/CHyperLink.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/ChatDlg.cpp
Normal file
BIN
virtuanessrc097-master/ChatDlg.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/ChatDlg.h
Normal file
BIN
virtuanessrc097-master/ChatDlg.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/CheatDlg.cpp
Normal file
BIN
virtuanessrc097-master/CheatDlg.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/CheatDlg.h
Normal file
BIN
virtuanessrc097-master/CheatDlg.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/Com.cpp
Normal file
BIN
virtuanessrc097-master/Com.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/Com.h
Normal file
BIN
virtuanessrc097-master/Com.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/Config.cpp
Normal file
BIN
virtuanessrc097-master/Config.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/Config.h
Normal file
BIN
virtuanessrc097-master/Config.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/ControllerDlg.cpp
Normal file
BIN
virtuanessrc097-master/ControllerDlg.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/ControllerDlg.h
Normal file
BIN
virtuanessrc097-master/ControllerDlg.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/Crclib.cpp
Normal file
BIN
virtuanessrc097-master/Crclib.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/Crclib.h
Normal file
BIN
virtuanessrc097-master/Crclib.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/DatachBarcodeDlg.cpp
Normal file
BIN
virtuanessrc097-master/DatachBarcodeDlg.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/DatachBarcodeDlg.h
Normal file
BIN
virtuanessrc097-master/DatachBarcodeDlg.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/DebugOut.cpp
Normal file
BIN
virtuanessrc097-master/DebugOut.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/DebugOut.h
Normal file
BIN
virtuanessrc097-master/DebugOut.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/DipSwitchDlg.cpp
Normal file
BIN
virtuanessrc097-master/DipSwitchDlg.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/DipSwitchDlg.h
Normal file
BIN
virtuanessrc097-master/DipSwitchDlg.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/DirectDraw.cpp
Normal file
BIN
virtuanessrc097-master/DirectDraw.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/DirectDraw.h
Normal file
BIN
virtuanessrc097-master/DirectDraw.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/DirectInput.cpp
Normal file
BIN
virtuanessrc097-master/DirectInput.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/DirectInput.h
Normal file
BIN
virtuanessrc097-master/DirectInput.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/DirectSound.cpp
Normal file
BIN
virtuanessrc097-master/DirectSound.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/DirectSound.h
Normal file
BIN
virtuanessrc097-master/DirectSound.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/Doc/Copying.txt
Normal file
BIN
virtuanessrc097-master/Doc/Copying.txt
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/Doc/ReadmeSrc.txt
Normal file
BIN
virtuanessrc097-master/Doc/ReadmeSrc.txt
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/EmuThread.cpp
Normal file
BIN
virtuanessrc097-master/EmuThread.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/EmuThread.h
Normal file
BIN
virtuanessrc097-master/EmuThread.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/EmulatorDlg.cpp
Normal file
BIN
virtuanessrc097-master/EmulatorDlg.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/EmulatorDlg.h
Normal file
BIN
virtuanessrc097-master/EmulatorDlg.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/English.vlp
Normal file
BIN
virtuanessrc097-master/English.vlp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/ExtSoundFile.h
Normal file
BIN
virtuanessrc097-master/ExtSoundFile.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/FolderDlg.cpp
Normal file
BIN
virtuanessrc097-master/FolderDlg.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/FolderDlg.h
Normal file
BIN
virtuanessrc097-master/FolderDlg.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/GameOptionDlg.cpp
Normal file
BIN
virtuanessrc097-master/GameOptionDlg.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/GameOptionDlg.h
Normal file
BIN
virtuanessrc097-master/GameOptionDlg.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/GraphicsDlg.cpp
Normal file
BIN
virtuanessrc097-master/GraphicsDlg.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/GraphicsDlg.h
Normal file
BIN
virtuanessrc097-master/GraphicsDlg.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/JoyAxisDlg.cpp
Normal file
BIN
virtuanessrc097-master/JoyAxisDlg.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/JoyAxisDlg.h
Normal file
BIN
virtuanessrc097-master/JoyAxisDlg.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/LanguageDlg.cpp
Normal file
BIN
virtuanessrc097-master/LanguageDlg.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/LanguageDlg.h
Normal file
BIN
virtuanessrc097-master/LanguageDlg.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/LauncherDlg.cpp
Normal file
BIN
virtuanessrc097-master/LauncherDlg.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/LauncherDlg.h
Normal file
BIN
virtuanessrc097-master/LauncherDlg.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/MMTimer.cpp
Normal file
BIN
virtuanessrc097-master/MMTimer.cpp
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/MMTimer.h
Normal file
BIN
virtuanessrc097-master/MMTimer.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/Macro.h
Normal file
BIN
virtuanessrc097-master/Macro.h
Normal file
Binary file not shown.
BIN
virtuanessrc097-master/MainFrame.cpp
Normal file
BIN
virtuanessrc097-master/MainFrame.cpp
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user