using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using SabreTools.Library.Data;
using SabreTools.Library.DatItems;
using SabreTools.Library.IO;
namespace SabreTools.Library.DatFiles
{
///
/// Represents parsing and writing of an AttractMode DAT
///
internal class AttractMode : DatFile
{
///
/// Constructor designed for casting a base DatFile
///
/// Parent DatFile to copy from
public AttractMode(DatFile datFile)
: base(datFile)
{
}
///
/// Parse an AttractMode DAT and return all found games within
///
/// Name of the file to be parsed
/// Index ID for the DAT
/// True if full pathnames are to be kept, false otherwise (default)
protected override void ParseFile(string filename, int indexId, bool keep)
{
// Open a file reader
Encoding enc = FileExtensions.GetEncoding(filename);
StreamReader sr = new StreamReader(FileExtensions.TryOpenRead(filename), enc);
sr.ReadLine(); // Skip the first line since it's the header
while (!sr.EndOfStream)
{
string line = sr.ReadLine();
/*
The gameinfo order is as follows
0 - game name
1 - game description
2 - emulator name (filename)
3 - cloneof
4 - year
5 - manufacturer
6 - category
7 - players
8 - rotation
9 - control
10 - status
11 - displaycount
12 - displaytype
13 - alt romname
14 - alt title
15 - extra
16 - buttons
*/
string[] gameinfo = line.Split(';');
Rom rom = new Rom
{
Name = "-",
Size = Constants.SizeZero,
CRC = Constants.CRCZero,
MD5 = Constants.MD5Zero,
#if NET_FRAMEWORK
RIPEMD160 = Constants.RIPEMD160Zero,
#endif
SHA1 = Constants.SHA1Zero,
ItemStatus = ItemStatus.None,
Machine = new Machine
{
Name = gameinfo[0],
Description = gameinfo[1],
CloneOf = gameinfo[3],
Year = gameinfo[4],
Manufacturer = gameinfo[5],
Category = gameinfo[6],
Players = gameinfo[7],
Rotation = gameinfo[8],
Control = gameinfo[9],
Status = gameinfo[10],
DisplayCount = gameinfo[11],
DisplayType = gameinfo[12],
Comment = gameinfo[15],
Buttons = gameinfo[16],
},
AltName = gameinfo[13],
AltTitle = gameinfo[14],
Source = new Source
{
Index = indexId,
Name = filename,
},
};
// Now process and add the rom
ParseAddHelper(rom);
}
sr.Dispose();
}
///
/// Create and open an output file for writing direct from a dictionary
///
/// Name of the file to write to
/// True if blank roms should be skipped on output, false otherwise (default)
/// True if the DAT was written correctly, false otherwise
public override bool WriteToFile(string outfile, bool ignoreblanks = false)
{
try
{
Globals.Logger.User($"Opening file for writing: {outfile}");
FileStream fs = FileExtensions.TryCreate(outfile);
// If we get back null for some reason, just log and return
if (fs == null)
{
Globals.Logger.Warning($"File '{outfile}' could not be created for writing! Please check to see if the file is writable");
return false;
}
SeparatedValueWriter svw = new SeparatedValueWriter(fs, new UTF8Encoding(false))
{
Quotes = false,
Separator = ';',
VerifyFieldCount = true
};
// Write out the header
WriteHeader(svw);
// Use a sorted list of games to output
foreach (string key in Items.SortedKeys)
{
List datItems = Items.FilteredItems(key);
// Resolve the names in the block
datItems = DatItem.ResolveNames(datItems);
for (int index = 0; index < datItems.Count; index++)
{
DatItem datItem = datItems[index];
// Check for a "null" item
datItem = ProcessNullifiedItem(datItem);
// Write out the item if we're not ignoring
if (!ShouldIgnore(datItem, ignoreblanks))
WriteDatItem(svw, datItem);
}
}
Globals.Logger.Verbose($"File written!{Environment.NewLine}");
svw.Dispose();
fs.Dispose();
}
catch (Exception ex)
{
Globals.Logger.Error(ex.ToString());
return false;
}
return true;
}
///
/// Write out DAT header using the supplied StreamWriter
///
/// SeparatedValueWriter to output to
/// True if the data was written, false on error
private bool WriteHeader(SeparatedValueWriter svw)
{
try
{
string[] headers = new string[]
{
"#Title",
"Name",
"Emulator",
"CloneOf",
"Year",
"Manufacturer",
"Category",
"Players",
"Rotation",
"Control",
"Status",
"DisplayCount",
"DisplayType",
"AltRomname",
"AltTitle",
"Extra",
"Buttons",
};
svw.WriteHeader(headers);
svw.Flush();
}
catch (Exception ex)
{
Globals.Logger.Error(ex.ToString());
return false;
}
return true;
}
///
/// Write out Game start using the supplied StreamWriter
///
/// SeparatedValueWriter to output to
/// DatItem object to be output
/// True if the data was written, false on error
private bool WriteDatItem(SeparatedValueWriter svw, DatItem datItem)
{
try
{
// No game should start with a path separator
datItem.Machine.Name = datItem.Machine.Name.TrimStart(Path.DirectorySeparatorChar);
// Pre-process the item name
ProcessItemName(datItem, true);
// Build the state
switch (datItem.ItemType)
{
case ItemType.Rom:
var rom = datItem as Rom;
string[] fields = new string[]
{
rom.Machine.Name,
rom.Machine.Description,
Header.FileName,
rom.Machine.CloneOf,
rom.Machine.Year,
rom.Machine.Manufacturer,
rom.Machine.Category,
rom.Machine.Players,
rom.Machine.Rotation,
rom.Machine.Control,
rom.ItemStatus.ToString(),
rom.Machine.DisplayCount,
rom.Machine.DisplayType,
rom.AltName,
rom.AltTitle,
rom.Machine.Comment,
rom.Machine.Buttons,
};
svw.WriteValues(fields);
break;
}
svw.Flush();
}
catch (Exception ex)
{
Globals.Logger.Error(ex.ToString());
return false;
}
return true;
}
}
}