No crash for me.
So, I did a bit more investigation into my crash. I noticed that the PDB symbols are distributed with the SDK -- very nice. This was able to help me track it down a bit more, even though I am not able to build a replacement DLL.
This is the call stack of the crash location:
Spoiler :
CvGameCoreDLL.dll!CvLandscapeInfo::getVerticalGameCell() C++
CvGameCoreDLL.dll!CvPlot::doFeature() + 0x2bc bytes C++
CvGameCoreDLL.dll!CvPlot::doTurn() + 0x292 bytes C++
CvGameCoreDLL.dll!CvMap::doTurn() + 0x2a bytes C++
CvGameCoreDLL.dll!CvGame::doTurn() + 0x2b7 bytes C++
CvGameCoreDLL.dll!CvGame::update() + 0xae bytes C++
Civ4BeyondSword.exe!00417a56()
[Frames below may be incorrect and/or missing, no symbols loaded for Civ4BeyondSword.exe]
kernel32.dll!76620111()
Civ4BeyondSword.exe!006a7ba8()
Civ4BeyondSword.exe!004e9de6()
Civ4BeyondSword.exe!009199ff()
kernel32.dll!76624911()
kernel32.dll!7662c56f()
ntdll.dll!77c2e4b6()
ntdll.dll!77c2e489()
Civ4BeyondSword.exe!0088000b()
Looking at the disassembly, getVerticalGameCell() is misleading -- it is optimized by the linker, and is the same as getDisappearanceProbability() from this line in CvPlot::doFeature():
iProbability = GC.getFeatureInfo(getFeatureType()).getDisappearanceProbability();
Here is the disassembly of the relevant portion of doFeature():
Spoiler :
06E2BC5F push offset string "FLAMES_EXPIRE_EFFECT" (702FD94h)
06E2BC64 mov ecx,offset gGlobals (711A9D0h)
06E2BC69 call CvGlobals::getDefineINT (6D7D980h)
06E2BC6E push eax
06E2BC6F mov ecx,edi
06E2BC71 call CvPlot::setFeatureType (6E2B490h)
06E2BC76 movsx eax,word ptr [edi+2Eh]
06E2BC7A push eax
06E2BC7B mov ecx,offset gGlobals (711A9D0h)
06E2BC80 call CvGlobals::getFeatureInfo (6D7CCE0h)
06E2BC85 mov ecx,eax
* 06E2BC87 call CvLandscapeInfo::getVerticalGameCell (6E50BB0h)
06E2BC8C mov esi,eax
06E2BC8E test esi,esi
06E2BC90 jle 06E2BF6C
06E2BC96 mov ecx,dword ptr [gGlobals+2Ch (711A9FCh)]
06E2BC9C push offset string "Feature Disappearance" (702FD7Ch)
06E2BCA1 push 2710h
06E2BCA6 call CvGame::getSorenRandNum (6CFC380h)
From that, it seems like EDI holds our "this" pointer, and the feature type is stored at: word ptr [edi+2Eh], which has this value:
*(short *)(edi + 0x2E) 0xffff short
It would seem that the feature type is -1, or NO_FEATURE. The question is, how did we even get in this block of code, if we are in NO_FEATURE? (There is a test at the top.) Given that, it seems that the code just above which converts a FLAMES_FEATURE to a FLAMES_EXPIRE_EFFECT has failed for some reason, after setting the feature type to NO_FEATURE. Perhaps canHaveFeature returned false. I don't know.
The crash for me (and not for Sto) can be explained, because calling getFeatureInfo with NO_FEATURE passed will index into an array and return the -1 element of the array. getDissaperanceProbability() will then dereference that pointer. For me, the pointer is consistently returning something in no-man's land, and it must return something in mapped memory for Sto. I would say the code should be checking for NO_FEATURE before calling getFeatureInfo().
By the process of elimination, if I load the save file and use the world editor to remove the flame features, it seems to be the flame which is two squares to the south of Acheron which is causing the problem, because when I take out that one everything is fine, but if I take out all the others and leave that one in, my game will crash.
Hope this helps, and let me know if there is anything more I can do.