// Legacy of Kain: Soul Reaver 1 & 2 Remaster Autosplitter Version 1.0 13 Dec 2024
// By TheDementedSalad
//Supports Load Remover
//Autosplitter for SR1 & 2


// Special thanks to:
// TheDementedSalad - Created Splitter
// Gemini REbirth - Dev for the game, helped with finding addresses and info for them

state("SRX", "Release")
{
	string10 	diaName:	0xC0160;
	byte		diaState:	0xC0194;
	bool		currGame:	0xBC7E8;
	
	byte 		SR1Cutscene: 	"sr1.dll", 0x2B1DE0; //1 Cutscene, 0 No Cutscene
	string10 	SR1map: 	"sr1.dll", 0x2A7FCA0;
	byte		SR1paused: 	"sr1.dll", 0x2A7FCB6; //6 paused 0 unpaused
	int 		SR1Info: 	"sr1.dll", 0x2A7F45C;
	int 		SR1x: 		"sr1.dll", 0x2B65DC;
	
	byte 		SR2Cutscene: 	"sr2.dll", 0x482918; //1 Cutscene, 0 No Cutscene
	string10 	SR2map: 	"sr2.dll", 0x5E92AD8;
	byte		SR2paused: 	"sr2.dll", 0x5E92AEE; //6 paused 0 unpaused
	int		SR2Info: 	"sr2.dll", 0x5E92268; //bit 0 Pass Through Walls, bit 1 Wall Crawling, bit 2 Force, bit 3 Soul Reaver, bit 4 Swim, bit 5 Constrict, bit 7 SR2Health
	
	/* Extra Info on Bits
	byte		SR2I2: 		"sr2.dll", 0x5E92269; //bit 1 Blood Reaver, bit 2 Spectral, bit 3 Material, bit 4 Dark, bit 5 Light, bit 6 Air, bit 7 Fire
	byte		SR2I3: 		"sr2.dll", 0x5E9226A; //bit 0 Water Reaver, bit 1 Earth, bit 2 Spirit, bit 3 Plane Shift Glyph, bit 4 Soul Reaver Glyph, bit 5 Dimension, bit 6 Time, bit 7 Mind
	byte		SR2I4: 		"sr2.dll", 0x5E9226B; //bit 0 Conflict Glyph, bit 1 Death, bit 2 States, bit 3 Nature, bit 4 Energy, bit 5 Balance, bit 7 Disable Soul Reaver
	*/
}

state("SRX", "Patch1")
{
	string10 	diaName:	0xC2170;
	byte		diaState:	0xC21A4;
	bool		currGame:	0xBE7E4;
	
	byte 		SR1Cutscene: 	"sr1.dll", 0x2B8F80; 
	string10 	SR1map: 	"sr1.dll", 0x2A86FC0;
	byte		SR1paused: 	"sr1.dll", 0x2A86FD6; 
	int 		SR1Info: 	"sr1.dll", 0x2A8677C;
	int 		SR1x: 		"sr1.dll", 0x2BD77C;
	
	byte 		SR2Cutscene: 	"sr2.dll", 0x488958;
	string10 	SR2map: 	"sr2.dll", 0x5E98AF8;
	byte		SR2paused: 	"sr2.dll", 0x5E98B0E; 
	int		SR2Info: 	"sr2.dll", 0x5E98288; 
}

startup
{
	Assembly.Load(File.ReadAllBytes("Components/asl-help")).CreateInstance("Basic");
	vars.Helper.Settings.CreateFromXml("Components/LoKSRR.Settings.xml");
	
	vars.bitCheck = new Func<int, int, bool>((int val, int b) => (val & (1 << b)) != 0);

	vars.finalSplit1 = 0;
	vars.finalSplit2 = 0;
}

init
{
	switch (modules.First().ModuleMemorySize)
	{
		case (111214592):
			version = "Release";
			break;
		case (111222784):
			version = "Patch1";
			break;
	}
	
	vars.completedSplits = new HashSet<string>();
}

onStart
{
	//resets the splits when a new run starts
	vars.completedSplits.Clear();
	vars.finalSplit1 = 0;
	vars.finalSplit2 = 0;
}

