Skip to content
Alan Tse edited this page Dec 15, 2023 · 49 revisions

Welcome to the CommonLibVR wiki!

ESL scratchpad

ESLs were not supported in VR. This was a page to aggregate data for VR for any attempts to add it. This is left for reference.

Want to help?

AFKMods discussion on ESL/ESP difference Save game format 1.5.97 address for .esl: 141632ac8

TESFile->smallFileCompileIndex looks to be just padding in VR. We can treat TESFile as the SE version and we likely won't overwrite any actual data

TESFile->currentform.formid in (TESFile__ReadFormHeader_14018EAD0) has plugin index equal to master index in master list (ex: "AAA.esp" has Skyrim, Dragonborn as masters. 0 = Skyrim.esm, 1 = Dragonborn.esm, 2 = AAA.esp).

Potentially relevant functions:

Name SSE VR Notes
bool TESFile::IsESL_14017E160 (TESFile * param_1) 14017E160
void TESFile::AdjustFormIDFileIndex(TESFile *a_this,uint *a_formid) 14017e180 Used to set formids for ESL files; need in VR
bool TESFile::SetCompileIndex_14017C63 (TESFile * a_file, int a_index) 14017C63 14018C480
PluginLoader? 14050eea0 14051dc00
LoadPluginBSA 140173BD0 140184360
TESDataHandler::ctor 140166D80 1401774C0 functions relevant for forms/formIDs/etc.
TESDataHandler::CompileFiles_14017EFF0 14016E660 14017EFF0 DataHandler->LoadingFiles set to true AND false here. offset 0x14A seems to be where masters are set above regular files. loadedModCount reset if a_unk is true, maybe this is where the plugins are parsed/loaded?
iFormsLoaded 141EC3B60 141F889C0 Named from FO4
TESDataHandler::ConstructObjectList_140180870 1401700E0 140180870 Named from FO4

Functions we should modify:

Name SSE VR Modification treatment isCompleted
TESDataHandler::sub_14017EFF0 14016E660 14017EFF0 ASM hook 5 spots where loadedmods is used, replace with TESFileCollection
TESDataHandler::AddFile 14017EFF0 Replace entire function with SSE or near SSE equivalent; uses TESFile::IsESL
sub_1401831F0 1401831F0 ASM replace 0x807-852. Jmp to function to add TESFile the way SSE does (ESP/ESL split)
TESFile::GetCompileIndex_14018C470 14018C470 Seems used for File checking/form ID setting. Fixes uses of this!
TESFile * TESNPC::GetFaceTint (TESNPC * a_this, undefined8 param_2, undefined8 param_3) 1403602b0 14036fb70 Uses TESFile::IsESL, sets bitmask to 0xFFF if ESL, 0xFFFFFF if not ESL
bool TESNPC::GenerateFaceGenData (TESNPC * a_this, undefined8 param_2) 140363210 140372b30 Uses TESFile::IsESL, but similar to GetFaceTint test appears unused?
void FUN_14038dcb0 (longlong param_1, char * param_2, TESForm__VFTable * param_3, TESForm * param_4) 14038dcb0 14039d660 Uses TESFile::IsESL, but SSE test looks unused?
bool TESDataHandler::FUN_1401703f0 (TESDataHandler * a_this, TESFile * a_file, bool a_isFirstPlugin, TESWorldSpace * a_worldspace) 14038dcb0 140180b80 Uses TESFile::AdjustFormIDFileIndex
bool TESFile::ReadFormHeader_14017ed70 (TESFile * param_1) 14017ed70 14018ead0 Uses TESFile::AdjustFormIDFileIndex
void FUN_1401957e0(uint *form_id,TESFile *param_2) 1401957e0 1401a5510 Uses TESFile::AdjustFormIDFileIndex
uint TESFile::FUN_14057cc20 (TESFile * param_1, uint param_2) 14057cc20 Uses TESFile::AdjustFormIDFileIndex
TESForm * papyrus__Game::GetFormFromFile_140972E10 (undefined8 a_vm, undefined4 a_stackID, undefined8 param_3, uint a_formid, char * a_modname) 140972e10 1409acca0 Uses TESFile::AdjustFormIDFileIndex
BGSSaveGameBuffer::sub_140585580 14057DDE0 140585580 Treat as SE, loop through regular files first, then small files afterwards and save their count/names
sub_1404B80A0 1404A8090 1404B80A0 Use only regular files in loop, ESLs ignored here in SE for some reason
sub_140585640 14057DF20 140585640 Loads and checks file names. Use handler->files instead of handler->loadedMods
TESFile * TESFile::FUN_14017f2d0 (TESFile * param_1, undefined4 param_2) 14017f2d0 14018f060 Copies a_this_00->SmallFileCompileIndex_47A = param_1->SmallFileCompileIndex_47A in SSE
BSTArrayHeapAllocator * TESFile::FUN_14017b000 (TESFile * param_1, longlong param_2) 14017b000 14018aeb0 Sets ESL record flag
undefined8 FUN_140c2c0c0 (void) 140c2c2bf 140c71186 Loads Plugins from plugins.txt. Needs to also add .esl
sub_14052D230 140536330 14052D230 Add ".ESL" check in addition to ESP/ESM
TESDataHandler__sub_14017E540 14016DBB0 14017E540 Add ".ESL" check in addition to ESP/ESM

