Browse Source
* Mostly complete header coverage, albeit with no real display options. * Does not currently read the publisher data.master
Ian Burgmyer
4 years ago
commit
d02496d44b
11 changed files with 655 additions and 0 deletions
@ -0,0 +1,261 @@ |
|||||||
|
## Ignore Visual Studio temporary files, build results, and |
||||||
|
## files generated by popular Visual Studio add-ons. |
||||||
|
|
||||||
|
# User-specific files |
||||||
|
*.suo |
||||||
|
*.user |
||||||
|
*.userosscache |
||||||
|
*.sln.docstates |
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio) |
||||||
|
*.userprefs |
||||||
|
|
||||||
|
# Build results |
||||||
|
[Dd]ebug/ |
||||||
|
[Dd]ebugPublic/ |
||||||
|
[Rr]elease/ |
||||||
|
[Rr]eleases/ |
||||||
|
x64/ |
||||||
|
x86/ |
||||||
|
bld/ |
||||||
|
[Bb]in/ |
||||||
|
[Oo]bj/ |
||||||
|
[Ll]og/ |
||||||
|
|
||||||
|
# Visual Studio 2015 cache/options directory |
||||||
|
.vs/ |
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot |
||||||
|
#wwwroot/ |
||||||
|
|
||||||
|
# MSTest test Results |
||||||
|
[Tt]est[Rr]esult*/ |
||||||
|
[Bb]uild[Ll]og.* |
||||||
|
|
||||||
|
# NUNIT |
||||||
|
*.VisualState.xml |
||||||
|
TestResult.xml |
||||||
|
|
||||||
|
# Build Results of an ATL Project |
||||||
|
[Dd]ebugPS/ |
||||||
|
[Rr]eleasePS/ |
||||||
|
dlldata.c |
||||||
|
|
||||||
|
# DNX |
||||||
|
project.lock.json |
||||||
|
project.fragment.lock.json |
||||||
|
artifacts/ |
||||||
|
|
||||||
|
*_i.c |
||||||
|
*_p.c |
||||||
|
*_i.h |
||||||
|
*.ilk |
||||||
|
*.meta |
||||||
|
*.obj |
||||||
|
*.pch |
||||||
|
*.pdb |
||||||
|
*.pgc |
||||||
|
*.pgd |
||||||
|
*.rsp |
||||||
|
*.sbr |
||||||
|
*.tlb |
||||||
|
*.tli |
||||||
|
*.tlh |
||||||
|
*.tmp |
||||||
|
*.tmp_proj |
||||||
|
*.log |
||||||
|
*.vspscc |
||||||
|
*.vssscc |
||||||
|
.builds |
||||||
|
*.pidb |
||||||
|
*.svclog |
||||||
|
*.scc |
||||||
|
|
||||||
|
# Chutzpah Test files |
||||||
|
_Chutzpah* |
||||||
|
|
||||||
|
# Visual C++ cache files |
||||||
|
ipch/ |
||||||
|
*.aps |
||||||
|
*.ncb |
||||||
|
*.opendb |
||||||
|
*.opensdf |
||||||
|
*.sdf |
||||||
|
*.cachefile |
||||||
|
*.VC.db |
||||||
|
*.VC.VC.opendb |
||||||
|
|
||||||
|
# Visual Studio profiler |
||||||
|
*.psess |
||||||
|
*.vsp |
||||||
|
*.vspx |
||||||
|
*.sap |
||||||
|
|
||||||
|
# TFS 2012 Local Workspace |
||||||
|
$tf/ |
||||||
|
|
||||||
|
# Guidance Automation Toolkit |
||||||
|
*.gpState |
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in |
||||||
|
_ReSharper*/ |
||||||
|
*.[Rr]e[Ss]harper |
||||||
|
*.DotSettings.user |
||||||
|
|
||||||
|
# JustCode is a .NET coding add-in |
||||||
|
.JustCode |
||||||
|
|
||||||
|
# TeamCity is a build add-in |
||||||
|
_TeamCity* |
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool |
||||||
|
*.dotCover |
||||||
|
|
||||||
|
# NCrunch |
||||||
|
_NCrunch_* |
||||||
|
.*crunch*.local.xml |
||||||
|
nCrunchTemp_* |
||||||
|
|
||||||
|
# MightyMoose |
||||||
|
*.mm.* |
||||||
|
AutoTest.Net/ |
||||||
|
|
||||||
|
# Web workbench (sass) |
||||||
|
.sass-cache/ |
||||||
|
|
||||||
|
# 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/ |
||||||
|
|
||||||
|
# Publish Web Output |
||||||
|
*.[Pp]ublish.xml |
||||||
|
*.azurePubxml |
||||||
|
# TODO: Comment the next line if you want to checkin your web deploy settings |
||||||
|
# but database connection strings (with potential passwords) will be unencrypted |
||||||
|
#*.pubxml |
||||||
|
*.publishproj |
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to |
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained |
||||||
|
# in these scripts will be unencrypted |
||||||
|
PublishScripts/ |
||||||
|
|
||||||
|
# NuGet Packages |
||||||
|
*.nupkg |
||||||
|
# The packages folder can be ignored because of Package Restore |
||||||
|
**/packages/* |
||||||
|
# except build/, which is used as an MSBuild target. |
||||||
|
!**/packages/build/ |
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed |
||||||
|
#!**/packages/repositories.config |
||||||
|
# NuGet v3's project.json files produces more ignoreable files |
||||||
|
*.nuget.props |
||||||
|
*.nuget.targets |
||||||
|
|
||||||
|
# Microsoft Azure Build Output |
||||||
|
csx/ |
||||||
|
*.build.csdef |
||||||
|
|
||||||
|
# Microsoft Azure Emulator |
||||||
|
ecf/ |
||||||
|
rcf/ |
||||||
|
|
||||||
|
# Windows Store app package directories and files |
||||||
|
AppPackages/ |
||||||
|
BundleArtifacts/ |
||||||
|
Package.StoreAssociation.xml |
||||||
|
_pkginfo.txt |
||||||
|
|
||||||
|
# Visual Studio cache files |
||||||
|
# files ending in .cache can be ignored |
||||||
|
*.[Cc]ache |
||||||
|
# but keep track of directories ending in .cache |
||||||
|
!*.[Cc]ache/ |
||||||
|
|
||||||
|
# Others |
||||||
|
ClientBin/ |
||||||
|
~$* |
||||||
|
*~ |
||||||
|
*.dbmdl |
||||||
|
*.dbproj.schemaview |
||||||
|
*.jfm |
||||||
|
*.pfx |
||||||
|
*.publishsettings |
||||||
|
node_modules/ |
||||||
|
orleans.codegen.cs |
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components |
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) |
||||||
|
#bower_components/ |
||||||
|
|
||||||
|
# RIA/Silverlight projects |
||||||
|
Generated_Code/ |
||||||
|
|
||||||
|
# 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 |
||||||
|
UpgradeLog*.htm |
||||||
|
|
||||||
|
# SQL Server files |
||||||
|
*.mdf |
||||||
|
*.ldf |
||||||
|
|
||||||
|
# Business Intelligence projects |
||||||
|
*.rdl.data |
||||||
|
*.bim.layout |
||||||
|
*.bim_*.settings |
||||||
|
|
||||||
|
# Microsoft Fakes |
||||||
|
FakesAssemblies/ |
||||||
|
|
||||||
|
# GhostDoc plugin setting file |
||||||
|
*.GhostDoc.xml |
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio |
||||||
|
.ntvs_analysis.dat |
||||||
|
|
||||||
|
# Visual Studio 6 build log |
||||||
|
*.plg |
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file |
||||||
|
*.opt |
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output |
||||||
|
**/*.HTMLClient/GeneratedArtifacts |
||||||
|
**/*.DesktopClient/GeneratedArtifacts |
||||||
|
**/*.DesktopClient/ModelManifest.xml |
||||||
|
**/*.Server/GeneratedArtifacts |
||||||
|
**/*.Server/ModelManifest.xml |
||||||
|
_Pvt_Extensions |
||||||
|
|
||||||
|
# Paket dependency manager |
||||||
|
.paket/paket.exe |
||||||
|
paket-files/ |
||||||
|
|
||||||
|
# FAKE - F# Make |
||||||
|
.fake/ |
||||||
|
|
||||||
|
# JetBrains Rider |
||||||
|
.idea/ |
||||||
|
*.sln.iml |
||||||
|
|
||||||
|
# CodeRush |
||||||
|
.cr/ |
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS) |
||||||
|
__pycache__/ |
||||||
|
*.pyc |
@ -0,0 +1,16 @@ |
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00 |
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DMGHeader", "DMGHeader\DMGHeader.csproj", "{4FF16F68-6FAD-4924-935B-78322B35BF6C}" |
||||||
|
EndProject |
||||||
|
Global |
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
||||||
|
Debug|Any CPU = Debug|Any CPU |
||||||
|
Release|Any CPU = Release|Any CPU |
||||||
|
EndGlobalSection |
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
||||||
|
{4FF16F68-6FAD-4924-935B-78322B35BF6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
||||||
|
{4FF16F68-6FAD-4924-935B-78322B35BF6C}.Debug|Any CPU.Build.0 = Debug|Any CPU |
||||||
|
{4FF16F68-6FAD-4924-935B-78322B35BF6C}.Release|Any CPU.ActiveCfg = Release|Any CPU |
||||||
|
{4FF16F68-6FAD-4924-935B-78322B35BF6C}.Release|Any CPU.Build.0 = Release|Any CPU |
||||||
|
EndGlobalSection |
||||||
|
EndGlobal |
@ -0,0 +1,8 @@ |
|||||||
|
namespace DMGHeader { |
||||||
|
public enum CgbMode { |
||||||
|
Disabled, |
||||||
|
PaletteOnly, |
||||||
|
Enhanced, |
||||||
|
Required |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||||
|
|
||||||
|
<PropertyGroup> |
||||||
|
<OutputType>Exe</OutputType> |
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework> |
||||||
|
</PropertyGroup> |
||||||
|
|
||||||
|
</Project> |
@ -0,0 +1,7 @@ |
|||||||
|
namespace DMGHeader { |
||||||
|
public enum DestinationCode { |
||||||
|
Japanese, |
||||||
|
NonJapanese, |
||||||
|
Unknown |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,6 @@ |
|||||||
|
namespace DMGHeader { |
||||||
|
public class DmgEntryPoint { |
||||||
|
public JumpType Jump { get; set; } = JumpType.None; |
||||||
|
public int JumpAddress { get; set; } = -1; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,198 @@ |
|||||||
|
using System; |
||||||
|
using System.IO; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
|
||||||
|
namespace DMGHeader { |
||||||
|
public class DmgHeader { |
||||||
|
public DmgEntryPoint EntryPoint { get; set; } |
||||||
|
public bool ValidLogo { get; set; } |
||||||
|
public string Title { get; set; } |
||||||
|
public CgbMode CgbMode { get; set; } |
||||||
|
public bool SgbSupport { get; set; } |
||||||
|
public string CartridgeType { get; set; } |
||||||
|
public MemorySize RomSize { get; set; } |
||||||
|
public MemorySize ExternalRamSize { get; set; } |
||||||
|
public DestinationCode DestinationCode { get; set; } |
||||||
|
public byte MaskRomVersion { get; set; } |
||||||
|
public byte HeaderChecksum { get; set; } |
||||||
|
public bool ValidHeaderChecksum { get; set; } |
||||||
|
public UInt16 CartridgeChecksum { get; set; } |
||||||
|
|
||||||
|
private byte[] _validLogo = { |
||||||
|
0xCE, 0xED, 0x66, 0x66, 0xCC, 0x0D, 0x00, 0x0B, 0x03, 0x73, 0x00, 0x83, 0x00, 0x0C, 0x00, 0x0D, |
||||||
|
0x00, 0x08, 0x11, 0x1F, 0x88, 0x89, 0x00, 0x0E, 0xDC, 0xCC, 0x6E, 0xE6, 0xDD, 0xDD, 0xD9, 0x99, |
||||||
|
0xBB, 0xBB, 0x67, 0x63, 0x6E, 0x0E, 0xEC, 0xCC, 0xDD, 0xDC, 0x99, 0x9F, 0xBB, 0xB9, 0x33, 0x3E |
||||||
|
}; |
||||||
|
|
||||||
|
public DmgHeader(string filename) { |
||||||
|
using var fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read); |
||||||
|
using var br = new BinaryReader(fs); |
||||||
|
|
||||||
|
fs.Seek(0x100, SeekOrigin.Begin); |
||||||
|
EntryPoint = ReadEntryPoint(br.ReadBytes(4)); |
||||||
|
ValidLogo = ValidateLogo(br.ReadBytes(_validLogo.Length)); |
||||||
|
|
||||||
|
// See if the upper bit of the CGB flag is set to see how much of the title field to read. |
||||||
|
fs.Seek(0x143, SeekOrigin.Begin); |
||||||
|
var cgb = (br.ReadByte() & 0b10000000) != 0; |
||||||
|
fs.Seek(0x134, SeekOrigin.Begin); |
||||||
|
var titleLen = cgb ? 15 : 16; |
||||||
|
|
||||||
|
Title = ReadTitle(br.ReadBytes(titleLen)); |
||||||
|
CgbMode = cgb ? ReadCgbMode(br.ReadByte()) : CgbMode.Disabled; |
||||||
|
|
||||||
|
fs.Seek(0x146, SeekOrigin.Begin); |
||||||
|
SgbSupport = br.ReadByte() == 0x03; |
||||||
|
|
||||||
|
CartridgeType = ReadCartridgeType(br.ReadByte()); |
||||||
|
RomSize = ReadRomSize(br.ReadByte()); |
||||||
|
ExternalRamSize = ReadExternalRamSize(br.ReadByte()); |
||||||
|
DestinationCode = ReadDestinationCode(br.ReadByte()); |
||||||
|
|
||||||
|
fs.Seek(0x14C, SeekOrigin.Begin); |
||||||
|
MaskRomVersion = br.ReadByte(); |
||||||
|
|
||||||
|
HeaderChecksum = br.ReadByte(); |
||||||
|
fs.Seek(0x134, SeekOrigin.Begin); |
||||||
|
ValidHeaderChecksum = HeaderChecksum == CalculateHeaderChecksum(br.ReadBytes(0x19)); |
||||||
|
|
||||||
|
fs.Seek(0x14E, SeekOrigin.Begin); |
||||||
|
CartridgeChecksum = br.ReadUInt16(); |
||||||
|
} |
||||||
|
|
||||||
|
private byte CalculateHeaderChecksum(byte[] data) { |
||||||
|
byte x = 0; |
||||||
|
|
||||||
|
unchecked { |
||||||
|
x = data.Aggregate(x, (current, b) => (byte)(current - b - 1)); |
||||||
|
} |
||||||
|
|
||||||
|
return x; |
||||||
|
} |
||||||
|
|
||||||
|
private string ReadCartridgeType(byte type) { |
||||||
|
switch(type) { |
||||||
|
case 0x00: return "ROM ONLY"; |
||||||
|
case 0x01: return "MBC1"; |
||||||
|
case 0x02: return "MBC1+RAM"; |
||||||
|
case 0x03: return "MBC1+RAM+BATTERY"; |
||||||
|
case 0x05: return "MBC2"; |
||||||
|
case 0x06: return "MBC2+BATTERY"; |
||||||
|
case 0x08: return "ROM+RAM"; |
||||||
|
case 0x09: return "ROM+RAM+BATTERY"; |
||||||
|
case 0x0B: return "MMM01"; |
||||||
|
case 0x0C: return "MMM01+RAM"; |
||||||
|
case 0x0D: return "MMM01+RAM+BATTERY"; |
||||||
|
case 0x0F: return "MBC3+TIMER+BATTERY"; |
||||||
|
case 0x10: return "MBC3+TIMER+RAM+BATTERY"; |
||||||
|
case 0x11: return "MBC3"; |
||||||
|
case 0x12: return "MBC3+RAM"; |
||||||
|
case 0x13: return "MBC3+RAM+BATTERY"; |
||||||
|
case 0x19: return "MBC5"; |
||||||
|
case 0x1A: return "MBC5+RAM"; |
||||||
|
case 0x1B: return "MBC5+RAM+BATTERY"; |
||||||
|
case 0x1C: return "MBC5+RUMBLE"; |
||||||
|
case 0x1D: return "MBC5+RUMBLE+RAM"; |
||||||
|
case 0x1E: return "MBC5+RUMBLE+RAM+BATTERY"; |
||||||
|
case 0x20: return "MBC6"; |
||||||
|
case 0x22: return "MBC7+SENSOR+RUMBLE+RAM+BATTERY"; |
||||||
|
case 0xFC: return "POCKET CAMERA"; |
||||||
|
case 0xFD: return "BANDAI TAMA5"; |
||||||
|
case 0xFE: return "HuC3"; |
||||||
|
case 0xFF: return "HuC1+RAM+BATTERY"; |
||||||
|
default: return "Unknown"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private CgbMode ReadCgbMode(byte mode) { |
||||||
|
if((mode & 0b10000000) == 0) return CgbMode.Disabled; |
||||||
|
if((mode & 0b01000000) != 0) return CgbMode.Required; |
||||||
|
if((mode & 0b00001100) != 0) return CgbMode.PaletteOnly; |
||||||
|
return CgbMode.Enhanced; |
||||||
|
} |
||||||
|
|
||||||
|
private DestinationCode ReadDestinationCode(byte data) { |
||||||
|
switch(data) { |
||||||
|
case 0x00: return DestinationCode.Japanese; |
||||||
|
case 0x01: return DestinationCode.NonJapanese; |
||||||
|
default: return DestinationCode.Unknown; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private DmgEntryPoint ReadEntryPoint(byte[] data) { |
||||||
|
var entry = new DmgEntryPoint(); |
||||||
|
|
||||||
|
var i = 0; |
||||||
|
|
||||||
|
for(; i < data.Length; i++) { |
||||||
|
if(data[i] != 0xC3 && data[i] != 0x18) continue; |
||||||
|
|
||||||
|
entry.Jump = data[i] == 0xC3 ? JumpType.Absolute : JumpType.Relative; |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
if(entry.Jump == JumpType.None) return entry; |
||||||
|
|
||||||
|
var addrLen = entry.Jump == JumpType.Absolute ? 2 : 1; |
||||||
|
var addr = data.Skip(++i).Take(addrLen).ToArray(); |
||||||
|
|
||||||
|
if(addr.Length != addrLen) return entry; |
||||||
|
|
||||||
|
if(entry.Jump == JumpType.Absolute) { |
||||||
|
// Stitch the values into a 16-bit value. |
||||||
|
entry.JumpAddress = addr[1] << 8 | addr[0]; |
||||||
|
} else { |
||||||
|
entry.JumpAddress = addr[0] + 0x100 + i; |
||||||
|
} |
||||||
|
|
||||||
|
return entry; |
||||||
|
} |
||||||
|
|
||||||
|
private MemorySize ReadExternalRamSize(byte data) { |
||||||
|
var size = new MemorySize(8); |
||||||
|
|
||||||
|
switch(data) { |
||||||
|
case 0x00: size.Size = 0; return size; |
||||||
|
case 0x01: size.Size = 2; return size; |
||||||
|
case 0x02: size.Size = 8; return size; |
||||||
|
case 0x03: size.Size = 32; return size; |
||||||
|
case 0x04: size.Size = 128; return size; |
||||||
|
case 0x05: size.Size = 64; return size; |
||||||
|
default: return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private MemorySize ReadRomSize(byte data) { |
||||||
|
var size = new MemorySize(16); |
||||||
|
|
||||||
|
switch(data) { |
||||||
|
case 0x00: size.Size = 32; return size; |
||||||
|
case 0x01: size.Size = 64; return size; |
||||||
|
case 0x02: size.Size = 128; return size; |
||||||
|
case 0x03: size.Size = 256; return size; |
||||||
|
case 0x04: size.Size = 512; return size; |
||||||
|
case 0x05: size.Size = 1024; return size; |
||||||
|
case 0x06: size.Size = 2048; return size; |
||||||
|
case 0x07: size.Size = 4096; return size; |
||||||
|
case 0x08: size.Size = 8192; return size; |
||||||
|
case 0x52: size.Size = 1152; return size; |
||||||
|
case 0x53: size.Size = 1280; return size; |
||||||
|
case 0x54: size.Size = 1536; return size; |
||||||
|
default: return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private string ReadTitle(byte[] data) { |
||||||
|
// Convert nulls to spaces. |
||||||
|
for(var i = 0; i < data.Length; i++) { |
||||||
|
if(data[i] == 0) data[i] = 32; |
||||||
|
} |
||||||
|
|
||||||
|
return Encoding.ASCII.GetString(data).Trim(); |
||||||
|
} |
||||||
|
|
||||||
|
private bool ValidateLogo(byte[] data) => |
||||||
|
data != null && data.Length == _validLogo.Length && data.SequenceEqual(_validLogo); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,7 @@ |
|||||||
|
namespace DMGHeader { |
||||||
|
public enum JumpType { |
||||||
|
None, |
||||||
|
Absolute, |
||||||
|
Relative |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
namespace DMGHeader { |
||||||
|
public class MemorySize { |
||||||
|
private int _size; |
||||||
|
|
||||||
|
public int Banks { get; private set; } |
||||||
|
|
||||||
|
public int BankSize { get; } |
||||||
|
|
||||||
|
public int Size { |
||||||
|
get => _size; |
||||||
|
set { |
||||||
|
_size = value; |
||||||
|
if(_size <= BankSize * 2) |
||||||
|
Banks = 0; |
||||||
|
else |
||||||
|
Banks = _size / BankSize; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public MemorySize(int bankSize) { |
||||||
|
BankSize = bankSize; |
||||||
|
} |
||||||
|
|
||||||
|
public override string ToString() { |
||||||
|
var ret = $"{Size} KB "; |
||||||
|
if(Banks == 0) |
||||||
|
ret += "(no bank switching)"; |
||||||
|
else |
||||||
|
ret += $"({Banks} banks of {BankSize} KB each)"; |
||||||
|
|
||||||
|
return ret; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,85 @@ |
|||||||
|
using System; |
||||||
|
using System.IO; |
||||||
|
|
||||||
|
namespace DMGHeader { |
||||||
|
internal static class Program { |
||||||
|
internal static void DumpHeader(DmgHeader header) { |
||||||
|
Console.Write("Entry Point: "); |
||||||
|
if(header.EntryPoint.Jump == JumpType.None) { |
||||||
|
Console.WriteLine("No jump found."); |
||||||
|
} else { |
||||||
|
var jumpType = header.EntryPoint.Jump == JumpType.Absolute ? "Absolute" : "Relative"; |
||||||
|
Console.WriteLine($"{jumpType} jump to ROM position 0x{header.EntryPoint.JumpAddress:X4}"); |
||||||
|
} |
||||||
|
|
||||||
|
Console.WriteLine($"Logo Check: {(header.ValidLogo ? "PASSED" : "FAILED")}"); |
||||||
|
Console.WriteLine($"Title/Manufacturer Code: {header.Title}"); |
||||||
|
|
||||||
|
Console.Write("CGB Mode: "); |
||||||
|
switch(header.CgbMode) { |
||||||
|
case CgbMode.Disabled: |
||||||
|
Console.WriteLine("Disabled"); |
||||||
|
break; |
||||||
|
case CgbMode.PaletteOnly: |
||||||
|
Console.WriteLine("Palette Only"); |
||||||
|
break; |
||||||
|
case CgbMode.Enhanced: |
||||||
|
Console.WriteLine("Enhanced"); |
||||||
|
break; |
||||||
|
case CgbMode.Required: |
||||||
|
Console.WriteLine("Required"); |
||||||
|
break; |
||||||
|
default: |
||||||
|
Console.WriteLine("Unknown"); |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
Console.WriteLine($"SGB: {(header.SgbSupport ? "Supported" : "Not Supported")}"); |
||||||
|
Console.WriteLine($"Cartridge Type: {header.CartridgeType}"); |
||||||
|
Console.WriteLine($"ROM Size: {header.RomSize}"); |
||||||
|
Console.WriteLine($"Cartridge RAM Size: {header.ExternalRamSize}"); |
||||||
|
|
||||||
|
Console.Write("Destination Code: "); |
||||||
|
switch(header.DestinationCode) { |
||||||
|
case DestinationCode.Japanese: |
||||||
|
Console.WriteLine("Japanese"); |
||||||
|
break; |
||||||
|
case DestinationCode.NonJapanese: |
||||||
|
Console.WriteLine("Non-Japanese"); |
||||||
|
break; |
||||||
|
case DestinationCode.Unknown: |
||||||
|
Console.WriteLine("Unknown/Invalid Code"); |
||||||
|
break; |
||||||
|
default: |
||||||
|
Console.WriteLine("-- INVALID ENUM VALUE -- "); |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
Console.WriteLine($"Mask ROM Version: 0x{header.MaskRomVersion:X2}"); |
||||||
|
Console.WriteLine($"Header Checksum: 0x{header.HeaderChecksum:X2}"); |
||||||
|
Console.WriteLine($"Header Checksum Status: {(header.ValidHeaderChecksum ? "VALID" : "NOT VALID")}"); |
||||||
|
Console.WriteLine($"Cartridge Checksum: 0x{header.CartridgeChecksum:X4}"); |
||||||
|
Console.WriteLine(); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private static int Main(string[] args) { |
||||||
|
if(args.Length == 0) { |
||||||
|
Console.WriteLine("usage: DMGHeader [filename]"); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
var filename = args[0]; |
||||||
|
|
||||||
|
if(!File.Exists(filename)) { |
||||||
|
Console.WriteLine("File not found!"); |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
var header = new DmgHeader(filename); |
||||||
|
DumpHeader(header); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
This is free and unencumbered software released into the public domain. |
||||||
|
|
||||||
|
Anyone is free to copy, modify, publish, use, compile, sell, or |
||||||
|
distribute this software, either in source code form or as a compiled |
||||||
|
binary, for any purpose, commercial or non-commercial, and by any |
||||||
|
means. |
||||||
|
|
||||||
|
In jurisdictions that recognize copyright laws, the author or authors |
||||||
|
of this software dedicate any and all copyright interest in the |
||||||
|
software to the public domain. We make this dedication for the benefit |
||||||
|
of the public at large and to the detriment of our heirs and |
||||||
|
successors. We intend this dedication to be an overt act of |
||||||
|
relinquishment in perpetuity of all present and future rights to this |
||||||
|
software under copyright law. |
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
||||||
|
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
||||||
|
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
||||||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
||||||
|
OTHER DEALINGS IN THE SOFTWARE. |
||||||
|
|
||||||
|
For more information, please refer to <http://unlicense.org/> |
||||||
|
|
Loading…
Reference in new issue