Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/hakchi2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/Apps
diff options
context:
space:
mode:
authorAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2017-10-09 15:04:08 +0300
committerAlexey 'Cluster' Avdyukhin <clusterrr@clusterrr.com>2017-10-09 15:15:07 +0300
commitd976ea7e4279db18c52feb5c0007ec1459827be9 (patch)
treef81505f0198c0321b61245e09034221b29629dcd /Apps
parent4b3a7c567d13bad64a55d70b4b7854a51a520be3 (diff)
Typo
Diffstat (limited to 'Apps')
-rw-r--r--Apps/NesMiniApplication.cs5
-rw-r--r--Apps/SnesGame.cs234
2 files changed, 195 insertions, 44 deletions
diff --git a/Apps/NesMiniApplication.cs b/Apps/NesMiniApplication.cs
index 24d953f4..f2ad4c1b 100644
--- a/Apps/NesMiniApplication.cs
+++ b/Apps/NesMiniApplication.cs
@@ -21,6 +21,7 @@ namespace com.clusterrr.hakchi_gui
public static Image DefaultCover = Resources.blank_app;
public static Form ParentForm;
public static bool? NeedPatch;
+ public static bool? Need3rdPartyEmulator;
public static bool? NeedAutoDownloadCover;
public static string GamesDirectory
@@ -462,10 +463,10 @@ namespace com.clusterrr.hakchi_gui
if (patches.Length > 0)
patch = patches[0];
}
- var patchesPath = System.IO.Path.Combine(patchesDirectory, System.IO.Path.GetFileNameWithoutExtension(inputFileName) + ".ips");
+ var patchesPath = Path.Combine(patchesDirectory, Path.GetFileNameWithoutExtension(inputFileName) + ".ips");
if (File.Exists(patchesPath))
patch = patchesPath;
- patchesPath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(inputFileName), System.IO.Path.GetFileNameWithoutExtension(inputFileName) + ".ips");
+ patchesPath = Path.Combine(Path.GetDirectoryName(inputFileName), System.IO.Path.GetFileNameWithoutExtension(inputFileName) + ".ips");
if (File.Exists(patchesPath))
patch = patchesPath;
}
diff --git a/Apps/SnesGame.cs b/Apps/SnesGame.cs
index e63e4c9c..0a52d7ca 100644
--- a/Apps/SnesGame.cs
+++ b/Apps/SnesGame.cs
@@ -20,11 +20,12 @@ namespace com.clusterrr.hakchi_gui
static List<byte> SfxTypes = new List<byte>() { 0x13, 0x14, 0x15, 0x1a };
static List<byte> Dsp1Types = new List<byte>() { 0x03, 0x05 };
static List<byte> SA1Types = new List<byte>() { 0x34, 0x35 };
+ // Known presets
static Dictionary<string, ushort> knownPresets = new Dictionary<string, ushort>()
{
{ "SUPER MARIOWORLD", 0x1011 },
{ "F-ZERO", 0x1018 },
- { "THE LEGEND OF ZELDA", 0x101D },
+ //{ "THE LEGEND OF ZELDA", 0x101D }, // Removed to use hacks and translations
{ "SUPER MARIO KART", 0x10BD },
{ "Super Metroid", 0x1040 },
{ "EARTH BOUND", 0x1070 },
@@ -43,10 +44,10 @@ namespace com.clusterrr.hakchi_gui
{ "STAR FOX", 0x1242 },
{ "YOSHI'S ISLAND", 0x123D },
{ "STARFOX2", 0x123C },
- { "ZELDANODENSETSU", 0x101F },
+ //{ "ZELDANODENSETSU", 0x101F }, // Removed to use hacks and translations
{ "SHVC FIREEMBLEM", 0x102B },
{ "SUPER DONKEY KONG", 0x1023 },
- //{ "Super Street Fighter", 0x1056 },
+ //{ "Super Street Fighter", 0x1056 }, // Invalid
{ "ROCKMAN X", 0x110A },
{ "CHOHMAKAIMURA", 0x1004 },
{ "SeikenDensetsu 2", 0x10B2 },
@@ -69,6 +70,78 @@ namespace com.clusterrr.hakchi_gui
{ "MEGAMAN X3", 0x113D },
{ "Breath of Fire", 0x1144 },
};
+ // Known LoRom games
+ static List<string> gamesLoRom = new List<string>()
+ {
+ };
+ // Known HiRom games
+ static List<string> gamesHiRom = new List<string>()
+ {
+ };
+ static List<string> problemGames = new List<string>()
+ {
+ { "ActRaiser-2 USA" }, // ActRaiser 2 (U) [!].smc
+ { "ALIEN vs. PREDATOR" }, // Alien vs. Predator (U).smc
+ { "ASTERIX" }, // Asterix (E) [!].smc
+ { "BATMAN--REVENGE JOKER" }, // Batman - Revenge of the Joker (U).smc
+ { "???????S???????????" }, // Bishoujo Senshi Sailor Moon S - Jougai Rantou! Shuyaku Soudatsusen (J).smc
+ { "CHAMPIONSHIP POOL" }, // Championship Pool (U).smc
+ { "ClayFighter 2" }, // Clay Fighter 2 - Judgment Clay (U) [!].smc
+ { "CLOCK TOWER SFX" }, // Clock Tower (J).smc
+ { "COOL WORLD" }, // Cool World (U) [!].smc
+ { "CRYSTAL BEANS" }, // Crystal Beans From Dungeon Explorer (J).smc
+ { "CYBER KNIGHT 2" }, // Cyber Knight II - Chikyuu Teikoku no Yabou (J).smc
+ { "ASCII DARK LAW" }, // Dark Law - Meaning of Death (J).smc
+ { "DIRT TRAX FX" }, // Dirt Trax FX (U) [!].smc
+ { "DBZ HYPER DIMENSION" }, // Dragon Ball Z - Hyper Dimension (F).smc
+ { "DRAGON BALL Z HD" }, // Dragon Ball Z - Hyper Dimension (J) [!].smc
+ { "DRAGONBALL Z 2" }, // Dragon Ball Z - La Legende Saien (F).smc
+ { "SFX DRAGONBALLZ2" }, // Dragon Ball Z - Super Butouden (F).smc
+ { "SFX SUPERBUTOUDEN2" }, // Dragon Ball Z - Super Butouden 2 (J) (V1.0).smc
+ { "DUNGEON MASTER" }, // Dungeon Master (U).smc
+ { "EARTHWORM JIM 2" }, // Earthworm Jim 2 (U) [!].smc
+ { "F1 WORLD CHAMP EDTION" }, // F1 World Championship Edition (E).smc
+ { "FACEBALL 2000" }, // Faceball 2000 (U) [!].smc
+ { "THE FIREMEN PAL" }, // Firemen, The (E).smc
+ { "HAMMERIN' HARRY (JPN)" }, // Ganbare Daiku no Gensan (J) [!].smc
+ { "HARMELUNNOBAIOLINHIKI" }, // Hamelin no Violin Hiki (J).smc
+ { "HOME ALONE" }, // Home Alone (U).smc
+ { "HUMAN GRANDPRIX" }, // Human Grand Prix (J).smc
+ { "HUMAN GRANDPRIX 3" }, // Human Grand Prix III - F1 Triple Battle (J).smc
+ { "ILLUSION OF GAIA USA" }, // Illusion of Gaia (U) [!].smc
+ { "ILLUSION OF TIME ENG" }, // Illusion of Time (E) [!].smc
+ { "JumpinDerby" }, // Jumpin' Derby (J).smc
+ { "KRUSTYS SUPERFUNHOUSE" }, // Krusty's Super Fun House (U) (V1.1).smc
+ { "Mario's Time Machine" }, // Mario's Time Machine (U) [!].smc
+ { "MARKOS MAGIC FOOTBALL" }, // Marko's Magic Football (E).smc
+ { "POWER RANGERS FIGHT" }, // Mighty Morphin Power Rangers - The Fighting Edition (U).smc
+ { "MOMOTETSU HAPPY" }, // Momotarou Dentetsu Happy (J) [!].smc
+ { "NHL HOCKEY 1998" }, // NHL '98 (U).smc
+ { "RENDERING RANGER R2" }, // Rendering Ranger R2 (J).smc
+ { "ROBOTREK 1 USA" }, // Robotrek (U) [!].smc
+ { "ROCK N' ROLL RACING" }, // Rock N' Roll Racing (U) [!].smc
+ { "ROMANCING SAGA3" }, // Romancing SaGa 3 (J) (V1.1).smc
+ { "SD??????GX" }, // SD Gundam GX (J) [!].smc
+ { "SECRET OF EVERMORE" }, // Secret of Evermore (U) [!].smc
+ { "Secret of MANA" }, // Secret of Mana (U) [!].smc
+ { "SIM CITY 2000" }, // Sim City 2000 (U).smc
+ { "SMASH TENNIS" }, // Smash Tennis (E) [!].smc
+ { "Star Ocean" }, // Star Ocean (J) [!].smc
+ { "STREET FIGHTER ALPHA2" }, // Street Fighter Alpha 2 (U) [!].smc
+ { "SUPER BASES LOADED 2" }, // Super Bases Loaded 2 (U).smc
+ { "PANIC BOMBER WORLD" }, // Super Bomberman - Panic Bomber W (J).smc
+ { "TALES OF PHANTASIA" }, // Tales of Phantasia (J) [!].smc
+ { "TERRANIGMA P" }, // Terranigma (E) [!].smc
+ { "TOP GEAR 3000" }, // Top Gear 3000 (U) [!].smc
+ { "UNIRACERS" }, // Uniracers (U) [!].smc
+ { "WARIO'S WOODS" }, // Wario's Woods (U) [!].smc
+ { "WORLD CLASS RUGBY" }, // World Class Rugby (E) [!].smc
+ { "WORLD CUP STRIKER" }, // World Cup Striker (E) (M3) [!].smc
+ { "WORLD MASTERS GOLF" }, // World Masters Golf (E).smc
+ { "WWF SUPER WRESTLEMANI" }, // WWF Super WrestleMania (U) [!].smc
+ { "WRESTLEMANIA" }, // WWF WrestleMania - The Arcade Game (U) [!].smc
+ };
+
private static Dictionary<uint, CachedGameInfo> gameInfoCache = null;
public override string GoogleSuffix
@@ -105,8 +178,31 @@ namespace com.clusterrr.hakchi_gui
if (ext.ToLower() != ".sfrom") // Need to patch for canoe
{
Debug.WriteLine($"Trying to convert {inputFileName}");
- MakeSfrom(ref rawRomData, ref saveCount);
+ bool problemGame = false;
+ MakeSfrom(ref rawRomData, ref saveCount, out problemGame);
outputFileName = Path.GetFileNameWithoutExtension(outputFileName) + ".sfrom";
+ // Using 3rd party emulator for this ROM
+ if (problemGame && Need3rdPartyEmulator != true)
+ {
+ if (Need3rdPartyEmulator != false)
+ {
+ var r = WorkerForm.MessageBoxFromThread(ParentForm,
+ string.Format(Resources.Need3rdPartyEmulator, Path.GetFileName(inputFileName)),
+ Resources.AreYouSure,
+ MessageBoxButtons.AbortRetryIgnore,
+ MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2, true);
+ if (r == DialogResult.Abort)
+ Need3rdPartyEmulator = true;
+ if (r == DialogResult.Ignore)
+ problemGame = false;
+ }
+ else problemGame = false;
+ }
+ if (problemGame)
+ {
+ application = "/bin/snes";
+ args = "";
+ }
}
}
else
@@ -117,51 +213,78 @@ namespace com.clusterrr.hakchi_gui
return true;
}
- private static void MakeSfrom(ref byte[] rawRomData, ref byte saveCount)
+ private static SnesRomHeader GetCorrectHeader(byte[] rawRomData, out SnesRomType romType, out string gameTitle)
{
var romHeaderLoRom = SnesRomHeader.Read(rawRomData, 0x7FC0);
var romHeaderHiRom = SnesRomHeader.Read(rawRomData, 0xFFC0);
- SnesRomHeader romHeader;
- bool loRom = true;
- bool hiRom = true;
- if (romHeaderLoRom.GameTitle.Length == 0)
- loRom = false;
- foreach (char c in romHeaderLoRom.GameTitle)
- if (c < 31 || c > 127) loRom = false;
- if (romHeaderHiRom.GameTitle.Length == 0)
- hiRom = false;
- foreach (char c in romHeaderHiRom.GameTitle)
- if (c < 31 || c > 127) hiRom = false;
- SnesRomType romType;
- if (loRom && !hiRom)
- {
+ var titleLo = romHeaderLoRom.GameTitle;
+ var titleHi = romHeaderHiRom.GameTitle;
+
+ // Boring LoRom/HiRom detection...
+ if (((romHeaderLoRom.Checksum ^ 0xFFFF) == romHeaderLoRom.ChecksumComplement) &&
+ ((romHeaderHiRom.Checksum ^ 0xFFFF) != romHeaderHiRom.ChecksumComplement))
romType = SnesRomType.LoRom;
- romHeader = romHeaderLoRom;
- }
- else if (!loRom && hiRom)
- {
+ else if (((romHeaderLoRom.Checksum ^ 0xFFFF) != romHeaderLoRom.ChecksumComplement) &&
+ ((romHeaderHiRom.Checksum ^ 0xFFFF) == romHeaderHiRom.ChecksumComplement))
romType = SnesRomType.HiRom;
- romHeader = romHeaderHiRom;
- }
- else if (((romHeaderLoRom.RomMakeup & 1) == 0) && ((romHeaderHiRom.RomMakeup & 1) == 0))
- {
+ else if (titleLo.Length != 0 && titleHi.Length == 0)
romType = SnesRomType.LoRom;
- romHeader = romHeaderLoRom;
+ else if (titleLo.Length == 0 && titleHi.Length != 0)
+ romType = SnesRomType.HiRom;
+ else if ((titleLo == titleHi) && ((romHeaderLoRom.RomMakeup & 1) == 0))
+ romType = SnesRomType.LoRom;
+ else if ((titleLo == titleHi) && ((romHeaderHiRom.RomMakeup & 1) == 1))
+ romType = SnesRomType.HiRom;
+ else if (gamesLoRom.Contains(titleLo))
+ romType = SnesRomType.LoRom;
+ else if (gamesHiRom.Contains(titleHi))
+ romType = SnesRomType.HiRom;
+ else
+ {
+ bool loRom = true;
+ bool hiRom = true;
+ foreach (char c in titleLo)
+ if (c < 31 || c > 127) loRom = false;
+ foreach (char c in titleHi)
+ if (c < 31 || c > 127) hiRom = false;
+ if (loRom && !hiRom)
+ romType = SnesRomType.LoRom;
+ else if (!loRom && hiRom)
+ romType = SnesRomType.HiRom;
+ else
+ {
+ Debug.WriteLine("Can't detect ROM type");
+ throw new Exception("can't detect ROM type, seems like ROM is corrupted");
+ }
}
- else if (((romHeaderLoRom.RomMakeup & 1) == 1) && ((romHeaderHiRom.RomMakeup & 1) == 1))
+
+ SnesRomHeader romHeader;
+ if (romType == SnesRomType.LoRom)
{
- romType = SnesRomType.HiRom;
- romHeader = romHeaderHiRom;
+ romHeader = romHeaderLoRom;
+ gameTitle = titleLo;
}
else
{
- // WTF is it?
- romType = SnesRomType.HiRom;
romHeader = romHeaderHiRom;
+ gameTitle = titleHi;
}
+ return romHeader;
+ }
+
+ private static void MakeSfrom(ref byte[] rawRomData, ref byte saveCount, out bool problemGame)
+ {
+ SnesRomType romType;
+ string gameTitle;
+ SnesRomHeader romHeader = GetCorrectHeader(rawRomData, out romType, out gameTitle);
+
+ if (romType == SnesRomType.LoRom)
+ rawRomData[0x7FD9] = 0x01; // Force NTSC
+ else
+ rawRomData[0xFFD9] = 0x01; // Force NTSC
- string gameTitle = romHeader.GameTitle.Trim();
Debug.WriteLine($"Game title: {gameTitle}");
+ Debug.WriteLine($"ROM type: {romType}");
ushort presetId = 0; // 0x1011;
ushort chip = 0;
if (SfxTypes.Contains(romHeader.RomType)) // Super FX chip
@@ -181,7 +304,8 @@ namespace com.clusterrr.hakchi_gui
Debug.WriteLine($"SA1 chip detected");
presetId = 0x109C; // ID from Super Mario RPG, SA1
}
- } else
+ }
+ else
{
Debug.WriteLine($"We have preset for this game");
}
@@ -198,6 +322,10 @@ namespace com.clusterrr.hakchi_gui
if (romHeader.SramSize > 0)
saveCount = 3;
+ else
+ saveCount = 0;
+
+ problemGame = problemGames.Contains(gameTitle);
rawRomData = result;
}
@@ -256,8 +384,8 @@ namespace com.clusterrr.hakchi_gui
[StructLayout(LayoutKind.Sequential)]
private struct SnesRomHeader
{
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
- public string GameTitle;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 21)]
+ public byte[] GameTitleArr;
[MarshalAs(UnmanagedType.U1)] // $xFD5
public byte RomMakeup;
[MarshalAs(UnmanagedType.U1)] // $xFD6
@@ -266,8 +394,10 @@ namespace com.clusterrr.hakchi_gui
public byte RomSize;
[MarshalAs(UnmanagedType.U1)] // $xFD8
public byte SramSize;
- [MarshalAs(UnmanagedType.U2)] // $xFD9
- public ushort LicenseId;
+ [MarshalAs(UnmanagedType.U1)] // $xFD9
+ public byte Country;
+ [MarshalAs(UnmanagedType.U1)] // $xFDA
+ public byte License;
[MarshalAs(UnmanagedType.U1)] // $xFDB
public byte Version;
[MarshalAs(UnmanagedType.U2)] // $xFDC
@@ -275,6 +405,23 @@ namespace com.clusterrr.hakchi_gui
[MarshalAs(UnmanagedType.U2)] // $xFDE
public ushort Checksum;
+ public string GameTitle
+ {
+ get
+ {
+ var data = new List<byte>(GameTitleArr);
+ if (data.Contains(0))
+ return "";
+ if (data.Contains(0xFF))
+ return "";
+ if (data[0] == 0x20)
+ return "";
+ while (data.Count > 0 && data[data.Count - 1] == 0x20)
+ data.RemoveAt(data.Count - 1);
+ return Encoding.ASCII.GetString(data.ToArray());
+ }
+ }
+
public byte[] GetBytes()
{
int size = Marshal.SizeOf(this);
@@ -518,13 +665,16 @@ namespace com.clusterrr.hakchi_gui
CachedGameInfo gameinfo;
if (gameInfoCache != null && gameInfoCache.TryGetValue(crc32, out gameinfo))
{
- Name = gameinfo.Name;
+ if (!string.IsNullOrEmpty(gameinfo.Name))
+ Name = gameinfo.Name;
Players = gameinfo.Players;
Simultaneous = gameinfo.Simultaneous;
- ReleaseDate = gameinfo.ReleaseDate;
+ if (!string.IsNullOrEmpty(gameinfo.ReleaseDate))
+ ReleaseDate = gameinfo.ReleaseDate;
if (ReleaseDate.Length == 4) ReleaseDate += "-01";
if (ReleaseDate.Length == 7) ReleaseDate += "-01";
- Publisher = gameinfo.Publisher.ToUpper();
+ if (!string.IsNullOrEmpty(gameinfo.Publisher))
+ Publisher = gameinfo.Publisher.ToUpper();
/*
if (!string.IsNullOrEmpty(gameinfo.CoverUrl))