/***************************************************************************************\
* Mortal Kombat Trilogy (PC) (GOG & DOSBox) AutoSplitter.                               *
* By piratesephiroth.                                                                   *
\***************************************************************************************/


state("MKTRILW") {
}


state("DOSBox") {
}


startup {
    refreshRate = 60;
    settings.Add("onlyShao",false,"Detect only Shao Khan's defeat");
}


init {
    long membase = 0;
    
    long gstateOffset = 0;
    long unknownOffset = 0;
    long p1joinOffset = 0;
    long p2joinOffset = 0;
    long p1charOffset = 0;
    long p2charOffset = 0;
    long p1roundsOffset = 0;
    long p2roundsOffset = 0;
    long twSelectOffset = 0;
    
    // short pause, waiting for the game to load
    Thread.Sleep(2000);
    
    if (game.ProcessName == "dosbox") {
        game.Suspend();
        foreach (var page in game.MemoryPages(true)) {
            var scanner = new SignatureScanner(game, page.BaseAddress, (int)page.RegionSize);
            var ptr = scanner.Scan(new SigScanTarget(0, "60 10 00 F0 F4 00 70 00 F4 00 70 00 F4 00 70 00"));
            if (ptr != IntPtr.Zero) {
                membase = (long)ptr;
                print("membase: dosbox.exe+0x" + membase.ToString("X"));
                break;
            }
        }
        game.Resume();
        
        if (membase == 0) {
            throw new Exception("Couldn't find dosbox membase!");
        }
        
        gstateOffset = 0x3539b0;
        unknownOffset = 0x336A0C;
        p1joinOffset = 0x3539b8;
        p2joinOffset = 0x353B30;
        p1charOffset = 0x3539cc;
        p2charOffset = 0x353b44;
        p1roundsOffset = 0x3539D8;
        p2roundsOffset = 0x353B50;
        twSelectOffset = 0x353ce0;
    }
    
    
    if (game.ProcessName == "MKTRILW") {
        var module = modules.First();
        var baseAddr = module.BaseAddress;
        gstateOffset = (long)baseAddr + 0x15422c;
        unknownOffset = (long)baseAddr + 0x137cdc;
        p1joinOffset = (long)baseAddr + 0x154234;
        p2joinOffset = (long)baseAddr + 0x1543ac;
        p1charOffset = (long)baseAddr + 0x154248;
        p2charOffset = (long)baseAddr + 0x1543c0;
        p1roundsOffset = (long)baseAddr + 0x154254;
        p2roundsOffset = (long)baseAddr + 0x1543cc;
        twSelectOffset = (long)baseAddr + 0x15455c;
    }

    
    vars.watchers = new MemoryWatcherList {
        new MemoryWatcher<byte>((IntPtr)(membase + gstateOffset)) { Name = "gameState" },
        new MemoryWatcher<byte>((IntPtr)(membase + unknownOffset)) { Name = "unknown" },
        new MemoryWatcher<byte>((IntPtr)(membase + p1joinOffset)) { Name = "p1Joined" },
        new MemoryWatcher<byte>((IntPtr)(membase + p2joinOffset)) { Name = "p2Joined" },
        new MemoryWatcher<byte>((IntPtr)(membase + p1charOffset)) { Name = "p1Char" },
        new MemoryWatcher<byte>((IntPtr)(membase + p2charOffset)) { Name = "p2Char" },
        new MemoryWatcher<byte>((IntPtr)(membase + p1roundsOffset)) { Name = "p1RoundsWon" },
        new MemoryWatcher<byte>((IntPtr)(membase + p2roundsOffset)) { Name = "p2RoundsWon" },
        new MemoryWatcher<byte>((IntPtr)(membase + twSelectOffset)) { Name = "towerSelect" }
    };
    
    vars.endOfMatch = false;
}


update {
    vars.watchers.UpdateAll(game);
}


start {
    //  if 0 or 2 players, do nothing
    if ((vars.watchers["p1Joined"].Current ^ vars.watchers["p2Joined"].Current) != 1){
        return false;
    }
    
    if (vars.watchers["gameState"].Current == 4 &&
        vars.watchers["unknown"].Current == 22 &&
        vars.watchers["towerSelect"].Current != 0) {
            return true;
        }
}


split {
    if (vars.watchers["p1Joined"].Current == 1){
        if (vars.watchers["p1RoundsWon"].Current == 2 && (vars.watchers["p1RoundsWon"].Current != vars.watchers["p1RoundsWon"].Old)){
            vars.endOfMatch = true;
        }
    }
    if (vars.watchers["p2Joined"].Current == 1){
        if (vars.watchers["p2RoundsWon"].Current == 2 && (vars.watchers["p2RoundsWon"].Current != vars.watchers["p2RoundsWon"].Old)){
            vars.endOfMatch = true;
        }
    }
    
    if (vars.endOfMatch) {
        if (vars.watchers["gameState"].Current == 5 && !settings["onlyShao"]) {
            vars.endOfMatch = false;
            print("WON THE MATCH!");
            return true;
        }
        if (vars.watchers["gameState"].Current== 11) {
            vars.endOfMatch = false;
            print("ALL DONE!");
            return true;
        }
    }
    
}


// reset timer if game is in attract mode
reset {
    if (vars.watchers["p1Joined"].Current + vars.watchers["p2Joined"].Current == 0){
        print("RESET");
        return true;
    }
}