using System; using System.IO; using System.Runtime.InteropServices; using Decal.Interop.Dat; namespace Decal.DecalDat.Tests { class Program { // File IDs from FileService.Startup() — decimal values converted to hex static readonly (uint id, string name)[] PortalFiles = new[] { (0x0E00000Eu, "SpellTable"), // 234881038 (0x0E00000Fu, "ComponentTable"), // 234881039 (0x0E000003u, "VitalFormulaTable"), // 234881027 (0x0E000004u, "SkillTable"), // 234881028 (0x25000006u, "AttributeTable"), // 620756998 (0x25000007u, "VitalTable"), // 620756999 }; static int _pass, _fail; static void Main(string[] args) { string acPath = args.Length > 0 ? args[0] : @"C:\Turbine\Asheron's Call"; string portalPath = Path.Combine(acPath, "client_portal.dat"); string cellPath = Path.Combine(acPath, "client_cell_1.dat"); Console.WriteLine("=== DecalDat Smoke Test ==="); Console.WriteLine($"Platform: {(IntPtr.Size == 4 ? "x86" : "x64")}"); Console.WriteLine(); TestDatFile("portal", portalPath, 1024); TestDatFile("cell", cellPath, 256); TestPortalKnownFiles(portalPath); TestStreamReadRestart(portalPath); TestStreamReadBinary(portalPath); Console.WriteLine(); Console.WriteLine($"=== Results: {_pass} passed, {_fail} failed ==="); } static void TestDatFile(string label, string path, int sectorSize) { Console.WriteLine($"[TEST] Open {label}.dat ({path})"); if (!File.Exists(path)) { Fail($" File not found: {path}"); return; } try { using (var dat = new DatFile(path, sectorSize)) { Pass($" Opened successfully (sector size {sectorSize})"); } } catch (Exception ex) { Fail($" Failed to open: {ex.Message}"); } } static void TestPortalKnownFiles(string portalPath) { if (!File.Exists(portalPath)) return; Console.WriteLine(); Console.WriteLine("[TEST] Read known portal.dat file IDs"); try { using (var dat = new DatFile(portalPath, 1024)) { foreach (var (id, name) in PortalFiles) { try { var entry = dat.GetFile(id); if (entry.Size > 0) Pass($" 0x{id:X8} ({name}): {entry.Size:N0} bytes"); else Fail($" 0x{id:X8} ({name}): size is 0"); } catch (FileNotFoundException) { Fail($" 0x{id:X8} ({name}): NOT FOUND"); } catch (Exception ex) { Fail($" 0x{id:X8} ({name}): ERROR - {ex.GetType().Name}: {ex.Message}"); } } } } catch (Exception ex) { Fail($" Failed to open DAT: {ex.Message}"); } } static void TestStreamReadRestart(string portalPath) { if (!File.Exists(portalPath)) return; Console.WriteLine(); Console.WriteLine("[TEST] DatStream: Read, Restart, Read again (consistency)"); using (var dat = new DatFile(portalPath, 1024)) { var entry = dat.GetFile(0x0E00000E); // SpellTable var stream = new DatStreamImpl(); stream.Load(entry); int size = stream.Size; if (size <= 0) { Fail("Size is 0"); return; } // Read first 64 bytes via ReadBinary int readSize = Math.Min(64, size); byte[] first = new byte[readSize]; stream.ReadBinary(readSize, ref first[0]); // Restart and read again stream.Restart(); byte[] second = new byte[readSize]; stream.ReadBinary(readSize, ref second[0]); bool match = true; for (int i = 0; i < readSize; i++) if (first[i] != second[i]) { match = false; break; } if (match) Pass($"Read {readSize} bytes, restarted, read again — identical"); else Fail("Data mismatch after Restart!"); stream.Restart(); if (stream.Tell == 0) Pass("Tell resets to 0 after Restart"); else Fail($"Tell is {stream.Tell} after Restart (expected 0)"); } } static void TestStreamReadBinary(string portalPath) { if (!File.Exists(portalPath)) return; Console.WriteLine(); Console.WriteLine("[TEST] DatStream: ReadBinary consistency + Tell tracking"); using (var dat = new DatFile(portalPath, 1024)) { var entry = dat.GetFile(0x0E000004); // SkillTable var stream = new DatStreamImpl(); stream.Load(entry); int size = stream.Size; int readSize = Math.Min(256, size); // Read in two chunks int chunk1 = readSize / 2; int chunk2 = readSize - chunk1; byte[] viaChunks = new byte[readSize]; stream.ReadBinary(chunk1, ref viaChunks[0]); if (stream.Tell == chunk1) Pass($"Tell is {chunk1} after reading {chunk1} bytes"); else Fail($"Tell is {stream.Tell} (expected {chunk1})"); // Read second chunk into offset position byte[] temp = new byte[chunk2]; stream.ReadBinary(chunk2, ref temp[0]); Array.Copy(temp, 0, viaChunks, chunk1, chunk2); // Restart and read all at once stream.Restart(); byte[] viaFull = new byte[readSize]; stream.ReadBinary(readSize, ref viaFull[0]); bool match = true; for (int i = 0; i < readSize; i++) if (viaChunks[i] != viaFull[i]) { match = false; break; } if (match) Pass($"Chunked read ({chunk1}+{chunk2}) matches full read ({readSize})"); else Fail("Chunked vs full read mismatch!"); if (stream.Tell == readSize) Pass($"Tell is {readSize} after reading {readSize} bytes"); else Fail($"Tell is {stream.Tell} (expected {readSize})"); } } static void Pass(string msg) { _pass++; Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine($" PASS {msg}"); Console.ResetColor(); } static void Fail(string msg) { _fail++; Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($" FAIL {msg}"); Console.ResetColor(); } } }