update
{	
	vars.Helper.Update();
	vars.Helper.MapPointers();
	
	if(!current.currGame){
		if(current.SR1map == "chrono1" && current.SR1Cutscene == 1 && old.SR1Cutscene == 0){
			vars.finalSplit1++;
			return true;
		}
	}
	
	if(current.currGame){
		if(current.SR2map == "strong2c" && current.SR2Cutscene == 1 && old.SR2Cutscene == 0){
			vars.finalSplit2++;
			return true;
		}
	}
	//print(modules.First().ModuleMemorySize.ToString());
}

start
{
	return current.SR1Cutscene == 1 && old.SR1Cutscene == 0 && current.SR1map == "under1" || current.SR2Cutscene == 1 && old.SR2Cutscene == 0 && current.SR2map == "strong1A";
}

split
{
	
	string setting = "";
	
	if(!current.currGame){
		if(current.SR1map != old.SR1map || current.SR1Cutscene != old.SR1Cutscene){
			setting = "Area_" + current.SR1map + "_" + current.SR1Cutscene;
		}
		
		if((current.SR1map == "cathy60" || current.SR1map == "cathy76") && current.SR1Cutscene == 1){
			setting = "glass1";
		}
	
		if((current.SR1map == "cathy59" || current.SR1map == "cathy75") && current.SR1Cutscene == 1){
			setting = "glass2";
		}
	
		if(current.SR1map == "cathy42" && current.SR1Cutscene == 1 && current.SR1x == -812){
			setting = "valve2";
		}
		
		if(current.SR1map == "cathy46" && current.SR1Cutscene == 1 && current.SR1x == -4707){
			setting = "valve3";
		}
		
		if(current.SR1map == "chrono1" && vars.finalSplit1 == 3 && current.SR1Cutscene == 1 && old.SR1Cutscene == 0){
			return true;
		}
		
		for (int i = 0; i < sizeof(int) * 8; i++){
			if (vars.bitCheck(current.SR1Info, i) && !vars.bitCheck(old.SR1Info, i)){
				setting = "SR1Info_" + i;
			}
		}
	}
	
	if(current.currGame){
		if(current.SR2map != old.SR2map || current.SR2Cutscene != old.SR2Cutscene){
			setting = "Area_" + current.SR2map + "_" + current.SR2Cutscene;
		}
		
		if(current.SR2map == "pillars12A" && current.SR2Cutscene == 1 && old.SR2Cutscene == 0 && vars.bitCheck(current.SR2Info, 12)){
			setting = "EGReturn1";
		}
		
		if(current.SR2map == "strong4A" && current.SR2Cutscene == 1 && old.SR2Cutscene == 0 && vars.bitCheck(current.SR2Info, 13)){
			setting = "MeetKain1";
		}
		
		if(current.SR2map == "janos4A" && current.SR2Cutscene == 1 && old.SR2Cutscene == 0 && vars.bitCheck(current.SR2Info, 15)){
			setting = "UschAmbush1";
		}
		
		if(current.SR2map == "strrong2c" && vars.finalSplit2 == 2 && current.SR2Cutscene == 1 && old.SR2Cutscene == 0){
			return true;
		}
		
		for (int i = 0; i < sizeof(int) * 8; i++){
			if (vars.bitCheck(current.SR2Info, i) && !vars.bitCheck(old.SR2Info, i)){
				setting = "SR2Info_" + i;
			}
		}
	}
	
	if(current.diaName != old.diaName || current.diaState != old.diaState){
		setting = "Dialogue_" + current.diaName + "_" + current.diaState;
	}
	
	// Debug. Comment out before release.
	if (!string.IsNullOrEmpty(setting))
	vars.Log(setting);

	if (settings.ContainsKey(setting) && settings[setting] && vars.completedSplits.Add(setting)){
		return true;
	}
}

isLoading
{
	return current.SR1paused == 6 || current.SR2paused == 6;
}

reset
{
	return current.diaName == "KAININT" && old.diaName != "KAININT" || current.diaName == "SR2INTRO" && old.diaName != "SR2INTRO";
}