Specific function discussion

TESNPC::GetFaceTint

Compare SSE vs VR

  if (a_this_00 != (TESFile *)0x0) {
    TESFile::IsESL_14017E160((TESFile *)a_this_00); // SSE function doesn't appear used?
    iVar4 = f_snprintf_1401423D0
                      (param_2,(char *)(param_3 & 0xffffffff),
                       "data\\Textures\\Actors\\Character\\FaceGenData\\FaceTint\\%s\\%08X.dds",
                       a_this_00->Name_58);
    a_this_00 = (TESFile *)CONCAT71((int7)(CONCAT44(extraout_var,iVar4) >> 8),1);
  }
  return a_this_00;

Assembly does a test but doesn't branch based on it?

       14036031d 8b 5b 14        MOV        EBX,dword ptr [RBX + 0x14]
       140360320 48 8b c8        MOV        a_this,RAX
       140360323 e8 38 de        CALL       TESFile::IsESL_14017E160                         bool IsESL_14017E160(TESFile * a
                 e1 ff
       140360328 84 c0           TEST       isESL,isESL
       14036032a 4c 8d 4f 58     LEA        R9,[RDI + 0x58]
       14036032e b9 ff ff        MOV        a_this,0xffffff
                 ff 00

VR:

  if (pTVar4 != (TESFile *)0x0) {
    iVar3 = f_snprintf_1401423D0
                      (param_2,(char *)(param_3 & 0xffffffff),
                       "data\\Textures\\Actors\\Character\\FaceGenData\\FaceTint\\%s\\%08X.dds",
                       pTVar4->Name_58);
    return (TESFile *)CONCAT71((int7)(CONCAT44(extraout_var,iVar3) >> 8),1);
  }
  return (TESFile *)0x0;
}

TESNPC::GenerateFaceGenData

SSE

  if (file != (TESFile *)0x0) {
    TESFile::IsESL_14017E160((TESFile *)file);
    f_snprintf_1401423D0
              (param_2,(char *)0x104,
               "Meshes\\Actors\\Character\\FaceGenData\\FaceGeom\\%s\\%08X.NIF",file->Name_58);
    return true;
  }
  return false;
                             LAB_14036327d                                   XREF[1]:     14036326b(j)  
       14036327d 8b 5b 14        MOV        EBX,dword ptr [RBX + 0x14]
       140363280 48 8b c8        MOV        a_this,file
       140363283 e8 d8 ae        CALL       TESFile::IsESL_14017E160                         bool IsESL_14017E160(TESFile * a
                 e1 ff
       140363288 84 c0           TEST       isESL,isESL
       14036328a 4c 8d 4f 58     LEA        R9,[RDI + 0x58]
       14036328e b9 ff ff        MOV        a_this,0xffffff
                 ff 00
       140363293 4c 8d 05        LEA        R8,[s_Meshes\Actors\Character\FaceGenD_1415a05   = "Meshes\\Actors\\Character\\Fa
                 56 d3 23 01

VR:

  if (pTVar3 == (TESFile *)0x0) {
    return false;
  }
  f_snprintf_1401423D0
            (param_2,(char *)0x104,"Meshes\\Actors\\Character\\FaceGenData\\FaceGeom\\%s\\%08X.NIF",
             pTVar3->Name_58);
  return true;