using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Ionic.Zlib;
using System.Diagnostics;

namespace nsmblaunch
{
    class Program
    {
        static void Main(string[] args)
        {
           /* if (args.Length < 1)
            {
                Console.WriteLine("usage: nsmblaunch.exe <savestate file>");
                return;
            }*/

            String filename = "nsmb.ds9";// args[0];

            Console.WriteLine("Reading input file...");
            byte[] stuff = File.ReadAllBytes(filename);
            MemoryStream ms = new MemoryStream(stuff.Length);
            BinaryReader br = new BinaryReader(ms);
            ms.Position = 0;
            ms.Write(stuff, 0, stuff.Length);

            ms.Position = 0;
            byte[] fileheader = br.ReadBytes(0x18);
            int length = br.ReadInt32();
            int complen = br.ReadInt32();

            byte[] ssbytes = new byte[length];

            if (complen == -1)
            {
                Console.WriteLine("Plain savestate found");
                ms.Read(ssbytes, 0, length);
            }
            else
            {
                Console.WriteLine("Compressed savestate found; decompressing...");
                using (ZlibStream gz = new ZlibStream(ms, CompressionMode.Decompress))
                {
                    gz.Read(ssbytes, 0, length);
                }
            }

            ms.Close();


            int world, level, area;
            for (; ; )
            {
                try
                {
                    Console.WriteLine("World number? (0-9)");
                    world = int.Parse(Console.ReadLine());
                    Console.WriteLine("Level number? (from 0)");
                    level = int.Parse(Console.ReadLine());
                    Console.WriteLine("Area number? (from 0, global)");
                    area = int.Parse(Console.ReadLine());

                    break;
                }
                catch (FormatException ex)
                {
                    Console.WriteLine("Bad format, try again");
                }
            }


            Console.WriteLine("Looking for main RAM in savestate...");

            int rampos = 0;
            for (; rampos < length; rampos++)
            {
                if (ssbytes[rampos  ] != 'W') continue;
                if (ssbytes[rampos+1] != 'R') continue;
                if (ssbytes[rampos+2] != 'A') continue;
                if (ssbytes[rampos+3] != 'M') continue;

                rampos += 12;
                Console.WriteLine("RAM found at 0x{0:X}", rampos);
                break;
            }

            ssbytes[rampos + 0x85A18] = (byte)world;
            ssbytes[rampos + 0x85A14] = (byte)level;
            ssbytes[rampos + 0x88F3A] = (byte)area;

            Console.WriteLine("Patched, writing output file...");

            FileStream outf = File.Create(filename);// + ".blarg.dsv");
            BinaryWriter bw = new BinaryWriter(outf);
            bw.Write(fileheader);
            bw.Write(length);
            bw.Write((int)-1);
            bw.Write(ssbytes);
            bw.Close();
            outf.Close();

            ProcessStartInfo blarg = new ProcessStartInfo();
            blarg.FileName = "desmume.exe";
            blarg.Arguments = "--load-slot 9 nsmb.nds";
            Process.Start(blarg);
        }
    }
}
