Has it really been over a week since I updated? I guess so. I've been taking Akari's suggestion and running with it. Trying to create something that most people could read. I've run into a problem, however.
Ignoring the fact that this is very hard work, let's also talk about erroneous scripts.
Cloud's Physical Counter and Sephiroth's Main scripts have several instances of two consecutive 72h commands. Only one of these will be called (the first one in each instance) and the second one is completely avoided. Why, then, is it there? Some weird deal with their compiler? Who knows.
Sephiroth's Init script is contradicting TFergusson's data. The script starts out:
12 6020
10 2440
80
60 01
90
and it does that three more times with other values in the 10h command. Fergusson states in his nots on command 80h:
Absolutely *NOTHING* happens (not even popping variables off) if 'y' is a '1x'-type Var.
y is either the first or second pop, he wasn't clear on that, but it's probably the first. However, if you notice the first two commands are to pop 1X-type variables to the stack so according to him this script shouldn't do anything . . . but it does.
This particular script, to me, translates as (in very simple terms):
Self.MainScriptOverride = True
Self.Flag(200) = True [&4029]
Self.Flag(100) = True [&4028]
Self.Flag(400) = True [&402A]
I'm not sure what these flags so...I guess I'm slightly stuck. I may just have to leave these in assembler (Which is easiest for me, but I know it's not good for everyone).
UPDATE: So who wants to see the decompiled Character AI Scripts? Yeah, I thought you did.
Cloud.PhysicalCounter:LocalVar:0000 <- 255
If (&BattleVar(Self).CharVar(Ally Covered) == 19)
{
LocalVar:0000 <- 80
}
ElseIf (&BattleVar(Self).CharVar(Ally Covered) == 18)
{
LocalVar:0000 <- 81
}
ElseIf (&BattleVar(Self).CharVar(Ally Covered) == 21)
{
LocalVar:0000 <- 82
}
ElseIf (&BattleVar(Self).CharVar(Ally Covered) == 17)
{
LocalVar:0000 <- 83
}
POP()
If ( (&LocalVar:0000 != 255) )
{
BattleVar(TempGlobal) <- &GlobalVar(0000)
BattleVar(2018) <- &BattleVar(TempGlobal)
BattleVar(TempGlobal) <- &BattleVar(TempGlobal) + 3
If ( (&BattleVar(TempGlobal) > 200) )
{
BattleVar(TempGlobal) <- 200
}
GlobalVar(0000) <- &BattleVar(TempGlobal))
Debug.Print: "LOVEPARA CHR:%d, %d->%d" ; &BattleVar(Self).CharVar(Ally Covered) - 16; &BattleVar(2018); &BattleVar(TempGlobal)
}
Cloud.AllyDeathLocalVar:0020 <- 0
If ( (&LocalVar:0020 < 3) )
{
BattleVar(Target) <- FlagBit(&LocalVar:0020)
If (&BattleVar(Target).CharVar(Status))
{
LocalVar:0000 <- 255
If (&BattleVar(Target).CharVar(Formation) == 19)
{
LocalVar:0000 <- 80
}
ElseIf (&BattleVar(Target).CharVar(Formation) == 18)
{
LocalVar:0000 <- 81
}
ElseIf (&BattleVar(Target).CharVar(Formation) == 21)
{
LocalVar:0000 <- 82
}
ElseIf (&BattleVar(Target).CharVar(Formation) == 17)
{
LocalVar:0000 <- 83
}
POP()
If ( (&LocalVar:0000 != 255) )
{
BattleVar(TempGlobal) <- &GlobalVar(0000)
BattleVar(2018) <- &BattleVar(TempGlobal)
BattleVar(TempGlobal) <- &BattleVar(TempGlobal) - 5
If ( (&BattleVar(TempGlobal) < 50) )
{
BattleVar(TempGlobal) <- 50
}
GlobalVar(0000) <- &BattleVar(TempGlobal))
Debug.Print: "LOVEPARA CHR:%d, %d->%d" ; &BattleVar(Target).CharVar(Formation) - 16; &BattleVar(2018); &BattleVar(TempGlobal)
}
LocalVar:0020 <- &LocalVar:0020 + 1
GOTO: 0x0006
}
Barret.InitLink with scripts on character: 3
Tifa.InitLink with scripts on character: 3
Aeris.GeneralCounterIf (&BattleVar(Self).CharVar(Formation) == 19)
{
LocalVar:0080 <- 80
}
ElseIf (&BattleVar(Self).CharVar(Formation) == 18)
{
LocalVar:0080 <- 81
}
ElseIf (&BattleVar(Self).CharVar(Formation) == 21)
{
LocalVar:0080 <- 82
}
ElseIf (&BattleVar(Self).CharVar(Formation) == 17)
{
LocalVar:0080 <- 83
}
POP()
BattleVar(Target) <- &BattleVar(Self).CharVar(40D0)
BattleVar(Target) <- (&BattleVar(Target).CharVar(Formation) == 16)
If (&BattleVar(Target))
{
LocalVar:0020 <- &BattleVar(Self).CharVar(4160)
LocalVar:0060 <- 0
If ( (&LocalVar:0020 < &LocalVar:0000) )
{
LocalVar:00A0 <- 0
LocalVar:0060 <- 2
}
ElseIf (&LocalVar:00C0)
{
If (&LocalVar:0020)
{
LocalVar:00A0 <- 1
LocalVar:0060 <- 4
}
}
ElseIf ( (&LocalVar:0020 > &LocalVar:0000) )
{
LocalVar:00A0 <- 1
LocalVar:0060 <- 2
}
If (&LocalVar:0060)
{
BattleVar(TempGlobal) <- &GlobalVar(0080)
BattleVar(2018) <- &BattleVar(TempGlobal)
If ( (&LocalVar:00A0 == 1) )
{
BattleVar(TempGlobal) <- &BattleVar(TempGlobal) + &LocalVar:0060
If ( (&BattleVar(TempGlobal) > 200) )
{
BattleVar(TempGlobal) <- 200
}
}
Else
{
BattleVar(TempGlobal) <- &BattleVar(TempGlobal) - &LocalVar:0060
If ( (&BattleVar(TempGlobal) < 50) )
{
BattleVar(TempGlobal) <- 50
}
GlobalVar(0080) <- &BattleVar(TempGlobal))
Debug.Print: "LOVEPARA CHR:%d, %d->%d" ; &BattleVar(Self).CharVar(Formation) - 16; &BattleVar(2018); &BattleVar(TempGlobal)
}
Aeris.DeathCounterIf (&BattleVar(Self).CharVar(Formation) == 19)
{
LocalVar:0080 <- 80
}
ElseIf (&BattleVar(Self).CharVar(Formation) == 18)
{
LocalVar:0080 <- 81
}
ElseIf (&BattleVar(Self).CharVar(Formation) == 21)
{
LocalVar:0080 <- 82
}
ElseIf (&BattleVar(Self).CharVar(Formation) == 17)
{
LocalVar:0080 <- 83
}
POP()
BattleVar(Target) <- &BattleVar(Self).CharVar(40D0)
BattleVar(Target) <- (&BattleVar(Target).CharVar(Formation) == 16)
If (&BattleVar(Target))
{
BattleVar(TempGlobal) <- &GlobalVar(0080)
BattleVar(2018) <- &BattleVar(TempGlobal)
BattleVar(TempGlobal) <- &BattleVar(TempGlobal) - 4
If ( (&BattleVar(TempGlobal) < 50) )
{
BattleVar(TempGlobal) <- 50
}
GlobalVar(0080) <- &BattleVar(TempGlobal))
Debug.Print: "LOVEPARA CHR:%d, %d->%d" ; &BattleVar(Self).CharVar(Formation) - 16; &BattleVar(2018); &BattleVar(TempGlobal)
}
Aeris.PreTurnLocalVar:0000 <- &BattleVar(Self).CharVar(4160)
LocalVar:00C0 <- &BattleVar(Self).CharVar(Status)
Yuffie.InitLink with scripts on character: 3
Vincent.MainLocalVar:0000 <- 98 + &BattleVar(2038) * 2
If ( (Random MOD 10 < 3) )
{
LocalVar:0000 <- &LocalVar:0000 + 1
}
BattleVar(Target) <- &BattleVar(2040)
Perform attack(&LocalVar:0000)
Sephiroth.InitBattleVar(Self).CharVar(Flag(0:4)) <- 1
BattleVar(Self).CharVar(Flag(1:1)) <- 1
BattleVar(Self).CharVar(Flag(1:0)) <- 1
BattleVar(Self).CharVar(Flag(1:2)) <- 1
Sephiroth.MainLocalVar:0000 <- 2
BattleVar(Target) <- (&BattleVar(Target).CharVar(ElemWeakness) >= 5)
If (&BattleVar(Target))
{
Debug.Print: "RESIST EARTH MONSTER" ; 0
LocalVar:0040 <- 1
}
BattleVar(Target) <- (&BattleVar(2050).CharVar(Formation) == 25)
If ( ( (&BattleVar(Target) And (&BattleVar(Target).CharVar(Status) == 1) ) And (Random MOD 3 == 0) ) )
{
LocalVar:0020 <- 8
}
ElseIf ( (BitCount(&BattleVar(Enemies)) == 1) )
{
BattleVar(Target) <- RandomBit(&BattleVar(Enemies))
If ( (&BattleVar(Target).CharVar(4270) >= 16) )
{
LocalVar:0020 <- 29
}
Else
{
LocalVar:0000 <- 1
}
}
Else
{
BattleVar(Target) <- &BattleVar(Enemies)
If (Random MOD 3 + &LocalVar:0040 == 0)
{
LocalVar:0020 <- 38
LocalVar:0040 <- 1
}
ElseIf (Random MOD 3 + &LocalVar:0040 == 1)
{
LocalVar:0020 <- 32
}
Else
{
LocalVar:0020 <- 35
}
Else
{
POP()
}
Perform attack(&LocalVar:0020)
This was JUST made from the WM 1.2.0 "Proving Grounds". This still isn't editable yet, but this is getting closer.
I realize this is a lot to go through just to read it all and it's probably pretty confusing. Let me point out a few details.
1. This is incomplete. There are still a lot of memory addresses that need to be accounted for. I haven't done them all, just most of the ones that show up in these scripts.
2. Look at Aeris's GeneralCounter. There's an ElseIF statement there near the middle that contains a nested IF statement. Normally this condition would just be ANDed to the ElseIf statement. This is not a mistake with my decompiler, this is the way it's written. Weird. It also needs two more close curly brackets. I'm not sure what to do about that...
3. Sephiroth's Main Script has two Elses at the end of it. This is a very strange (and unnecessary) code that makes disassembling weird. The code at script address 0xDD is "72 E000". For those keeping score, you can see why this is a completely unnecessary line. If 72h does mean go to address xxxx, then this line basically says "go to the next line". The way I keep track of Elses is by where these jump commands are. That POP() statement will just execute in that larger Else statement.
That's about all I have to report. It's taken me about 2 days (about 11 hours work) to get these results from what I had shown previously. I have no clue how to write an assembler for this so this maybe just a translator more than anything else. I will not likely write an assembler, but I might...given the proper incentive of course.
Non-WM-related update: Wondering why I haven't been doing anything WM related lately? I've been
fixing the PC MDef bug.
WM-related update: I hope people are still looking at this even though it's currently on the second page. I believe I have isolated the damage calculation function and where the 0002h flag is handled. Apparently it does something with the Affect MP.
Here's what it does if that 0002h flag is active (using modified addresses):
if (not (&(99E308+6Ch) and 200h) and _ ' Is flag active?
not (&C3F37C and (1 << arg_4)) and _ ' Not sure what argument_4 is. Often passes
not (&(99E308+228h) and 40000h) then ' Some flag it set? Never seen it pass.
var_34 = 1
else
var_34 = 0
end if
var_14 = var_34
var_14 then goes on to be checked with the Affect MP flag.
if (var_14 = 0 and _
not (&(99E308+6Ch) and 100h) and _ 'Affect MP?
not (&(99E308+228h) and 1) and _ 'This flag is not on
not (&(99E308+230h) and C1h) then
&(99E308+218h) = &(99E308+218h) or 1 'Turn this flag on
end if
If var_14 is 1 it skips several steps afterwards as well.
I don't know what any of these addresses are or what data starts at 0x99E308. Looks like data specific to the current attack since +6Ch is the special flags and something close to +60h and +64 are Camera movements. Apparently that address gets written to address 0x99CE0C almost as soon as the game starts and gets referenced in 1210 places after that! If anyone can identify these addresses let me know. They're probably off from the original 1.02 by a bit.