|
@@ -23,6 +23,7 @@ extern LA MAIN;
|
|
|
const char* LA_UDF_EXTENSION_STRINGS[]={
|
|
|
"LA_UDF_EXTENSION_FLOAT32",
|
|
|
"LA_UDF_EXTENSION_RAW",
|
|
|
+ "LA_UDF_EXTENSION_QUICK_SEEK",
|
|
|
"",
|
|
|
};
|
|
|
|
|
@@ -2509,15 +2510,18 @@ void la_ReadBuffer(laUDF *udf, u64bit Size, void *Result){
|
|
|
}
|
|
|
void* la_ReadRaw(laUDF *udf, int* _sz){
|
|
|
int _size = la_ReadInt(udf);
|
|
|
- if (_size){
|
|
|
- void* data=calloc(1,_size);
|
|
|
- la_ReadBuffer(udf, _size, data);
|
|
|
- if(_sz) *_sz=_size;
|
|
|
- return data;
|
|
|
- } return 0;
|
|
|
+ if(_sz){
|
|
|
+ if (_size){
|
|
|
+ void* data=calloc(1,_size);
|
|
|
+ la_ReadBuffer(udf, _size, data);
|
|
|
+ if(_sz) *_sz=_size;
|
|
|
+ return data;
|
|
|
+ } return 0;
|
|
|
+ }else{
|
|
|
+ la_Seek(udf, la_Tell(udf)+_size); return 0;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-
|
|
|
void la_WriteSingleProperty(laUDF *udf, void *FromInstance, laProp *p){
|
|
|
la_WriteString(udf, p->Identifier);
|
|
|
}
|
|
@@ -2745,9 +2749,13 @@ void la_WriteEnumProp(laUDF *udf, laPropPack *pp){
|
|
|
}
|
|
|
void la_ReadRawProp(laUDF *udf, laPropPack *pp){
|
|
|
la_ReadShort(udf);//mark
|
|
|
- int _size=0;
|
|
|
- void* data=la_ReadRaw(udf,&_size);
|
|
|
- if (pp) laSetRaw(pp, data, _size); free(data);
|
|
|
+ if (pp) {
|
|
|
+ int _size=0;
|
|
|
+ void* data=la_ReadRaw(udf,&_size);
|
|
|
+ laSetRaw(pp, data, _size); free(data);
|
|
|
+ }else{
|
|
|
+ la_ReadRaw(udf,0);
|
|
|
+ }
|
|
|
}
|
|
|
void la_WriteRawProp(laUDF *udf, laPropPack *pp){
|
|
|
laProp *p = pp->LastPs->p;
|
|
@@ -2950,57 +2958,6 @@ void la_AddPostReadNode(void *Instance, laContainerPostReadFunc Func){
|
|
|
upr->Instance = Instance;
|
|
|
upr->Func = Func;
|
|
|
}
|
|
|
-laUDFContentNode *la_AppendUDFContentNode(laUDFContentInstance *Parent, laPropPack *ForMe, u64bit FileSeek){
|
|
|
- char FullPath[256]={0};
|
|
|
- laUDFContentNode *ucn = CreateNew(laUDFContentNode);
|
|
|
- FullPath[0] = 0;
|
|
|
-
|
|
|
- laProp *p = ForMe->LastPs->p;
|
|
|
-
|
|
|
- strSafeSet(&ucn->Identifier, p->Identifier);
|
|
|
- sprintf(FullPath, "%s.%s", Parent->Parent->FullPath->Ptr, p->Identifier);
|
|
|
- strSafeSet(&ucn->FullPath, FullPath);
|
|
|
- ucn->PP.Go = &ucn->FakePS;
|
|
|
- ucn->PP.LastPs = &ucn->FakePS;
|
|
|
- ucn->FakePS.p = p;
|
|
|
- ucn->FakePS.Type = U'.';
|
|
|
- ucn->PP.RawThis = &Parent->Parent->PP;
|
|
|
- ucn->Parent = Parent;
|
|
|
- ucn->FileSeek = FileSeek;
|
|
|
-
|
|
|
- lstAppendItem(&Parent->Children, ucn);
|
|
|
-
|
|
|
- return ucn;
|
|
|
-}
|
|
|
-laUDFContentInstance *la_AppendUDFContentInstance(laUDFContentNode *Parent, u64bit FileSeek){
|
|
|
- laUDFContentInstance *uci = CreateNew(laUDFContentInstance);
|
|
|
-
|
|
|
- uci->FileSeek = FileSeek;
|
|
|
- uci->Parent = Parent;
|
|
|
- strSafePrint(&uci->Identifier,"Instance at seek 0x%0x", FileSeek);
|
|
|
-
|
|
|
- lstAppendItem(&Parent->Instances, uci);
|
|
|
-
|
|
|
- return uci;
|
|
|
-}
|
|
|
-void la_DestroyUDFContentNodeTreeRecursive(laUDFContentNode *ucn, int FreeRoot){
|
|
|
- laUDFContentNode *ucni, *NextUCNI;
|
|
|
- laUDFContentInstance *ucii, *NextUCII;
|
|
|
- for (ucii = ucn->Instances.pFirst; ucii; ucii = NextUCII){
|
|
|
- NextUCII = ucii->Item.pNext;
|
|
|
- for (ucni = ucii->Children.pFirst; ucni; ucni = NextUCNI){
|
|
|
- NextUCNI = ucni->Item.pNext;
|
|
|
- strSafeDestroy(&ucii->Identifier);
|
|
|
- lstRemoveItem(&ucii->Children, ucni);
|
|
|
- la_DestroyUDFContentNodeTreeRecursive(ucni, 1);
|
|
|
- }
|
|
|
- lstRemoveItem(&ucn->Instances, ucii);
|
|
|
- FreeMem(ucii);
|
|
|
- }
|
|
|
- strSafeDestroy(&ucn->Identifier);
|
|
|
- strSafeDestroy(&ucn->FullPath);
|
|
|
- if (FreeRoot) FreeMem(ucn);
|
|
|
-}
|
|
|
|
|
|
void *la_GetReadDBInstNUID(char *ReferReadNUID){
|
|
|
if (!ReferReadNUID) return 0;
|
|
@@ -3058,7 +3015,7 @@ void la_LoadAdditionalRegistries(){
|
|
|
laManagedUDF* m;
|
|
|
logPrint("[INFO] Loading additional resource: %s\n",r->Path->Ptr);
|
|
|
laUDF* udf = laOpenUDF(r->Path->Ptr, 1, 0, &m);
|
|
|
- if (udf){ laExtractUDF(udf, m, LA_UDF_MODE_OVERWRITE, 0); laCloseUDF(udf); }else{ logPrint("[WARN] Can't open resource: %s\n",r->Path->Ptr); }
|
|
|
+ if (udf){ laExtractUDF(udf, m, LA_UDF_MODE_OVERWRITE); laCloseUDF(udf); }else{ logPrint("[WARN] Can't open resource: %s\n",r->Path->Ptr); }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -3176,13 +3133,16 @@ int la_ExtractFakeProp(laUDF *udf){
|
|
|
}
|
|
|
}
|
|
|
break;
|
|
|
+ case LA_PROP_RAW:
|
|
|
+ la_ReadRawProp(udf, 0);
|
|
|
+ break;
|
|
|
default:
|
|
|
ReadState = ReadState;
|
|
|
break;
|
|
|
}
|
|
|
return 0;
|
|
|
}
|
|
|
-int la_ExtractProp(laUDF *udf, laManagedUDF* mUDF, laPropPack *pp, void *ParentInst, int Mode, laUDFContentNode *Parent){
|
|
|
+int la_ExtractProp(laUDF *udf, laManagedUDF* mUDF, laPropPack *pp, void *ParentInst, int Mode){
|
|
|
laPropStep SubPS = {0};
|
|
|
laPropPack SubPP = {0};
|
|
|
char buf[LA_RAW_CSTR_MAX_LEN] = {0};
|
|
@@ -3199,7 +3159,6 @@ int la_ExtractProp(laUDF *udf, laManagedUDF* mUDF, laPropPack *pp, void *ParentI
|
|
|
int VariableNodeSize;
|
|
|
char NodeType[128]={0};
|
|
|
int EStatus = 0;
|
|
|
- laUDFContentInstance *uci;
|
|
|
real ReadF;
|
|
|
int ReadI;
|
|
|
int IsExceptionNode = 0;
|
|
@@ -3212,13 +3171,11 @@ int la_ExtractProp(laUDF *udf, laManagedUDF* mUDF, laPropPack *pp, void *ParentI
|
|
|
|
|
|
SubMode = la_ReadShort(udf);
|
|
|
if (SubMode == LA_UDF_SHARE_RESOURCE){
|
|
|
- if (!Parent){
|
|
|
- la_ReadString(udf, buf);
|
|
|
- laSetActiveInstance(p, pp->LastPs->UseInstance, la_FindSharedResouce(buf));
|
|
|
- }
|
|
|
+ la_ReadString(udf, buf);
|
|
|
+ laSetActiveInstance(p, pp->LastPs->UseInstance, la_FindSharedResouce(buf));
|
|
|
}elif (SubMode == LA_UDF_REFER){
|
|
|
Instance = la_ReadPointer(udf);
|
|
|
- if (Instance && !Parent && p->Offset>=0){
|
|
|
+ if (Instance && p->Offset>=0){
|
|
|
if (p->OffsetIsPointer) la_AddPtrSyncCommand(Instance, ParentInst, 0, p);
|
|
|
else la_AddDataInst(Instance, 0, ((BYTE *)pp->LastPs->UseInstance + p->Offset));
|
|
|
}
|
|
@@ -3226,7 +3183,7 @@ int la_ExtractProp(laUDF *udf, laManagedUDF* mUDF, laPropPack *pp, void *ParentI
|
|
|
char NUID[32]={0};
|
|
|
NUID[0] = 0;
|
|
|
la_ReadString(udf, NUID);
|
|
|
- if (NUID[0] && !Parent){
|
|
|
+ if (NUID[0]){
|
|
|
la_AddPtrSyncCommand(0, ParentInst, NUID, p);
|
|
|
}
|
|
|
}elif (SubMode == LA_UDF_COLLECTION){
|
|
@@ -3244,7 +3201,6 @@ int la_ExtractProp(laUDF *udf, laManagedUDF* mUDF, laPropPack *pp, void *ParentI
|
|
|
laPropIterator PI = {0};
|
|
|
|
|
|
ItemType = la_ReadShort(udf);
|
|
|
- if (Parent) uci = la_AppendUDFContentInstance(Parent, la_Tell(udf));
|
|
|
|
|
|
Instance = laGetInstance(p, pp->LastPs->UseInstance, &PI);
|
|
|
|
|
@@ -3252,7 +3208,7 @@ int la_ExtractProp(laUDF *udf, laManagedUDF* mUDF, laPropPack *pp, void *ParentI
|
|
|
|
|
|
if (ItemType == LA_UDF_HYPER_ITEM){
|
|
|
if (p->SubProp->Hyper == 2){
|
|
|
- if (!Parent && !IsExceptionNode) la_ReadHyperData(udf, Instance);
|
|
|
+ if (!IsExceptionNode) la_ReadHyperData(udf, Instance);
|
|
|
else la_ReadHyperData(udf, 0);
|
|
|
if(mUDF) memAssignRef(Instance, &((laMemNodeHyper*)memGetHead(Instance, 0))->FromFile, mUDF);
|
|
|
memMarkClean(Instance);
|
|
@@ -3260,16 +3216,16 @@ int la_ExtractProp(laUDF *udf, laManagedUDF* mUDF, laPropPack *pp, void *ParentI
|
|
|
if(Mode==LA_UDF_MODE_APPEND){ lstAppendPointer(&MAIN.RenewHyper2s,Instance); }
|
|
|
}
|
|
|
|
|
|
- if (!Parent && p->SubProp->PostRead) la_AddPostReadNode(Instance, p->SubProp->PostRead);
|
|
|
+ if (p->SubProp->PostRead) la_AddPostReadNode(Instance, p->SubProp->PostRead);
|
|
|
|
|
|
ReadInstance = la_ReadPointer(udf);
|
|
|
ReadState = la_ReadInt(udf);
|
|
|
|
|
|
- if (!Parent) ThisDBInst=Instance;
|
|
|
+ ThisDBInst=Instance;
|
|
|
|
|
|
PropNumPerItem = la_ReadShort(udf);
|
|
|
for (j = 0; j < PropNumPerItem; j++){
|
|
|
- int result; laUDFContentNode *ucn;
|
|
|
+ int result;
|
|
|
la_ReadString(udf, buf);
|
|
|
subp = la_PropLookup(&p->SubProp->Props, buf);
|
|
|
SubPP.RawThis = pp;
|
|
@@ -3277,17 +3233,12 @@ int la_ExtractProp(laUDF *udf, laManagedUDF* mUDF, laPropPack *pp, void *ParentI
|
|
|
SubPS.UseInstance = Instance;
|
|
|
if ((!subp) ||subp->UDFIgnore){la_ExtractFakeProp(udf); continue;}
|
|
|
if (subp&&!subp->SubProp){ subp->SubProp = la_ContainerLookup(((laSubProp *)subp)->TargetID); }
|
|
|
- if (subp&& Parent && subp->PropertyType == LA_PROP_SUB){
|
|
|
- if (!subp->UDFIsRefer && !IsExceptionNode){
|
|
|
- ucn = la_AppendUDFContentNode(uci, &SubPP, la_Tell(udf));
|
|
|
- result = la_ExtractProp(udf, mUDF, &SubPP, ThisDBInst, Mode, ucn);
|
|
|
- }else{ result = la_ExtractFakeProp(udf);}
|
|
|
- }else{
|
|
|
- result = (IsExceptionNode||!subp) ? result = la_ExtractFakeProp(udf) : la_ExtractProp(udf, mUDF, &SubPP, ThisDBInst, Mode, Parent);
|
|
|
- }
|
|
|
+
|
|
|
+ result = (IsExceptionNode||!subp) ? result = la_ExtractFakeProp(udf) : la_ExtractProp(udf, mUDF, &SubPP, ThisDBInst, Mode);
|
|
|
+
|
|
|
EStatus = result ? result : EStatus;
|
|
|
}
|
|
|
- if (!Parent && p->SubProp->PostReadIm) p->SubProp->PostReadIm(Instance);
|
|
|
+ if (p->SubProp->PostReadIm) p->SubProp->PostReadIm(Instance);
|
|
|
}else{
|
|
|
if(Mode==LA_UDF_MODE_APPEND && p->UDFIsSingle){
|
|
|
logPrint("[Note] Mode is APPEND but property '%s' only allows one instance, will overwrite.\n", p->Identifier);
|
|
@@ -3302,8 +3253,6 @@ int la_ExtractProp(laUDF *udf, laManagedUDF* mUDF, laPropPack *pp, void *ParentI
|
|
|
|
|
|
ItemType = la_ReadShort(udf);
|
|
|
|
|
|
- if (Parent) uci = la_AppendUDFContentInstance(Parent, la_Tell(udf));
|
|
|
-
|
|
|
if(p->UDFReadProgress){ laShowProgress((real)i/NumItems,-1); } //printf("add pc %s\n",pc->Identifier);
|
|
|
|
|
|
if(pc==LA_PC_SOCKET_OUT || pc==LA_PC_SOCKET_IN){ laGraphRequestRebuild(); }
|
|
@@ -3312,7 +3261,7 @@ int la_ExtractProp(laUDF *udf, laManagedUDF* mUDF, laPropPack *pp, void *ParentI
|
|
|
if (udf){
|
|
|
int IsItem=((laSubProp*)p)->ListHandleOffset?1:0;
|
|
|
RealSize = RealSize ? RealSize : p->SubProp->NodeSize;
|
|
|
- if (!Parent && !IsExceptionNode){
|
|
|
+ if (!IsExceptionNode){
|
|
|
if (p->UDFIsSingle && (pp->EndInstance=laGetActiveInstanceStrict(pp->LastPs->p,pp->LastPs->UseInstance))){
|
|
|
Instance = pp->EndInstance; la_ResetInstance(Instance, pc, IsItem); replaced=1;
|
|
|
}
|
|
@@ -3340,14 +3289,14 @@ int la_ExtractProp(laUDF *udf, laManagedUDF* mUDF, laPropPack *pp, void *ParentI
|
|
|
else la_ReadHyperData(udf, 0);
|
|
|
if(Mode==LA_UDF_MODE_APPEND){ lstAppendPointer(&MAIN.RenewHyper2s,Instance); }
|
|
|
}
|
|
|
- if (!Parent && !IsExceptionNode){
|
|
|
+ if (!IsExceptionNode){
|
|
|
if (pc->PostRead) la_AddPostReadNode(Instance, pc->PostRead);
|
|
|
}
|
|
|
|
|
|
ReadInstance = la_ReadPointer(udf);
|
|
|
ReadState = la_ReadInt(udf);
|
|
|
|
|
|
- if (!Parent && !IsExceptionNode && !replaced){
|
|
|
+ if (!IsExceptionNode && !replaced){
|
|
|
la_AddDataInst(ReadInstance, pc->Hyper == 2 ? ((laMemNodeHyper *)memGetHead(Instance,0))->NUID.String : 0, Instance);
|
|
|
}
|
|
|
ThisDBInst = Instance;
|
|
@@ -3359,23 +3308,18 @@ int la_ExtractProp(laUDF *udf, laManagedUDF* mUDF, laPropPack *pp, void *ParentI
|
|
|
subp = la_PropLookup(&pc->Props, buf);
|
|
|
if ((!subp) || subp->UDFIgnore) la_ExtractFakeProp(udf);
|
|
|
else{
|
|
|
- int result; laUDFContentNode *ucn;
|
|
|
+ int result;
|
|
|
ThisSeek = la_Tell(udf);
|
|
|
SubPP.RawThis = pp; SubPS.p = subp; SubPS.UseInstance = Instance;
|
|
|
la_EnsureSubTarget(subp, 0);
|
|
|
- if (Parent && subp->PropertyType == LA_PROP_SUB && subp->SubProp){
|
|
|
- if (!subp->UDFIsRefer && !IsExceptionNode){
|
|
|
- ucn = la_AppendUDFContentNode(uci, &SubPP, ThisSeek);
|
|
|
- result = la_ExtractProp(udf, mUDF, &SubPP, ThisDBInst, Mode, ucn);
|
|
|
- }else{ result = la_ExtractFakeProp(udf); }
|
|
|
- }else{
|
|
|
- result = IsExceptionNode ? la_ExtractFakeProp(udf) : la_ExtractProp(udf, mUDF, &SubPP, ThisDBInst, Mode, Parent);
|
|
|
- }
|
|
|
+
|
|
|
+ result = IsExceptionNode ? la_ExtractFakeProp(udf) : la_ExtractProp(udf, mUDF, &SubPP, ThisDBInst, Mode);
|
|
|
+
|
|
|
EStatus = result ? result : EStatus;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (!Parent && !IsExceptionNode && !replaced){
|
|
|
+ if (!IsExceptionNode && !replaced){
|
|
|
if (pc->PostReadIm) pc->PostReadIm(Instance);
|
|
|
if (pp->LastPs->UseInstance){
|
|
|
if (!p->UDFIsSingle){
|
|
@@ -3398,30 +3342,18 @@ int la_ExtractProp(laUDF *udf, laManagedUDF* mUDF, laPropPack *pp, void *ParentI
|
|
|
break;
|
|
|
case LA_PROP_INT:
|
|
|
case LA_PROP_ARRAY | LA_PROP_INT:
|
|
|
- ReadI = la_ReadIntProp(udf, Parent ? 0 : pp);
|
|
|
- if (Parent && p->Tag & LA_AS_IDENTIFIER){
|
|
|
- sprintf(buf, "%d", ReadI); strSafeSet(&((laUDFContentInstance *)Parent->Instances.pLast)->Identifier, buf);
|
|
|
- }
|
|
|
+ ReadI = la_ReadIntProp(udf, pp);
|
|
|
break;
|
|
|
case LA_PROP_FLOAT:
|
|
|
case LA_PROP_ARRAY | LA_PROP_FLOAT:
|
|
|
- ReadF = la_ReadFloatProp(udf, Parent ? 0 : pp);
|
|
|
- if (Parent && p->Tag & LA_AS_IDENTIFIER){
|
|
|
- sprintf(buf, "%lf", ReadF); strSafeSet(&((laUDFContentInstance *)Parent->Instances.pLast)->Identifier, buf);
|
|
|
- }
|
|
|
+ ReadF = la_ReadFloatProp(udf, pp);
|
|
|
break;
|
|
|
case LA_PROP_STRING:
|
|
|
- if (Parent && p->Tag & LA_AS_IDENTIFIER){
|
|
|
- la_ReadStringPropAsIdentifier(udf, buf); strSafeSet(&((laUDFContentInstance *)Parent->Instances.pLast)->Identifier, buf);
|
|
|
- }else{
|
|
|
- la_ReadStringProp(udf, Parent ? 0 : pp);
|
|
|
- }
|
|
|
+ la_ReadStringProp(udf, pp);
|
|
|
break;
|
|
|
case LA_PROP_ENUM:
|
|
|
case LA_PROP_ARRAY | LA_PROP_ENUM:
|
|
|
- la_ReadEnumProp(udf, Parent ? 0 : pp, buf);
|
|
|
- if (Parent && p->Tag & LA_AS_IDENTIFIER){
|
|
|
- strSafeSet(&((laUDFContentInstance *)Parent->Instances.pLast)->Identifier, buf); }
|
|
|
+ la_ReadEnumProp(udf, pp, buf);
|
|
|
break;
|
|
|
case LA_PROP_RAW:
|
|
|
la_ReadRawProp(udf, pp);
|
|
@@ -3442,6 +3374,31 @@ int la_RematchPointers(int Mode){
|
|
|
while(inst=lstPopPointer(&MAIN.RenewHyper2s)){ laMemNodeHyper* h=memGetHead(inst,0);memMakeHyperData(h);memAssignRef(h,&h->FromFile,0); }
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+int la_WriteHyperRecords(laUDF *udf){
|
|
|
+ int i = 0;
|
|
|
+ u64bit CountSeek = la_Tell(udf);
|
|
|
+ u64bit EndSeek;
|
|
|
+ laUDFHyperRecordItem *hri;
|
|
|
+ laMemNodeHyper* h;
|
|
|
+ la_WriteLong(udf, 0);
|
|
|
+ while (hri = lstPopItem(&udf->HyperRecords)){
|
|
|
+ h=memGetHead(hri->HyperUserMem, 0);
|
|
|
+ la_WriteString(udf, h->NUID.String);
|
|
|
+ if(hri->pc) la_WriteString(udf, hri->pc->Identifier); else la_WriteString(udf, "");
|
|
|
+ la_WritePointer(udf, hri->Seek);
|
|
|
+ i++; memFree(hri);
|
|
|
+ }
|
|
|
+ EndSeek = la_Tell(udf);
|
|
|
+ la_Seek(udf, CountSeek); la_WriteLong(udf, i); la_Seek(udf, EndSeek);
|
|
|
+
|
|
|
+ return i;
|
|
|
+}
|
|
|
+int la_WritePropQuickSeek(laUDF *udf){
|
|
|
+ for(laUDFPropSegment* ps=udf->PropsToOperate.pFirst;ps;ps=ps->Item.pNext){
|
|
|
+ la_WriteString(udf,SSTR(ps->Path)); la_WriteLong(udf,ps->WriteQuickSeek);
|
|
|
+ }
|
|
|
+}
|
|
|
int laPackUDF(laUDF *udf, int UseInstanceList, int DoBackup){
|
|
|
laUDFPropSegment *ps;
|
|
|
short NumSegments = 0;
|
|
@@ -3481,39 +3438,51 @@ int laPackUDF(laUDF *udf, int UseInstanceList, int DoBackup){
|
|
|
|
|
|
udf->CurrentH2Instance=udf->H2Instances.pFirst;
|
|
|
|
|
|
- while (ps = lstPopItem(&udf->PropsToOperate)){
|
|
|
+ for(laUDFPropSegment* ps=udf->PropsToOperate.pFirst;ps;ps=ps->Item.pNext){
|
|
|
printf(" %-15s\n", ps->Path ? ps->Path->Ptr : ps->PPP->LastPs->p->Identifier);
|
|
|
+ ps->WriteQuickSeek = la_Tell(udf);
|
|
|
la_WriteProp(udf, ps->PPP ? ps->PPP : &ps->PP, ps->PPP ? 1 : 0, UseInstanceList);
|
|
|
- la_FreePropStepCache(ps->PP.Go);
|
|
|
- strSafeDestroy(&ps->Path);
|
|
|
- FreeMem(ps);
|
|
|
}
|
|
|
logPrint("[ALL DONE]\n\n");
|
|
|
|
|
|
nuidActualSeek = la_Tell(udf);
|
|
|
|
|
|
+ la_WritePropQuickSeek(udf);
|
|
|
la_WriteHyperRecords(udf);
|
|
|
|
|
|
u64bit ActualSize=la_Tell(udf);
|
|
|
|
|
|
- la_Seek(udf, RefPos);
|
|
|
- la_WriteLong(udf, udf->TotalRefs);
|
|
|
-
|
|
|
- la_Seek(udf, nuidSeekRef);
|
|
|
- la_WritePointer(udf, nuidActualSeek);
|
|
|
-
|
|
|
- la_Seek(udf, SizeAndExt);
|
|
|
- la_WritePointer(udf, (ActualSize&(0x0000ffffffffffff))<<16);
|
|
|
+ la_Seek(udf, RefPos); la_WriteLong(udf, udf->TotalRefs);
|
|
|
+ la_Seek(udf, nuidSeekRef); la_WritePointer(udf, nuidActualSeek);
|
|
|
+ la_Seek(udf, SizeAndExt); la_WritePointer(udf, ((ActualSize&(0x0000ffffffffffff))<<16)|LA_UDF_EXTENSIONS_ENABLED);
|
|
|
|
|
|
udf->Modified = 0;
|
|
|
|
|
|
+ while(ps = lstPopItem(&udf->PropsToOperate)){
|
|
|
+ la_FreePropStepCache(ps->PP.Go);
|
|
|
+ strSafeDestroy(&ps->Path);
|
|
|
+ FreeMem(ps);
|
|
|
+ }
|
|
|
+
|
|
|
laCloseUDF(udf);
|
|
|
|
|
|
laHideProgress();
|
|
|
|
|
|
return 1;
|
|
|
}
|
|
|
-int laExtractUDF(laUDF *udf, laManagedUDF* mUDF, int Mode, laListHandle *Parent){
|
|
|
+
|
|
|
+void laExtractProp(laUDF *udf, char* Path){
|
|
|
+ laUDFPropSegment *ps = CreateNew(laUDFPropSegment);
|
|
|
+ strSafeSet(&ps->Path, Path);
|
|
|
+}
|
|
|
+int la_PropIsSelected(laUDF* udf, char* Path){
|
|
|
+ if(!udf->PropsToOperate.pFirst) return 1;
|
|
|
+ for(laUDFPropSegment* ps=udf->PropsToOperate.pFirst;ps;ps=ps->Item.pNext){
|
|
|
+ if(strSame(SSTR(ps->Path),Path)) return 1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+int laExtractUDF(laUDF *udf, laManagedUDF* mUDF, int Mode){
|
|
|
char Identifier[9] = {0};
|
|
|
char buf[1024]={0};
|
|
|
short Version, NumSegments;
|
|
@@ -3524,7 +3493,6 @@ int laExtractUDF(laUDF *udf, laManagedUDF* mUDF, int Mode, laListHandle *Parent)
|
|
|
int EStatus = 0;
|
|
|
u64bit SeekRef;
|
|
|
int IsPart;
|
|
|
- laUDFContentNode *ucni = Parent;
|
|
|
|
|
|
ma_device_stop(&MAIN.Audio->AudioDevice);
|
|
|
if(MAIN.InitArgs.HasAudio) laSpinLock(&MAIN.Audio->AudioStatusLock);
|
|
@@ -3535,7 +3503,7 @@ int laExtractUDF(laUDF *udf, laManagedUDF* mUDF, int Mode, laListHandle *Parent)
|
|
|
|
|
|
// file size verification and extension switches.
|
|
|
u64bit verification=la_ReadPointer(udf);
|
|
|
- u64bit FileSize=verification>>16; int Extensions=verification&0xffff;
|
|
|
+ u64bit FileSize=verification>>16; int Extensions=verification&LA_UDF_ALL_EXTENSIONS;
|
|
|
if(FileSize && FileSize<la_FileSize(udf)){ logPrintNew("UDF verification failed for %s\n", udf->FileName->Ptr); return 0; }
|
|
|
|
|
|
/*udf->TotalRefs = */ la_ReadLong(udf);
|
|
@@ -3543,58 +3511,81 @@ int laExtractUDF(laUDF *udf, laManagedUDF* mUDF, int Mode, laListHandle *Parent)
|
|
|
la_ReadLong(udf); //seek mark
|
|
|
SeekRef = la_ReadPointer(udf);
|
|
|
|
|
|
- logPrintNew("Extracting UDF %s:\n", udf->FileName->Ptr);
|
|
|
+ logPrintNew("Extracting UDF [0x%x] %s:\n", udf->Extensions, udf->FileName->Ptr);
|
|
|
|
|
|
//MAIN.NextPendingPointer = 0;
|
|
|
//MAIN.PendingPointers = CreateNewBuffer(laUDFPointerRecord, udf->TotalRefs);
|
|
|
|
|
|
//SubPP.LastPs = &SubP;
|
|
|
|
|
|
- if (!udf->PropsToOperate.pFirst){ //Extract All
|
|
|
- for (i = 0; i < NumSegments; i++){
|
|
|
- laUDFContentNode *ucn;
|
|
|
- laUDFContentInstance *uci;
|
|
|
- void *dbi = 0;
|
|
|
- int result;
|
|
|
- int LastOffset;
|
|
|
- la_ReadString(udf, buf);
|
|
|
- LastOffset = strlen(buf) - 1;
|
|
|
- buf[LastOffset] = buf[LastOffset] == U'.' ? 0 : buf[LastOffset];
|
|
|
- logPrint(" Prop Segment \"%s\" ...\n", buf);
|
|
|
- la_GetPropFromPath(&SubPP, 0, buf, 0);
|
|
|
- la_StepPropPack(&SubPP);
|
|
|
- if (Parent){
|
|
|
- ucni = CreateNew(laUDFContentNode);
|
|
|
- la_GetPropFromPath(&ucni->PP, 0, buf, 0);
|
|
|
- la_StepPropPack(&ucni->PP);
|
|
|
- strSafeSet(&ucni->FullPath, buf);
|
|
|
- strSafeSet(&ucni->Identifier, buf);
|
|
|
- ucni->FileSeek = la_Tell(udf);
|
|
|
- lstAppendItem(Parent, ucni);
|
|
|
- }
|
|
|
- dbi = SubPP.EndInstance; //la_GetWriteDBInst(SubPP.EndInstance);
|
|
|
- result = (SubPP.LastPs&&SubPP.LastPs->p)?
|
|
|
- la_ExtractProp(udf, mUDF, &SubPP, dbi, Mode, ucni):
|
|
|
- la_ExtractFakeProp(udf);
|
|
|
- EStatus = result ? result : EStatus;
|
|
|
- laNotifyUsersPP(&SubPP);
|
|
|
- logPrint(" [Done]\n", buf);
|
|
|
- la_FreePropStepCache(SubPP.Go);
|
|
|
- SubPP.Go = 0;
|
|
|
- }
|
|
|
+ for (i = 0; i < NumSegments; i++){
|
|
|
+ void *dbi = 0;
|
|
|
+ int result, LastOffset, selected=0;
|
|
|
+ la_ReadString(udf, buf);
|
|
|
+ LastOffset = strlen(buf) - 1;
|
|
|
+ buf[LastOffset] = buf[LastOffset] == U'.' ? 0 : buf[LastOffset];
|
|
|
+ logPrint(" Prop Segment \"%s\" ...", buf);
|
|
|
+ selected = la_PropIsSelected(udf, buf);
|
|
|
+ la_GetPropFromPath(&SubPP, 0, buf, 0);
|
|
|
+ la_StepPropPack(&SubPP);
|
|
|
+ dbi = SubPP.EndInstance; //la_GetWriteDBInst(SubPP.EndInstance);
|
|
|
+ result = (SubPP.LastPs&&SubPP.LastPs->p&&selected)?
|
|
|
+ la_ExtractProp(udf, mUDF, &SubPP, dbi, Mode):
|
|
|
+ la_ExtractFakeProp(udf);
|
|
|
+ EStatus = result ? result : EStatus;
|
|
|
+ //if(SubPP.LastPs->p->PropertyType!=LA_PROP_RAW){
|
|
|
+ // laNotifyUsersPP(&SubPP);
|
|
|
+ //}
|
|
|
+ logPrint(" [Done]\n", buf);
|
|
|
+ la_FreePropStepCache(SubPP.Go);
|
|
|
+ SubPP.Go = 0;
|
|
|
}
|
|
|
|
|
|
la_RematchPointers(Mode);
|
|
|
-
|
|
|
+
|
|
|
laHideProgress();
|
|
|
-
|
|
|
+
|
|
|
MAIN.IsReadingUDF = 0;
|
|
|
|
|
|
+ laUDFPropSegment* ps; while (ps = lstPopItem(&udf->PropsToOperate)){ strSafeDestroy(&ps->Path); FreeMem(ps); }
|
|
|
+
|
|
|
if(MAIN.InitArgs.HasAudio) laSpinUnlock(&MAIN.Audio->AudioStatusLock);
|
|
|
|
|
|
return EStatus;
|
|
|
}
|
|
|
|
|
|
+int laExtractQuickRaw(FILE* fp, char* path, uint8_t** buf, size_t* size){
|
|
|
+ laUDF _udf={0},*udf=&_udf; udf->DiskFile = fp;
|
|
|
+ char str[128];
|
|
|
+ char Identifier[32];
|
|
|
+ la_Seek(udf,0);
|
|
|
+ la_ReadBuffer(udf, sizeof(LA_UDF_IDENTIFIER) - 1, Identifier);
|
|
|
+ u64bit verification=la_ReadPointer(udf);
|
|
|
+ u64bit FileSize=verification>>16; int Extensions=verification&LA_UDF_ALL_EXTENSIONS;
|
|
|
+ if(FileSize && FileSize<la_FileSize(udf)){ return 0; }
|
|
|
+ if(!(Extensions & LA_UDF_EXTENSION_QUICK_SEEK)){ return 0; }
|
|
|
+
|
|
|
+ /*udf->TotalRefs = */ la_ReadLong(udf);
|
|
|
+ short NumSegments = la_ReadShort(udf);
|
|
|
+ la_ReadLong(udf); //seek mark
|
|
|
+ off_t SeekRef = la_ReadPointer(udf);
|
|
|
+
|
|
|
+ la_Seek(udf,SeekRef);
|
|
|
+
|
|
|
+ for(int i=0;i<NumSegments;i++){
|
|
|
+ la_ReadString(udf,str);
|
|
|
+ int Seek = la_ReadLong(udf);
|
|
|
+ if(strSame(str,path)){
|
|
|
+ la_Seek(udf,Seek);
|
|
|
+ la_ReadString(udf, str); // prop name
|
|
|
+ la_ReadShort(udf);// raw mark
|
|
|
+ void* data=la_ReadRaw(udf,size);
|
|
|
+ *buf=data; if(data){ return 1; }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
|
|
|
laManagedUDF* la_FindManagedUDF(char* FileName){
|
|
|
for(laManagedUDF* m=MAIN.ManagedUDFs.pFirst;m;m=m->Item.pNext){
|
|
@@ -3617,16 +3608,28 @@ void la_MakeDummyManagedUDF(){
|
|
|
MAIN.DummyManageUDFSingleForce=memAcquire(sizeof(laManagedUDF)); strSafeSet(&MAIN.DummyManageUDFSingleForce->BaseName, "< Force >");
|
|
|
}
|
|
|
}
|
|
|
-void laSaveProp(char* path){
|
|
|
+laManagedSaveProp* laSaveProp(char* path){
|
|
|
if(!path || !path[0]) return; laManagedSaveProp* msp=0;
|
|
|
for(laManagedSaveProp* m=MAIN.ManagedSaveProps.pFirst;m;m=m->Item.pNext){
|
|
|
if(!strcmp(m->Path->Ptr,path)){ msp=m; break; }
|
|
|
}
|
|
|
if(!msp){ msp=memAcquireSimple(sizeof(laManagedSaveProp)); lstAppendItem(&MAIN.ManagedSaveProps, msp); }
|
|
|
strSafeSet(&msp->Path, path);
|
|
|
+ return msp;
|
|
|
+}
|
|
|
+void laSaveAlongside(laManagedSaveProp* parent, char* path){
|
|
|
+ if(!path || !path[0] || !parent) return; laManagedSaveProp* msp=0;
|
|
|
+ for(laManagedSaveProp* m=parent->SaveAlongside.pFirst;m;m=m->Item.pNext){
|
|
|
+ if(!strcmp(m->Path->Ptr,path)){ msp=m; break; }
|
|
|
+ }
|
|
|
+ if(!msp){ msp=memAcquireSimple(sizeof(laManagedSaveProp)); lstAppendItem(&parent->SaveAlongside, msp); }
|
|
|
+ strSafeSet(&msp->Path, path);
|
|
|
}
|
|
|
void laClearSaveProp(){
|
|
|
- laManagedSaveProp* m; while(m=lstPopItem(&MAIN.ManagedSaveProps)) { strSafeDestroy(&m->Path); memFree(m); }
|
|
|
+ laManagedSaveProp* m; while(m=lstPopItem(&MAIN.ManagedSaveProps)) {
|
|
|
+ laManagedSaveProp* ma; while(ma=lstPopItem(&m->SaveAlongside)){ strSafeDestroy(&ma->Path); memFree(ma); }
|
|
|
+ strSafeDestroy(&m->Path); memFree(m);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
int la_ScanForModifiedRecursive(laPropPack* pp, int ReturnIfAnyMod, int ReturnIfAnyEmpty, int* rempty, int RegisterToUDF){
|
|
@@ -3673,7 +3676,12 @@ int laRegisterModifications(int ReturnIfAnyMod, int ReturnIfAnyEmpty, int* rempt
|
|
|
result|=la_ScanForModifiedRecursive(&PP, ReturnIfAnyMod, ReturnIfAnyEmpty, rempty, RegisterToUDF);
|
|
|
for(laManagedUDF* m=MAIN.ManagedUDFs.pFirst;m;m=m->Item.pNext){
|
|
|
if(!m->udf)continue;
|
|
|
- if(m->udf->HasInstances){ laWriteProp(m->udf,msp->Path->Ptr); m->udf->HasInstances=0; }
|
|
|
+ if(m->udf->HasInstances){ laWriteProp(m->udf,SSTR(msp->Path));
|
|
|
+ for(laManagedSaveProp* am=msp->SaveAlongside.pFirst;am;am=am->Item.pNext){
|
|
|
+ laWriteProp(m->udf,SSTR(am->Path));
|
|
|
+ }
|
|
|
+ m->udf->HasInstances=0;
|
|
|
+ }
|
|
|
}
|
|
|
if((ReturnIfAnyMod||ReturnIfAnyEmpty)&&result)return result;
|
|
|
la_FreePropStepCache(PP.Go);
|
|
@@ -3717,26 +3725,15 @@ void la_ReadOwnHyperItems(laUDF *udf, laUDFRegistry* r){
|
|
|
} else {logPrint("Duplicated Resource: %s | %s\n",uid.String,name);}
|
|
|
}
|
|
|
}
|
|
|
-int la_WriteHyperRecords(laUDF *udf){
|
|
|
- int i = 0;
|
|
|
- u64bit CountSeek = la_Tell(udf);
|
|
|
- u64bit EndSeek;
|
|
|
- laUDFHyperRecordItem *hri;
|
|
|
- laMemNodeHyper* h;
|
|
|
- la_WriteLong(udf, 0);
|
|
|
- while (hri = lstPopItem(&udf->HyperRecords)){
|
|
|
- h=memGetHead(hri->HyperUserMem, 0);
|
|
|
- la_WriteString(udf, h->NUID.String);
|
|
|
- if(hri->pc) la_WriteString(udf, hri->pc->Identifier); else la_WriteString(udf, "");
|
|
|
- la_WritePointer(udf, hri->Seek);
|
|
|
- i++; memFree(hri);
|
|
|
+int la_ReadPropQuickSeek(laUDF *udf){
|
|
|
+ char* buf[128];
|
|
|
+ for(int i=0;i<udf->NumSegmets;i++){
|
|
|
+ laUDFPropQuickSeek *qs = memAcquireSimple(sizeof(laUDFPropQuickSeek));
|
|
|
+ la_ReadString(udf,buf); strSafeSet(&qs->Path,buf);
|
|
|
+ qs->QuickSeek = la_ReadLong(udf);
|
|
|
+ lstAppendItem(&udf->QuickSeeks,qs);
|
|
|
+ logPrint(" QuickSeek 0x%x %s\n",qs->QuickSeek,SSTR(qs->Path));
|
|
|
}
|
|
|
- EndSeek = la_Tell(udf);
|
|
|
- la_Seek(udf, CountSeek);
|
|
|
- la_WriteLong(udf, i);
|
|
|
- la_Seek(udf, EndSeek);
|
|
|
-
|
|
|
- return i;
|
|
|
}
|
|
|
|
|
|
laUDF *laOpenUDF(char *FileName, int ReadToMemory, laUDFRegistry* ReadRegistryRef, laManagedUDF** UseManaged){
|
|
@@ -3764,6 +3761,13 @@ laUDF *laOpenUDF(char *FileName, int ReadToMemory, laUDFRegistry* ReadRegistryRe
|
|
|
}
|
|
|
|
|
|
extensions = la_ReadPointer(udf);
|
|
|
+ udf->Extensions = extensions & LA_UDF_ALL_EXTENSIONS;
|
|
|
+ if((udf->Extensions | LA_UDF_EXTENSIONS_ENABLED)!=LA_UDF_EXTENSIONS_ENABLED){
|
|
|
+ logPrint("Unsupported UDF extension 0x%x (0x%x enabled), it's probably saved with a newer version of the program.\n",
|
|
|
+ udf->Extensions,LA_UDF_EXTENSIONS_ENABLED);
|
|
|
+ laCloseUDF(udf);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
udf->TotalRefs = la_ReadLong(udf); //total refs
|
|
|
udf->NumSegmets = la_ReadShort(udf); //num segments
|
|
@@ -3772,6 +3776,9 @@ laUDF *laOpenUDF(char *FileName, int ReadToMemory, laUDFRegistry* ReadRegistryRe
|
|
|
la_Seek(udf, SeekRef);
|
|
|
|
|
|
if(ReadRegistryRef){
|
|
|
+ if(udf->Extensions & LA_UDF_EXTENSION_QUICK_SEEK){
|
|
|
+ la_ReadPropQuickSeek(udf);
|
|
|
+ }
|
|
|
la_ReadOwnHyperItems(udf, ReadRegistryRef);
|
|
|
}
|
|
|
|
|
@@ -3785,11 +3792,13 @@ void laCloseUDF(laUDF *udf){
|
|
|
laUDFOwnHyperItem *ohi;
|
|
|
laUDFHyperRecordItem *hri;
|
|
|
laUDFPropSegment *ps;
|
|
|
+ laUDFPropQuickSeek *qs;
|
|
|
|
|
|
if (udf->DiskFile){ fclose(udf->DiskFile); udf->DiskFile=0; };
|
|
|
|
|
|
while (lstPopPointer(&udf->OwnHyperItems));
|
|
|
while (lstPopPointer(&udf->HyperRecords));
|
|
|
+ while (qs = lstPopItem(&udf->QuickSeeks)){ strSafeDestroy(&qs->Path); memFree(qs); }
|
|
|
|
|
|
if(udf->CurrentH2Instance){ logPrint("[WARN] udf->CurrentH2Instance!=0 after UDF packing.\n"); udf->CurrentH2Instance=0; }
|
|
|
|