翻译迭代中

This commit is contained in:
ALIENJACK\alien 2024-07-24 14:27:10 +08:00
parent 2d47b306f4
commit 0e25114e9c
30 changed files with 1021 additions and 109 deletions

View File

@ -123,6 +123,49 @@ NavMeshSettings:
debug: debug:
m_Flags: 0 m_Flags: 0
m_NavMeshData: {fileID: 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 --- !u!1 &708549044
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0

View File

@ -2,7 +2,7 @@
"name": "AxibugEmuOnline.Client", "name": "AxibugEmuOnline.Client",
"rootNamespace": "AxibugEmuOnline.Client", "rootNamespace": "AxibugEmuOnline.Client",
"references": [ "references": [
"GUID:0c194730510bd1b4fad0398ccfe4235b" "GUID:390a2c4058e5c304a87e8be70c84d80b"
], ],
"includePlatforms": [], "includePlatforms": [],
"excludePlatforms": [], "excludePlatforms": [],

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5ff32bd86cd0f8245811007dc4e50768
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,20 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using VirtualNes.Core.Debug;
namespace AxibugEmuOnline.Client
{
public class CoreDebuger : IDebugerImpl
{
public void Log(string message)
{
Debug.Log(message);
}
public void LogError(string message)
{
Debug.LogError(message);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 06357866273334741b885e5a1ad23afd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,49 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using VirtualNes.Core;
namespace AxibugEmuOnline.Client
{
public class CoreSupporter : ISupporterImpl
{
private static string RomDirectoryPath
{
get
{
#if UNITY_EDITOR
return "Assets/StreamingAssets/Roms";
#else
return $"{Application.streamingAssetsPath}/Roms";
#endif
}
}
public Stream OpenRom(string fname)
{
try
{
var stream = File.Open($"{RomDirectoryPath}/{fname}", FileMode.Open);
return stream;
}
catch (Exception ex)
{
Debug.LogError(ex);
return null;
}
}
public void GetRomPathInfo(string fname, out string fullPath, out string directPath)
{
directPath = RomDirectoryPath;
fullPath = $"{directPath}/{fname}";
}
public Stream OpenFile_DISKSYS()
{
return File.Open($"{Application.streamingAssetsPath}/Disksys.rom", FileMode.Open, FileAccess.Read);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8207d923313517f448d7b4d54756e993
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,21 @@
using UnityEngine;
using VirtualNes.Core;
using VirtualNes.Core.Debug;
namespace AxibugEmuOnline.Client
{
public class NesEmulator : MonoBehaviour
{
private void Start()
{
StartGame("Kirby.nes");
}
public void StartGame(string romName)
{
Supporter.Setup(new CoreSupporter());
Debuger.Setup(new CoreDebuger());
NES nes = new NES(romName);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 39557e19783acee499ace6c68549e8f8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 353264361911f2f43bb2c088c7e73fec
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,6 +1,6 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 01dd757415143ae46921461228964dd5 guid: 588a6a32c9d46b943b4909b1757f4572
TextScriptImporter: DefaultImporter:
externalObjects: {} externalObjects: {}
userData: userData:
assetBundleName: assetBundleName:

View File

@ -1,6 +1,6 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: ecb5d904338d35c43bb3b98249b36394 guid: 41cd7684d8de61f4499c3aa27a6c5b3a
TextScriptImporter: DefaultImporter:
externalObjects: {} externalObjects: {}
userData: userData:
assetBundleName: assetBundleName:

View File

@ -1,6 +1,6 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 4933f61382c34574db545f3d9e72b51d guid: 50dfce75937af2a44bafd221a0163501
TextScriptImporter: DefaultImporter:
externalObjects: {} externalObjects: {}
userData: userData:
assetBundleName: assetBundleName:

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 7abf09a3e3fd84648852e5d972dfd260
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -19,6 +19,8 @@ namespace VirtualNes.Core
public APU(NES parent) public APU(NES parent)
{ {
@internal = new APU_INTERNAL();
exsound_select = 0; exsound_select = 0;
nes = parent; nes = parent;

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7b37fc906e6cec64eb2608762f7f80bf
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,92 @@
using Codice.CM.Client.Differences;
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting.Antlr3.Runtime.Tree;
using UnityEngine;
namespace VirtualNes.Core
{
public static class CRC
{
const int CHAR_BIT = 8;
const ulong CRCPOLY1 = 0x04C11DB7UL;
const ulong CRCPOLY2 = 0xEDB88320UL;
static bool m_Init;
static bool m_InitRev;
static ulong[] m_CrcTable = new ulong[byte.MaxValue + 1];
static ulong[] m_CrcTableRev = new ulong[byte.MaxValue + 1];
public static ulong Crc(int size, Span<byte> c)
{
if (!m_Init)
{
MakeTable();
m_Init = true;
}
ulong r = 0xFFFFFFFFUL;
int step = 0;
while (--size >= 0)
{
r = (r << CHAR_BIT) ^ m_CrcTable[(byte)(r >> (32 - CHAR_BIT)) ^ c[step]];
step++;
}
return ~r & 0xFFFFFFFFUL;
}
public static ulong CrcRev(int size, Span<byte> c)
{
if (!m_InitRev)
{
MakeTableRev();
m_InitRev = true;
}
ulong r = 0xFFFFFFFFUL;
int step = 0;
while (--size >= 0)
{
r = (r >> CHAR_BIT) ^ m_CrcTableRev[(byte)r ^ c[step]];
step++;
}
return r ^ 0xFFFFFFFFUL;
}
static void MakeTable()
{
int i, j;
ulong r;
for (i = 0; i <= byte.MaxValue; i++)
{
r = (ulong)i << (32 - CHAR_BIT);
for (j = 0; j < CHAR_BIT; j++)
{
if ((r & 0x80000000UL) > 0) r = (r << 1) ^ CRCPOLY1;
else r <<= 1;
}
m_CrcTable[i] = r & 0xFFFFFFFFUL;
}
}
static void MakeTableRev()
{
int i, j;
ulong r;
for (i = 0; i <= byte.MaxValue; i++)
{
r = (ulong)i;
for (j = 0; j < CHAR_BIT; j++)
{
if ((r & 1) > 0) r = (r >> 1) ^ CRCPOLY2;
else r >>= 1;
}
m_CrcTableRev[i] = r;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e1939f721bc0cab42add18338dbff333
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,143 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace VirtualNes.Core
{
public enum EnumRomControlByte1 : byte
{
ROM_VMIRROR = 0x01,
ROM_SAVERAM = 0x02,
ROM_TRAINER = 0x04,
ROM_4SCREEN = 0x08,
}
public enum EnumRomControlByte2 : byte
{
ROM_VSUNISYSTEM = 0x01
}
public enum EnumRomType
{
InValid,
NES,
/// <summary> Nintendo Disk System </summary>
FDS,
NSF
}
public struct NSFHEADER
{
byte[] ID;
byte Version;
byte TotalSong;
byte StartSong;
ushort LoadAddress;
ushort InitAddress;
ushort PlayAddress;
byte[] SongName;
byte[] ArtistName;
byte[] CopyrightName;
ushort SpeedNTSC;
byte[] BankSwitch;
ushort SpeedPAL;
byte NTSC_PALbits;
byte ExtraChipSelect;
byte[] Expansion; // must be 0
public static int SizeOf()
{
return 128;
}
public static NSFHEADER GetDefault()
{
var res = new NSFHEADER();
res.ID = new byte[5];
res.SongName = new byte[32];
res.ArtistName = new byte[32];
res.CopyrightName = new byte[32];
res.BankSwitch = new byte[8];
res.Expansion = new byte[4];
return res;
}
}
public struct NESHEADER
{
public byte[] ID;
public byte PRG_PAGE_SIZE;
public byte CHR_PAGE_SIZE;
public byte control1;
public byte control2;
public byte[] reserved;
public bool CheckValid()
{
return GetRomType() != EnumRomType.InValid;
}
public static int SizeOf()
{
return 16;
}
public EnumRomType GetRomType()
{
if (ID[0] == 'N' && ID[1] == 'E' && ID[2] == 'S' && ID[3] == 0x1A)
return EnumRomType.NES;
if (ID[0] == 'F' && ID[1] == 'D' && ID[2] == 'S' && ID[3] == 0x1A)
return EnumRomType.FDS;
if (ID[0] == 'N' && ID[1] == 'E' && ID[2] == 'S' && ID[3] == 'M')
return EnumRomType.NSF;
return EnumRomType.InValid;
}
public static NESHEADER GetDefault()
{
var res = new NESHEADER();
res.ID = new byte[4];
res.reserved = new byte[8];
return res;
}
public static NESHEADER Read(Span<byte> data)
{
var res = new NESHEADER();
res.ID = data.Slice(0, 4).ToArray();
res.PRG_PAGE_SIZE = data[4];
res.CHR_PAGE_SIZE = data[5];
res.control1 = data[6];
res.control2 = data[7];
res.reserved = data.Slice(8, 8).ToArray();
return res;
}
public byte[] DataToBytes()
{
byte[] res = new byte[16];
res[0] = ID[0];
res[1] = ID[1];
res[2] = ID[2];
res[3] = ID[3];
res[4] = PRG_PAGE_SIZE;
res[5] = CHR_PAGE_SIZE;
res[6] = control1;
res[7] = control2;
res[8] = reserved[0];
res[9] = reserved[1];
res[10] = reserved[2];
res[11] = reserved[3];
res[12] = reserved[4];
res[13] = reserved[5];
res[14] = reserved[6];
res[15] = reserved[7];
return res;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 65b1ea91f79171f4f82ab91106909f86
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,426 @@
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Remoting.Messaging;
using UnityEngine;
namespace VirtualNes.Core
{
public static class RomPatch
{
public static void DoPatch(ref ulong crc, ref byte[] lpPRG, ref byte[] lpCHR, ref int mapper, ref NESHEADER header)
{
// Mapper 000
if (crc == 0x57970078)
{ // F-1 Race(J)
lpPRG[0x078C] = 0x6C;
lpPRG[0x3FE1] = 0xFF;
lpPRG[0x3FE6] = 0x00;
}
if (crc == 0xaf2bbcbc // Mach Rider(JU)
|| crc == 0x3acd4bf1 // Mach Rider(Alt)(JU) 無理矢理パッチ(^^;
|| crc == 0x8bbe9bec)
{
lpPRG[0x090D] = 0x6E;
lpPRG[0x7FDF] = 0xFF;
lpPRG[0x7FE4] = 0x00;
header.control1 = (byte)EnumRomControlByte1.ROM_VMIRROR;
}
if (crc == 0xe16bb5fe)
{ // Zippy Race(J)
header.control1 &= 0xf6;
}
if (crc == 0x85534474)
{ // Lode Runner(J)
lpPRG[0x29E9] = 0xEA; // セーブメニューを出すパッチ
lpPRG[0x29EA] = 0xEA;
lpPRG[0x29F8] = 0xEA;
lpPRG[0x29F9] = 0xEA;
}
// Mapper 001
if (crc == 0x7831b2ff // America Daitouryou Senkyo(J)
|| crc == 0x190a3e11 // Be-Bop-Highschool - Koukousei Gokuraku Densetsu(J)
|| crc == 0x52449508 // Home Run Nighter - Pennant League!!(J)
|| crc == 0x0973f714 // Jangou(J)
|| crc == 0x7172f3d4 // Kabushiki Doujou(J)
|| crc == 0xa5781280 // Kujaku Ou 2(J)
|| crc == 0x8ce9c87b // Money Game, The(J)
|| crc == 0xec47296d // Morita Kazuo no Shougi(J)
|| crc == 0xcee5857b // Ninjara Hoi!(J)
|| crc == 0xe63d9193 // Tanigawa Kouji no Shougi Shinan 3(J)
|| crc == 0xd54f5da9 // Tsuppari Wars(J)
|| crc == 0x1e0c7ea3)
{ // AD&D Dragons of Flame(J)
header.control1 |= (byte)EnumRomControlByte1.ROM_SAVERAM;
}
if (crc == 0x1995ac4e)
{ // Ferrari Grand Prix Challenge(J) 無理矢理パッチ(^^;
lpPRG[0x1F7AD] = 0xFF;
lpPRG[0x1F7BC] = 0x00;
}
if (crc == 0x20d22251)
{ // Top rider(J) 無理矢理パッチ(^^;
lpPRG[0x1F17E] = 0xEA;
lpPRG[0x1F17F] = 0xEA;
}
if (crc == 0x11469ce3)
{ // Viva! Las Vegas(J) 無理矢理パッチ(^^;
lpCHR[0x0000] = 0x01;
}
if (crc == 0x3fccdc7b)
{ // Baseball Star - Mezase Sankanou!!(J) 無理矢理パッチ(^^;
lpPRG[0x0F666] = 0x9D;
}
if (crc == 0xdb564628)
{ // Mario Open Golf(J)
lpPRG[0x30195] = 0xC0;
}
// Mapper 002
if (crc == 0x63af202f)
{ // JJ - Tobidase Daisakusen Part 2(J)
header.control1 &= 0xf6;
header.control1 |= (byte)EnumRomControlByte1.ROM_VMIRROR;
}
if (crc == 0x99a62e47)
{ // Black Bass 2, The(J)
header.control1 &= 0xf6;
header.control1 |= (byte)EnumRomControlByte1.ROM_VMIRROR;
}
if (crc == 0x0eaa7515 // Rod Land(J)
|| crc == 0x22ab9694)
{ // Rod Land(E)
header.control1 &= 0xf6;
header.control1 |= (byte)EnumRomControlByte1.ROM_VMIRROR;
}
if (crc == 0x2061772a)
{ // Tantei Jinguji Taburou Tokino Sugiyukumamani (J)
header.control1 &= 0xf6;
header.control1 |= (byte)EnumRomControlByte1.ROM_VMIRROR;
}
// Mapper 003
if (crc == 0x29401686)
{ // Minna no Taabou no Nakayoshi Dai Sakusen(J)
// lpPRG[0x2B3E] = 0x60;
}
if (crc == 0x932a077a)
{ // TwinBee(J)
mapper = 87;
}
if (crc == 0x8218c637)
{ // Space Hunter(J)
// header.control1 &= 0xf6;
// header.control1 |= ROM_4SCREEN;
header.control1 = (byte)EnumRomControlByte1.ROM_VMIRROR;
}
if (crc == 0x2bb6a0f8 // Sherlock Holmes - Hakushaku Reijou Yuukai Jiken(J)
|| crc == 0x28c11d24 // Sukeban Deka 3(J)
|| crc == 0x02863604)
{ // Sukeban Deka 3(J)(Alt)
header.control1 &= 0xf6;
header.control1 |= (byte)EnumRomControlByte1.ROM_VMIRROR;
}
// Mapper 004
if (crc == 0x58581770)
{ // Rasaaru Ishii no Childs Quest(J)
header.control1 &= 0xf6;
header.control1 |= (byte)EnumRomControlByte1.ROM_VMIRROR;
}
if (crc == 0xf3feb3ab // Kunio Kun no Jidaigeki Dayo Zenin Shuugou! (J)
|| crc == 0xa524ae9b // Otaku no Seiza - An Adventure in the Otaku Galaxy (J)
|| crc == 0x46dc6e57 // SD Gundam - Gachapon Senshi 2 - Capsule Senki (J)
|| crc == 0x66b2dec7 // SD Gundam - Gachapon Senshi 3 - Eiyuu Senki (J)
|| crc == 0x92b07fd9 // SD Gundam - Gachapon Senshi 4 - New Type Story (J)
|| crc == 0x8ee6463a // SD Gundam - Gachapon Senshi 5 - Battle of Universal Century (J)
|| crc == 0xaf754426 // Ultraman Club 3 (J)
|| crc == 0xfe4e5b11 // Ushio to Tora - Shinen no Daiyou (J)
|| crc == 0x57c12c17)
{ // Yamamura Misa Suspense - Kyouto Zaiteku Satsujin Jiken (J)
header.control1 |= (byte)EnumRomControlByte1.ROM_SAVERAM;
}
if (crc == 0x42e03e4a)
{ // RPG Jinsei Game (J)
mapper = 118;
header.control1 |= (byte)EnumRomControlByte1.ROM_SAVERAM;
}
if (crc == 0xfd0299c3)
{ // METAL MAX(J)
lpPRG[0x3D522] = 0xA9;
lpPRG[0x3D523] = 0x19;
}
if (crc == 0x1d2e5018 // Rockman 3(J)
|| crc == 0x6b999aaf)
{ // Mega Man 3(U)
// lpPRG[0x3C179] = 0xBA;//
// lpPRG[0x3C9CC] = 0x9E;
}
// Mapper 005
if (crc == 0xe91548d8)
{ // Shin 4 Nin Uchi Mahjong - Yakuman Tengoku (J)
header.control1 |= (byte)EnumRomControlByte1.ROM_SAVERAM;
}
if (crc == 0x255b129c)
{ // Gun Sight (J) / Gun Sight (J)[a1]
lpPRG[0x02D0B] = 0x01;
lpPRG[0x0BEC0] = 0x01;
}
// Mapper 010
if (crc == 0xc9cce8f2)
{ // Famicom Wars (J)
header.control1 |= (byte)EnumRomControlByte1.ROM_SAVERAM;
}
// Mapper 016
if (crc == 0x983d8175 // Datach - Battle Rush - Build Up Robot Tournament (J)
|| crc == 0x894efdbc // Datach - Crayon Shin Chan - Ora to Poi Poi (J)
|| crc == 0x19e81461 // Datach - Dragon Ball Z - Gekitou Tenkaichi Budou Kai (J)
|| crc == 0xbe06853f // Datach - J League Super Top Players (J)
|| crc == 0x0be0a328 // Datach - SD Gundam - Gundam Wars (J)
|| crc == 0x5b457641 // Datach - Ultraman Club - Supokon Fight! (J)
|| crc == 0xf51a7f46 // Datach - Yuu Yuu Hakusho - Bakutou Ankoku Bujutsu Kai (J)
|| crc == 0x31cd9903 // Dragon Ball Z - Kyoushuu! Saiya Jin (J)
|| crc == 0xe49fc53e // Dragon Ball Z 2 - Gekishin Freeza!! (J)
|| crc == 0x09499f4d // Dragon Ball Z 3 - Ressen Jinzou Ningen (J)
|| crc == 0x2e991109 // Dragon Ball Z Gaiden - Saiya Jin Zetsumetsu Keikaku (J)
|| crc == 0x170250de)
{ // Rokudenashi Blues(J)
header.control1 |= (byte)EnumRomControlByte1.ROM_SAVERAM;
}
// Mapper 019
if (crc == 0x3296ff7a // Battle Fleet (J)
|| crc == 0x429fd177 // Famista '90 (J)
|| crc == 0xdd454208 // Hydlide 3 - Yami Kara no Houmonsha (J)
|| crc == 0xb1b9e187 // Kaijuu Monogatari (J)
|| crc == 0xaf15338f)
{ // Mindseeker (J)
header.control1 |= (byte)EnumRomControlByte1.ROM_SAVERAM;
}
// Mapper 026
if (crc == 0x836cc1ab)
{ // Mouryou Senki Madara (J)
header.control1 |= (byte)EnumRomControlByte1.ROM_SAVERAM;
}
// Mapper 033
if (crc == 0x547e6cc1)
{ // Flintstones - The Rescue of Dino & Hoppy, The(J)
mapper = 48;
}
// Mapper 065
if (crc == 0xfd3fc292)
{ // Ai Sensei no Oshiete - Watashi no Hoshi (J)
mapper = 32;
}
// Mapper 068
if (crc == 0xfde79681)
{ // Maharaja (J)
header.control1 |= (byte)EnumRomControlByte1.ROM_SAVERAM;
}
// Mapper 069
if (crc == 0xfeac6916 // Honoo no Toukyuuji - Dodge Danpei 2(J)
|| crc == 0x67898319)
{ // Barcode World(J)
header.control1 |= (byte)EnumRomControlByte1.ROM_SAVERAM;
}
// Mapper 080
if (crc == 0x95aaed34 // Mirai Shinwa Jarvas (J)
|| crc == 0x17627d4b)
{ // Taito Grand Prix - Eikou heno License (J)
header.control1 |= (byte)EnumRomControlByte1.ROM_SAVERAM;
}
// Mapper 082
if (crc == 0x4819a595)
{ // Kyuukyoku Harikiri Stadium - Heisei Gannen Ban (J)
header.control1 |= (byte)EnumRomControlByte1.ROM_SAVERAM;
}
// Mapper 086
if (crc == 0xe63f7d0b)
{ // Urusei Yatsura - Lum no Wedding Bell(J)
mapper = 101;
}
// Mapper 118
if (crc == 0x3b0fb600)
{ // Ys 3 - Wonderers From Ys (J)
header.control1 |= (byte)EnumRomControlByte1.ROM_SAVERAM;
}
// Mapper 180
if (crc == 0xc68363f6)
{ // Crazy Climber(J)
header.control1 &= 0xf6;
}
// VS-Unisystem
if (crc == 0x70901b25)
{ // VS Slalom
mapper = 99;
}
if (crc == 0xd5d7eac4)
{ // VS Dr. Mario
mapper = 1;
header.control2 |= (byte)EnumRomControlByte2.ROM_VSUNISYSTEM;
}
if (crc == 0xffbef374 // VS Castlevania
|| crc == 0x8c0c2df5)
{ // VS Top Gun
mapper = 2;
header.control2 |= (byte)EnumRomControlByte2.ROM_VSUNISYSTEM;
}
if (crc == 0xeb2dba63 // VS TKO Boxing
|| crc == 0x98cfe016 // VS TKO Boxing (Alt)
|| crc == 0x9818f656)
{ // VS TKO Boxing (f1)
mapper = 4;
header.control2 |= (byte)EnumRomControlByte2.ROM_VSUNISYSTEM;
}
if (crc == 0x135adf7c)
{ // VS Atari RBI Baseball
mapper = 4;
header.control2 |= (byte)EnumRomControlByte2.ROM_VSUNISYSTEM;
}
if (crc == 0xf9d3b0a3 // VS Super Xevious
|| crc == 0x9924980a // VS Super Xevious (b1)
|| crc == 0x66bb838f)
{ // VS Super Xevious (b2)
mapper = 4;
header.control1 &= 0xF6;
header.control2 |= (byte)EnumRomControlByte2.ROM_VSUNISYSTEM;
}
if (crc == 0x17ae56be)
{ // VS Freedom Force
mapper = 4;
header.control1 &= 0xF6;
header.control1 |= (byte)EnumRomControlByte1.ROM_4SCREEN;
header.control2 |= (byte)EnumRomControlByte2.ROM_VSUNISYSTEM;
}
if (crc == 0xe2c0a2be)
{ // VS Platoon
mapper = 68;
header.control2 |= (byte)EnumRomControlByte2.ROM_VSUNISYSTEM;
}
if (crc == 0xcbe85490 // VS Excitebike
|| crc == 0x29155e0c // VS Excitebike (Alt)
|| crc == 0xff5135a3)
{ // VS Hogan's Alley
header.control1 &= 0xF6;
header.control1 |= (byte)EnumRomControlByte1.ROM_4SCREEN;
}
if (crc == 0x0b65a917)
{ // VS Mach Rider(Endurance Course)
lpPRG[0x7FDF] = 0xFF;
lpPRG[0x7FE4] = 0x00;
}
if (crc == 0x8a6a9848 // VS Mach Rider(Endurance Course)(Alt)
|| crc == 0xae8063ef)
{ // VS Mach Rider(Japan, Fighting Course)
lpPRG[0x7FDD] = 0xFF;
lpPRG[0x7FE2] = 0x00;
}
if (crc == 0x16d3f469)
{ // VS Ninja Jajamaru Kun (J)
header.control1 &= 0xf6;
header.control1 |= (byte)EnumRomControlByte1.ROM_VMIRROR;
}
if (crc == 0xc99ec059)
{ // VS Raid on Bungeling Bay(J)
mapper = 99;
header.control1 &= 0xF6;
header.control1 |= (byte)EnumRomControlByte1.ROM_4SCREEN;
}
if (crc == 0xca85e56d)
{ // VS Mighty Bomb Jack(J)
mapper = 99;
header.control1 &= 0xF6;
header.control1 |= (byte)EnumRomControlByte1.ROM_4SCREEN;
}
if (crc == 0xeb2dba63 // VS TKO Boxing
|| crc == 0x9818f656 // VS TKO Boxing
|| crc == 0xed588f00 // VS Duck Hunt
|| crc == 0x8c0c2df5 // VS Top Gun
|| crc == 0x16d3f469 // VS Ninja Jajamaru Kun
|| crc == 0x8850924b // VS Tetris
|| crc == 0xcf36261e // VS Sky Kid
|| crc == 0xe1aa8214 // VS Star Luster
|| crc == 0xec461db9 // VS Pinball
|| crc == 0xe528f651 // VS Pinball (alt)
|| crc == 0x17ae56be // VS Freedom Force
|| crc == 0xe2c0a2be // VS Platoon
|| crc == 0xff5135a3 // VS Hogan's Alley
|| crc == 0x70901b25 // VS Slalom
|| crc == 0x0b65a917 // VS Mach Rider(Endurance Course)
|| crc == 0x8a6a9848 // VS Mach Rider(Endurance Course)(Alt)
|| crc == 0xae8063ef // VS Mach Rider(Japan, Fighting Course)
|| crc == 0xcc2c4b5d // VS Golf
|| crc == 0xa93a5aee // VS Stroke and Match Golf
|| crc == 0x86167220 // VS Lady Golf
|| crc == 0xffbef374 // VS Castlevania
|| crc == 0x135adf7c // VS Atari RBI Baseball
|| crc == 0xd5d7eac4 // VS Dr. Mario
|| crc == 0x46914e3e // VS Soccer
|| crc == 0x70433f2c // VS Battle City
|| crc == 0x8d15a6e6 // VS bad .nes
|| crc == 0x1e438d52 // VS Goonies
|| crc == 0xcbe85490 // VS Excitebike
|| crc == 0x29155e0c // VS Excitebike (alt)
|| crc == 0x07138c06 // VS Clu Clu Land
|| crc == 0x43a357ef // VS Ice Climber
|| crc == 0x737dd1bf // VS Super Mario Bros
|| crc == 0x4bf3972d // VS Super Mario Bros
|| crc == 0x8b60cc58 // VS Super Mario Bros
|| crc == 0x8192c804 // VS Super Mario Bros
|| crc == 0xd99a2087 // VS Gradius
|| crc == 0xf9d3b0a3 // VS Super Xevious
|| crc == 0x9924980a // VS Super Xevious
|| crc == 0x66bb838f // VS Super Xevious
|| crc == 0xc99ec059 // VS Raid on Bungeling Bay(J)
|| crc == 0xca85e56d)
{ // VS Mighty Bomb Jack(J)
header.control2 |= (byte)EnumRomControlByte2.ROM_VSUNISYSTEM;
}
if (mapper == 99 || mapper == 151)
{
header.control2 |= (byte)EnumRomControlByte2.ROM_VSUNISYSTEM;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 953873ef00535544abd9591708c8e7a5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -94,7 +94,6 @@ namespace VirtualNes.Core
pad = new PAD(this); pad = new PAD(this);
Debuger.Log("Loading ROM Image..."); Debuger.Log("Loading ROM Image...");
rom = new ROM(fname); rom = new ROM(fname);
} }
catch (Exception ex) catch (Exception ex)

View File

@ -1,4 +1,5 @@
using System; using Codice.CM.Client.Differences;
using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using VirtualNes.Core.Debug; using VirtualNes.Core.Debug;
@ -8,6 +9,7 @@ namespace VirtualNes.Core
public class ROM public class ROM
{ {
protected NESHEADER header; protected NESHEADER header;
protected NSFHEADER nsfheader;
protected string path; protected string path;
protected string name; protected string name;
protected string fullpath; protected string fullpath;
@ -21,8 +23,12 @@ namespace VirtualNes.Core
protected byte[] lpDisk; protected byte[] lpDisk;
protected ulong crc; protected ulong crc;
protected ulong crcall; protected ulong crcall;
protected ulong crcvrom;
protected int mapper; protected int mapper;
protected int diskno; protected int diskno;
protected ulong fdsmakerID;
protected ulong fdsgameID;
public ROM(string fname) public ROM(string fname)
{ {
Stream fp = null; Stream fp = null;
@ -46,7 +52,7 @@ namespace VirtualNes.Core
try try
{ {
fp = Supporter.OpenFile(fname); fp = Supporter.OpenRom(fname);
if (fp == null) if (fp == null)
{ {
throw new System.Exception($"Open Rom Failed:[{fname}]"); throw new System.Exception($"Open Rom Failed:[{fname}]");
@ -69,7 +75,7 @@ namespace VirtualNes.Core
throw new Exception($"rom file is not valid:[{fname}]"); throw new Exception($"rom file is not valid:[{fname}]");
ulong PRGoffset, CHRoffset; ulong PRGoffset, CHRoffset;
long PRGsize, CHRsize; long PRGsize = 0, CHRsize = 0;
var romType = header.GetRomType(); var romType = header.GetRomType();
if (romType == EnumRomType.NES) if (romType == EnumRomType.NES)
@ -87,7 +93,6 @@ namespace VirtualNes.Core
if (PRGsize <= 0 || (PRGsize + CHRsize) > FileSize) if (PRGsize <= 0 || (PRGsize + CHRsize) > FileSize)
{ {
// NES僿僢僟偑堎忢偱偡
throw new Exception($"Invalid NesHeader:[{fname}]"); throw new Exception($"Invalid NesHeader:[{fname}]");
} }
@ -164,7 +169,7 @@ namespace VirtualNes.Core
lpPRG[3] = 0x1A; lpPRG[3] = 0x1A;
lpPRG[4] = (byte)diskno; lpPRG[4] = (byte)diskno;
fp = Supporter.OpenFile("DISKSYS.ROM"); fp = Supporter.OpenFile_DISKSYS();
if (fp == null) if (fp == null)
{ {
throw new Exception($"Not found DISKSYS.ROM for [{fname}]"); throw new Exception($"Not found DISKSYS.ROM for [{fname}]");
@ -183,13 +188,97 @@ namespace VirtualNes.Core
lpDiskBios = new byte[8 * 1024]; lpDiskBios = new byte[8 * 1024];
if (bios[0] == 'N' && bios[1] == 'E' && bios[2] == 'S' && bios[3] == 0x1A) if (bios[0] == 'N' && bios[1] == 'E' && bios[2] == 'S' && bios[3] == 0x1A)
{ {
Array.Copy(bios, 0x6010, lpDiskBios, 0, lpDiskBios.Length);
} }
} else
}
catch
{ {
Array.Copy(bios, lpDiskBios, lpDiskBios.Length);
}
bios = null;
}
else if (romType == EnumRomType.NSF)
{
bNSF = true;
header = NESHEADER.GetDefault();
nsfheader = NSFHEADER.GetDefault();
PRGsize = FileSize - NSFHEADER.SizeOf();
Debuger.Log($"PRGSIZE:{PRGsize}");
PRGsize = (PRGsize + 0x0FFF) & ~0x0FFF;
Debuger.Log($"PRGSIZE:{PRGsize}");
lpPRG = new byte[PRGsize];
Array.Copy(temp, NSFHEADER.SizeOf(), lpPRG, 0, FileSize - NSFHEADER.SizeOf());
NSF_PAGE_SIZE = (int)(PRGsize >> 12);
Debuger.Log($"PAGESIZE:{NSF_PAGE_SIZE}");
}
else
{
throw new Exception($"Unsupport format:[{fname}]");
}
Supporter.GetFilePathInfo(fname, out fullpath, out path);
if (!bNSF)
{
mapper = (header.control1 >> 4) | (header.control2 & 0xF0);
crc = crcall = crcvrom = 0;
if (mapper != 20)
{
Span<byte> sTemp = temp;
if (IsTRAINER())
{
crcall = CRC.CrcRev((int)(512 + PRGsize + CHRsize), sTemp.Slice(NESHEADER.SizeOf()));
crc = CRC.CrcRev((int)(512 + PRGsize), sTemp);
if (CHRsize > 0)
crcvrom = CRC.CrcRev((int)CHRsize, sTemp.Slice((int)(PRGsize + 512 + NESHEADER.SizeOf())));
}
else
{
crcall = CRC.CrcRev((int)(PRGsize + CHRsize), sTemp.Slice(NESHEADER.SizeOf()));
crc = CRC.CrcRev((int)(PRGsize), sTemp.Slice(NESHEADER.SizeOf()));
if (CHRsize > 0)
crcvrom = CRC.CrcRev((int)CHRsize, sTemp.Slice((int)(PRGsize + NESHEADER.SizeOf())));
}
FileNameCheck(fname);
RomPatch.DoPatch(ref crc, ref lpPRG, ref lpCHR, ref mapper, ref header);
fdsmakerID = fdsgameID = 0;
}
else //mapper==20
{
crc = crcall = crcvrom = 0;
fdsmakerID = lpPRG[0x1F];
fdsgameID = (ulong)((lpPRG[0x20] << 24) | (lpPRG[0x21] << 16) | (lpPRG[0x22] << 8) | (lpPRG[0x23] << 0));
}
}
else //NSF
{
mapper = 0x0100; // Private mapper
crc = crcall = crcvrom = 0;
fdsmakerID = fdsgameID = 0;
}
temp = null;
}
catch (Exception ex)
{
fp?.Dispose();
temp = null;
bios = null;
lpPRG = null;
lpCHR = null;
lpTrainer = null;
lpDiskBios = null;
lpDisk = null;
throw ex;
} }
} }
@ -197,98 +286,16 @@ namespace VirtualNes.Core
{ {
return (header.control1 & (byte)EnumRomControlByte1.ROM_TRAINER) > 0; return (header.control1 & (byte)EnumRomControlByte1.ROM_TRAINER) > 0;
} }
}
public enum EnumRomControlByte1 : byte protected void FileNameCheck(string fname)
{ {
ROM_VMIRROR = 0x01, if (fname.Contains("(E)"))
ROM_SAVERAM = 0x02,
ROM_TRAINER = 0x04,
ROM_4SCREEN = 0x08,
}
public enum EnumRomType
{ {
InValid, bPAL = true;
NES, return;
/// <summary> Nintendo Disk System </summary>
FDS,
NSF
}
public struct NESHEADER
{
public byte[] ID;
public byte PRG_PAGE_SIZE;
public byte CHR_PAGE_SIZE;
public byte control1;
public byte control2;
public byte[] reserved;
public bool CheckValid()
{
return GetRomType() != EnumRomType.InValid;
}
public static int SizeOf()
{
return 16;
}
public EnumRomType GetRomType()
{
if (ID[0] == 'N' && ID[1] == 'E' && ID[2] == 'S' && ID[3] == 0x1A)
return EnumRomType.NES;
if (ID[0] == 'F' && ID[1] == 'D' && ID[2] == 'S' && ID[3] == 0x1A)
return EnumRomType.FDS;
if (ID[0] == 'N' && ID[1] == 'E' && ID[2] == 'S' && ID[3] == 'M')
return EnumRomType.NSF;
return EnumRomType.InValid;
}
public static NESHEADER GetDefault()
{
var res = new NESHEADER();
res.ID = new byte[4];
res.reserved = new byte[8];
return res;
}
public static NESHEADER Read(Span<byte> data)
{
var res = new NESHEADER();
res.ID = data.Slice(0, 4).ToArray();
res.PRG_PAGE_SIZE = data[4];
res.CHR_PAGE_SIZE = data[5];
res.control1 = data[6];
res.control2 = data[7];
res.reserved = data.Slice(8, 8).ToArray();
return res;
}
public byte[] DataToBytes()
{
byte[] res = new byte[16];
res[0] = ID[0];
res[1] = ID[1];
res[2] = ID[2];
res[3] = ID[3];
res[4] = PRG_PAGE_SIZE;
res[5] = CHR_PAGE_SIZE;
res[6] = control1;
res[7] = control2;
res[8] = reserved[0];
res[9] = reserved[1];
res[10] = reserved[2];
res[11] = reserved[3];
res[12] = reserved[4];
res[13] = reserved[5];
res[14] = reserved[6];
res[15] = reserved[7];
return res;
} }
} }
}
} }

View File

@ -13,14 +13,27 @@ namespace VirtualNes.Core
s_support = supporter; s_support = supporter;
} }
public static Stream OpenFile(string fname) public static Stream OpenRom(string fname)
{ {
return s_support.OpenFile(fname); return s_support.OpenRom(fname);
} }
public static void GetFilePathInfo(string fname, out string fullPath, out string directPath)
{
s_support.GetRomPathInfo(fname, out fullPath, out directPath);
}
public static Stream OpenFile_DISKSYS()
{
return s_support.OpenFile_DISKSYS();
}
} }
public interface ISupporterImpl public interface ISupporterImpl
{ {
Stream OpenFile(string fname); Stream OpenRom(string fname);
void GetRomPathInfo(string fname, out string fullPath, out string directPath);
Stream OpenFile_DISKSYS();
} }
} }