diff --git a/fpPS4.lpi b/fpPS4.lpi
index 8703b2d..4b1905a 100644
--- a/fpPS4.lpi
+++ b/fpPS4.lpi
@@ -615,6 +615,7 @@
+
diff --git a/kernel/ps4_queue.pas b/kernel/ps4_queue.pas
index b2eaaf1..b6f83bd 100644
--- a/kernel/ps4_queue.pas
+++ b/kernel/ps4_queue.pas
@@ -559,7 +559,7 @@ begin
begin
Result:=0;
node:=P^;
- HAMT_delete32(@eq^.FUserEvents.hamt,id);
+ HAMT_delete32(@eq^.FUserEvents.hamt,id,nil);
_free_kevent_node(node);
end else
begin
diff --git a/ps4_elf.pas b/ps4_elf.pas
index 4f6e2cf..4ad2d8e 100644
--- a/ps4_elf.pas
+++ b/ps4_elf.pas
@@ -1054,6 +1054,7 @@ begin
DT_NEEDED:
begin
mu.value:=entry.d_un.d_val;
+ _md:=Default(TMODULE);
_md.strName:=PChar(@pStrTable[mu.name_offset]);
_add_need(_md.strName);
Writeln('DT_NEEDED :',_md.strName); //import filename
@@ -1061,6 +1062,7 @@ begin
DT_SCE_MODULE_INFO:
begin
mu.value:=entry.d_un.d_val;
+ _md:=Default(TMODULE);
_md.strName:=PChar(@pStrTable[mu.name_offset]);
_md.Import:=False;
Writeln('DT_SCE_MODULE_INFO:',_md.strName,':',HexStr(mu.id,4)); //current module name
@@ -1070,6 +1072,7 @@ begin
DT_SCE_NEEDED_MODULE:
begin
mu.value:=entry.d_un.d_val;
+ _md:=Default(TMODULE);
_md.strName:=PChar(@pStrTable[mu.name_offset]);
_md.Import:=True;
Writeln('DT_SCE_NEEDED_MODULE :',HexStr(mu.id,4),':',_md.strName); //import module name
@@ -1078,6 +1081,7 @@ begin
DT_SCE_IMPORT_LIB:
begin
lu.value:=entry.d_un.d_val;
+ lib:=Default(TLIBRARY);
lib.strName:=PChar(@pStrTable[lu.name_offset]);
lib.Import:=True;
Writeln('DT_SCE_IMPORT_LIB :',HexStr(lu.id,4),':',lib.strName); //import lib name
@@ -1086,6 +1090,7 @@ begin
DT_SCE_EXPORT_LIB:
begin
lu.value:=entry.d_un.d_val;
+ lib:=Default(TLIBRARY);
lib.strName:=PChar(@pStrTable[lu.name_offset]);
lib.Import:=False;
Writeln('DT_SCE_EXPORT_LIB :',HexStr(lu.id,4),':',lib.strName); //export libname
diff --git a/ps4_program.pas b/ps4_program.pas
index 1f29166..b7b15f9 100644
--- a/ps4_program.pas
+++ b/ps4_program.pas
@@ -416,14 +416,19 @@ end;
procedure TElf_node._set_lib(id:Word;lib:TLIBRARY);
var
- i:SizeInt;
+ p,i:SizeInt;
plib:PLIBRARY;
begin
i:=Length(aLibs);
if (i<=id) then
begin
i:=id+1;
+ p:=Length(aLibs);
SetLength(aLibs,i);
+ for p:=p to i-1 do
+ begin
+ aLibs[p]:=nil;
+ end;
end;
plib:=aLibs[id];
if (plib=nil) then plib:=AllocMem(SizeOf(TLIBRARY));
@@ -434,14 +439,19 @@ end;
procedure TElf_node._set_lib_attr(u:TLibraryValue);
var
- i:SizeInt;
+ p,i:SizeInt;
plib:PLIBRARY;
begin
i:=Length(aLibs);
if (i<=u.id) then
begin
i:=u.id+1;
+ p:=Length(aLibs);
SetLength(aLibs,i);
+ for p:=p to i-1 do
+ begin
+ aLibs[p]:=nil;
+ end;
end;
plib:=aLibs[u.id];
if (plib=nil) then plib:=AllocMem(SizeOf(TLIBRARY));
diff --git a/rtl/hamt.pas b/rtl/hamt.pas
index 24e242a..bdd7c1a 100644
--- a/rtl/hamt.pas
+++ b/rtl/hamt.pas
@@ -1,7 +1,8 @@
{ Simplified implementation of HAMT (Hash Array Mapped Trie) with 32bit/64bit hash key.
Specific hash functions and collision resolution are outside the scope of
this implementation and can be implemented on top of it.
- Copyright (C) 2021 Red_prig
+
+ Copyright (C) 2023 Red_prig
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
@@ -37,7 +38,7 @@ function HAMT_clear32(hamt:THAMT;cb:Tfree_data_cb;userdata:Pointer):Boolean;
function HAMT_destroy32(hamt:THAMT;cb:Tfree_data_cb;userdata:Pointer):Boolean;
function HAMT_search32(hamt:THAMT;key:DWORD):PPointer; //mutable link to data
function HAMT_insert32(hamt:THAMT;key:DWORD;data:Pointer):PPointer; //mutable link to data
-function HAMT_delete32(hamt:THAMT;key:DWORD):Pointer; //data
+function HAMT_delete32(hamt:THAMT;key:DWORD;old:PPointer):Boolean; //data
function HAMT_traverse32(hamt:THAMT;cb:Tfree_data_cb;userdata:Pointer):Boolean;
function HAMT_create64:THAMT;
@@ -45,7 +46,7 @@ function HAMT_clear64(hamt:THAMT;cb:Tfree_data_cb;userdata:Pointer):Boolean;
function HAMT_destroy64(hamt:THAMT;cb:Tfree_data_cb;userdata:Pointer):Boolean;
function HAMT_search64(hamt:THAMT;key:QWORD):PPointer; //mutable link to data
function HAMT_insert64(hamt:THAMT;key:QWORD;data:Pointer):PPointer; //mutable link to data
-function HAMT_delete64(hamt:THAMT;key:QWORD):Pointer; //data
+function HAMT_delete64(hamt:THAMT;key:QWORD;old:PPointer):Boolean; //data
function HAMT_traverse64(hamt:THAMT;cb:Tfree_data_cb;userdata:Pointer):Boolean;
type
@@ -97,6 +98,52 @@ type
TSTUB_HAMT32=array[0..HAMT32.root_size-1] of THAMTNode32;
TSTUB_HAMT64=array[0..HAMT64.root_size-1] of THAMTNode64;
+ //iterators
+
+ PHAMT_Iterator32=^THAMT_Iterator32;
+ THAMT_Iterator32=packed object
+ type
+ PStackNode=^TStackNode;
+ TStackNode=packed record
+ bnode,cnode,enode:PHAMTNode32;
+ end;
+ var
+ cpos:Ptruint;
+ data:array[0..HAMT32.stack_max+1] of TStackNode;
+ end;
+
+ PHAMT_Iterator64=^THAMT_Iterator64;
+ THAMT_Iterator64=packed object
+ type
+ PStackNode=^TStackNode;
+ TStackNode=packed record
+ bnode,cnode,enode:PHAMTNode64;
+ end;
+ var
+ cpos:Ptruint;
+ data:array[0..HAMT64.stack_max+1] of TStackNode;
+ end;
+
+//32
+
+function HAMT_first32(hamt:THAMT;i:PHAMT_Iterator32):Boolean;
+function HAMT_last32(hamt:THAMT;i:PHAMT_Iterator32):Boolean;
+
+function HAMT_next32(i:PHAMT_Iterator32):Boolean;
+function HAMT_prev32(i:PHAMT_Iterator32):Boolean;
+
+function HAMT_get_value32(i:PHAMT_Iterator32;v:PPointer):Boolean;
+
+//64
+
+function HAMT_first64(hamt:THAMT;i:PHAMT_Iterator64):Boolean;
+function HAMT_last64(hamt:THAMT;i:PHAMT_Iterator64):Boolean;
+
+function HAMT_next64(i:PHAMT_Iterator64):Boolean;
+function HAMT_prev64(i:PHAMT_Iterator64):Boolean;
+
+function HAMT_get_value64(i:PHAMT_Iterator64;v:PPointer):Boolean;
+
implementation
function IsSubTrie32(n:PHAMTNode32):Boolean; inline;
@@ -165,16 +212,14 @@ end;
function GetBitMapSize32(BitKey:DWORD):DWORD; inline;
begin
+ if (BitKey=0) then Exit(0);
Result:=PopCnt(BitKey);
- Result:=Result and HAMT32.node_mask;
- if (Result=0) then Result:=HAMT32.node_size;
end;
function GetBitMapSize64(BitKey:QWORD):QWORD; inline;
begin
+ if (BitKey=0) then Exit(0);
Result:=PopCnt(BitKey);
- Result:=Result and HAMT64.node_mask;
- if (Result=0) then Result:=HAMT64.node_size;
end;
function BitIsNotSet32(BitKey,keypart:DWORD):Boolean; inline;
@@ -208,15 +253,41 @@ begin
end;
function GetMapPos32(BitKey,keypart:DWORD):DWORD; inline;
+var
+ k:DWORD;
begin
- Result:=PopCnt(BitKey and (not DWORD(HAMT32.const_max shl keypart)));
- Result:=Result and HAMT32.node_mask; //Clamp
+ k:=BitKey and (not DWORD(HAMT32.const_max shl keypart));
+ if (k=0) then Exit(0);
+ Result:=PopCnt(k);
end;
function GetMapPos64(BitKey,keypart:QWORD):QWORD; inline;
+var
+ k:QWORD;
begin
- Result:=PopCnt(BitKey and (not QWORD(HAMT64.const_max shl keypart)));
- Result:=Result and HAMT64.node_mask; //Clamp
+ k:=BitKey and (not QWORD(HAMT64.const_max shl keypart));
+ if (k=0) then Exit(0);
+ Result:=PopCnt(k);
+end;
+
+function GetRootKeyMask32(key:DWORD):DWORD; inline;
+begin
+ Result:=key and HAMT32.root_mask;
+end;
+
+function GetNodeKeyMask32(key,bits:DWORD):DWORD; inline;
+begin
+ Result:=(key shr bits) and HAMT32.node_mask;
+end;
+
+function GetRootKeyMask64(key:QWORD):QWORD; inline;
+begin
+ Result:=key and HAMT64.root_mask;
+end;
+
+function GetNodeKeyMask64(key,bits:QWORD):QWORD; inline;
+begin
+ Result:=(key shr bits) and HAMT64.node_mask;
end;
function HAMT_create32:THAMT;
@@ -240,6 +311,7 @@ var
data:array[0..HAMT32.stack_max] of TStackNode;
Size:DWORD;
begin
+ if (node^.BaseValue=nil) then Exit;
if IsSubTrie32(node) then
begin
curr:=@data;
@@ -295,6 +367,7 @@ var
data:array[0..HAMT64.stack_max] of TStackNode;
Size:QWORD;
begin
+ if (node^.BaseValue=nil) then Exit;
if IsSubTrie64(node) then
begin
curr:=@data;
@@ -376,6 +449,7 @@ var
data:array[0..HAMT32.stack_max] of TStackNode;
Size:QWORD;
begin
+ if (node^.BaseValue=nil) or (cb=nil) then Exit;
if IsSubTrie32(node) then
begin
curr:=@data;
@@ -405,15 +479,13 @@ begin
end;
end else
begin
- if (cb<>nil) then
- cb(GetValue32(curr^.cnode),userdata);
+ cb(GetValue32(curr^.cnode),userdata);
Inc(curr^.cnode);
end;
until false;
end else
begin
- if (cb<>nil) then
- cb(GetValue32(node),userdata);
+ cb(GetValue32(node),userdata);
end;
end;
@@ -428,6 +500,7 @@ var
data:array[0..HAMT64.stack_max] of TStackNode;
Size:QWORD;
begin
+ if (node^.BaseValue=nil) or (cb=nil) then Exit;
if IsSubTrie64(node) then
begin
curr:=@data;
@@ -457,15 +530,13 @@ begin
end;
end else
begin
- if (cb<>nil) then
- cb(GetValue64(curr^.cnode),userdata);
+ cb(GetValue64(curr^.cnode),userdata);
Inc(curr^.cnode);
end;
until false;
end else
begin
- if (cb<>nil) then
- cb(GetValue64(node),userdata);
+ cb(GetValue64(node),userdata);
end;
end;
@@ -515,7 +586,8 @@ begin
keypartbits:=HAMT32.root_bits;
- keypart:=key and HAMT32.root_mask;
+ keypart:=GetRootKeyMask32(key);
+
node:=@PHAMTNode32(hamt)[keypart];
if (node^.BaseValue=nil) then Exit(nil);
@@ -532,7 +604,7 @@ begin
//Subtree: look up in bitmap
Assert(keypartbits no match
@@ -556,7 +628,8 @@ begin
keypartbits:=HAMT64.root_bits;
- keypart:=key and HAMT64.root_mask;
+ keypart:=GetRootKeyMask64(key);
+
node:=@PHAMTNode64(hamt)[keypart];
if (node^.BaseValue=nil) then Exit(nil);
@@ -573,7 +646,7 @@ begin
//Subtree: look up in bitmap
Assert(keypartbits no match
@@ -595,9 +668,13 @@ var
begin
if (hamt=nil) then Exit(nil);
+ Assert(data<>nil);
+ Assert((PtrUint(data) and 1)=0);
+
keypartbits:=HAMT32.root_bits;
- keypart:=key and HAMT32.root_mask;
+ keypart:=GetRootKeyMask32(key);
+
node:=@PHAMTNode32(hamt)[keypart];
if (node^.BaseValue=nil) then
@@ -621,8 +698,9 @@ begin
repeat
Assert(keypartbitsnil);
+ Assert((PtrUint(data) and 1)=0);
+
keypartbits:=HAMT64.root_bits;
- keypart:=key and HAMT64.root_mask;
+ keypart:=GetRootKeyMask64(key);
node:=@PHAMTNode64(hamt)[keypart];
if (node^.BaseValue=nil) then
@@ -740,8 +823,9 @@ begin
repeat
Assert(keypartbitsnil) then
+ begin
+ //save value
+ old^:=GetValue32(node);
+ end;
+
+ //clear
node^:=Default(THAMTNode32);
- if (prev=nil) then Exit;
- node:=prev;
+ if (curr=@data) then Exit; //not in stack
+
+ //up
+ Dec(curr);
+ node:=curr^;
+
+ keypartbits:=keypartbits-HAMT32.node_bits;
node^.BitMapKey:=UnSetBitInSet32(node^.BitMapKey,keypart);
+
Size:=GetBitMapSize32(node^.BitMapKey);
oldnodes:=GetSubTrie32(node);
+ if (Size=0) then
+ begin
+ repeat
+ //free
+ node^:=Default(THAMTNode32);
+ FreeMem(oldnodes);
+
+ if (curr=@data) then Exit; //not in stack
+
+ //up
+ Dec(curr);
+ node:=curr^;
+
+ keypartbits:=keypartbits-HAMT32.node_bits;
+
+ keypart:=GetNodeKeyMask32(key,keypartbits);
+ Map:=GetMapPos32(node^.BitMapKey,keypart);
+
+ node^.BitMapKey:=UnSetBitInSet32(node^.BitMapKey,keypart);
+
+ Size:=GetBitMapSize32(node^.BitMapKey);
+ oldnodes:=GetSubTrie32(node);
+
+ shrink;
+
+ until (Size<>0);
+ end else
if (Size=1) then
begin
- if (Map=0) then
+ if not copyup then
begin
- node^:=oldnodes[1];
- end else
- begin
- node^:=oldnodes[0];
+ shrink;
end;
- FreeMem(oldnodes);
- end else
- if ((2*Size*SizeOf(THAMTNode32))<=MemSize(oldnodes)) then
- begin
- newnodes:=AllocMem(Size*SizeOf(THAMTNode32));
- Assert((PtrUint(newnodes) and 1)=0);
- Move(oldnodes[0] ,newnodes[0] ,Map*SizeOf(THAMTNode32));
- Move(oldnodes[Map+1],newnodes[Map],(Size-Map)*SizeOf(THAMTNode32));
- FreeMem(oldnodes);
- SetSubTrie32(node,newnodes);
end else
begin
- Move(oldnodes[Map+1],oldnodes[Map],(Size-Map)*SizeOf(THAMTNode32));
+ shrink;
end;
Exit;
end else
- Exit(nil);
+ begin
+ //non exists?
+ Exit;
+ end;
end;
+
//Subtree: look up in bitmap
Assert(keypartbits no match
+ Exit; // bit is 0 in bitmap -> no match
Map:=GetMapPos32(node^.BitMapKey,keypart);
- // Go down a level */
- prev:=node;
+ // Go down a level
+ curr^:=node;
+ Inc(curr);
+
node:=@GetSubTrie32(node)[Map];
keypartbits:=keypartbits+HAMT32.node_bits;
until false;
end;
-function HAMT_delete64(hamt:THAMT;key:QWORD):Pointer;
+function HAMT_delete64(hamt:THAMT;key:QWORD;old:PPointer):Boolean;
var
- prev,node,oldnodes,newnodes:PHAMTNode64;
+ node,oldnodes:PHAMTNode64;
keypart,Map,Size:QWORD;
keypartbits:QWORD;
+
+ curr:^PHAMTNode64;
+ data:array[0..HAMT64.stack_max] of PHAMTNode64;
+
+ function copyup:Boolean;
+ var
+ tmp:PHAMTNode64;
+ begin
+ if (Map=0) then
+ begin
+ tmp:=@oldnodes[1];
+ end else
+ begin
+ tmp:=@oldnodes[0];
+ end;
+
+ Result:=not IsSubTrie64(tmp);
+
+ if Result then
+ begin
+ //copy up
+ node^:=tmp^;
+ FreeMem(oldnodes);
+ end;
+ end;
+
+ procedure shrink;
+ var
+ newnodes:PHAMTNode64;
+ begin
+ if ((2*Size*SizeOf(THAMTNode64))<=MemSize(oldnodes)) then //shrink mem?
+ begin
+ newnodes:=AllocMem(Size*SizeOf(THAMTNode64));
+ Assert((PtrUint(newnodes) and 1)=0);
+ Move(oldnodes[0] ,newnodes[0] ,Map*SizeOf(THAMTNode64));
+ Move(oldnodes[Map+1],newnodes[Map],(Size-Map)*SizeOf(THAMTNode64));
+ FreeMem(oldnodes);
+ SetSubTrie64(node,newnodes);
+ oldnodes:=newnodes;
+ end else
+ begin
+ Move(oldnodes[Map+1],oldnodes[Map],(Size-Map)*SizeOf(THAMTNode64));
+ end;
+ end;
+
begin
- if (hamt=nil) then Exit(nil);
+ Result:=False;
+ if (hamt=nil) then Exit;
+
+ curr:=@data;
keypartbits:=HAMT64.root_bits;
- prev:=nil;
Map:=0;
- keypart:=key and HAMT64.root_mask;
+ keypart:=GetRootKeyMask64(key);
+
node:=@PHAMTNode64(hamt)[keypart];
- if (node^.BaseValue=nil) then Exit(nil);
+ if (node^.BaseValue=nil) then Exit;
repeat
if not IsSubTrie64(node) then
begin
if (node^.BitMapKey=key) then
begin
- Result:=GetValue64(node);
+ Result:=True;
+ if (old<>nil) then
+ begin
+ //save value
+ old^:=GetValue64(node);
+ end;
+
+ //clear
node^:=Default(THAMTNode64);
- if (prev=nil) then Exit;
- node:=prev;
+ if (curr=@data) then Exit; //not in stack
+
+ //up
+ Dec(curr);
+ node:=curr^;
+
+ keypartbits:=keypartbits-HAMT64.node_bits;
node^.BitMapKey:=UnSetBitInSet64(node^.BitMapKey,keypart);
+
Size:=GetBitMapSize64(node^.BitMapKey);
oldnodes:=GetSubTrie64(node);
+ if (Size=0) then
+ begin
+ repeat
+ //free
+ node^:=Default(THAMTNode64);
+ FreeMem(oldnodes);
+
+ if (curr=@data) then Exit; //not in stack
+
+ //up
+ Dec(curr);
+ node:=curr^;
+
+ keypartbits:=keypartbits-HAMT64.node_bits;
+
+ keypart:=GetNodeKeyMask64(key,keypartbits);
+ Map:=GetMapPos64(node^.BitMapKey,keypart);
+
+ node^.BitMapKey:=UnSetBitInSet64(node^.BitMapKey,keypart);
+
+ Size:=GetBitMapSize64(node^.BitMapKey);
+ oldnodes:=GetSubTrie64(node);
+
+ shrink;
+
+ until (Size<>0);
+ end else
if (Size=1) then
begin
- if (Map=0) then
+ if not copyup then
begin
- node^:=oldnodes[1];
- end else
- begin
- node^:=oldnodes[0];
+ shrink;
end;
- FreeMem(oldnodes);
- end else
- if ((2*Size*SizeOf(THAMTNode64))<=MemSize(oldnodes)) then
- begin
- newnodes:=AllocMem(Size*SizeOf(THAMTNode64));
- Assert((PtrUint(newnodes) and 1)=0);
- Move(oldnodes[0] ,newnodes[0] ,Map*SizeOf(THAMTNode64));
- Move(oldnodes[Map+1],newnodes[Map],(Size-Map)*SizeOf(THAMTNode64));
- FreeMem(oldnodes);
- SetSubTrie64(node,newnodes);
end else
begin
- Move(oldnodes[Map+1],oldnodes[Map],(Size-Map)*SizeOf(THAMTNode64));
+ shrink;
end;
Exit;
end else
- Exit(nil);
+ begin
+ //non exists?
+ Exit;
+ end;
end;
+
//Subtree: look up in bitmap
Assert(keypartbits no match
+ Exit; // bit is 0 in bitmap -> no match
Map:=GetMapPos64(node^.BitMapKey,keypart);
- // Go down a level */
- prev:=node;
+ // Go down a level
+ curr^:=node;
+ Inc(curr);
+
node:=@GetSubTrie64(node)[Map];
keypartbits:=keypartbits+HAMT64.node_bits;
until false;
end;
+//iterator32
+
+function _HAMT_next32(i:PHAMT_Iterator32):Boolean;
+var
+ curr:THAMT_Iterator32.PStackNode;
+ node:PHAMTNode32;
+ Size:QWORD;
+begin
+ Result:=False;
+
+ curr:=@i^.data[i^.cpos];
+
+ repeat
+ if (curr^.cnode>=curr^.enode) then
+ begin
+ //up
+ if (i^.cpos=0) then Exit;
+ Dec(i^.cpos);
+ Dec(curr);
+ //next
+ Inc(curr^.cnode);
+ Continue;
+ end;
+ if IsSubTrie32(curr^.cnode) then
+ begin
+ //down
+ node:=curr^.cnode;
+ Inc(i^.cpos);
+ Inc(curr);
+ Size:=GetBitMapSize32(node^.BitMapKey);
+ With curr^ do
+ begin
+ //new
+ bnode:=GetSubTrie32(node);
+ cnode:=bnode;
+ enode:=@bnode[Size];
+ end;
+ end else
+ begin
+ Exit(True);
+ end;
+ until false;
+end;
+
+//
+
+function _HAMT_prev32(i:PHAMT_Iterator32):Boolean;
+var
+ curr:THAMT_Iterator32.PStackNode;
+ node:PHAMTNode32;
+ Size:QWORD;
+begin
+ Result:=False;
+
+ curr:=@i^.data[i^.cpos];
+
+ repeat
+ if (curr^.cnode=Length(i^.data)) then Exit;
+
+ curr:=@i^.data[i^.cpos];
+
+ if (curr^.cnode=Length(i^.data)) then Exit;
+
+ curr:=@i^.data[i^.cpos];
+
+ if (curr^.cnode>=curr^.bnode) then
+ begin
+ //prev
+ Dec(curr^.cnode);
+ end;
+
+ Result:=_HAMT_prev32(i);
+end;
+
+function HAMT_get_value32(i:PHAMT_Iterator32;v:PPointer):Boolean;
+var
+ curr:THAMT_Iterator32.PStackNode;
+begin
+ Result:=False;
+ if (i=nil) or (v=nil) then Exit;
+ if (i^.cpos>=Length(i^.data)) then Exit;
+
+ curr:=@i^.data[i^.cpos];
+
+ if IsSubTrie32(curr^.cnode) then Exit;
+
+ v^:=GetValue32(curr^.cnode);
+ Result:=True;
+end;
+
+//iterator64
+
+function _HAMT_next64(i:PHAMT_Iterator64):Boolean;
+var
+ curr:THAMT_Iterator64.PStackNode;
+ node:PHAMTNode64;
+ Size:QWORD;
+begin
+ Result:=False;
+
+ curr:=@i^.data[i^.cpos];
+
+ repeat
+ if (curr^.cnode>=curr^.enode) then
+ begin
+ //up
+ if (i^.cpos=0) then Exit;
+ Dec(i^.cpos);
+ Dec(curr);
+ //next
+ Inc(curr^.cnode);
+ Continue;
+ end;
+ if (curr^.cnode^.BaseValue=nil) then //space
+ begin
+ Inc(curr^.cnode);
+ Continue;
+ end;
+ if IsSubTrie64(curr^.cnode) then
+ begin
+ //down
+ node:=curr^.cnode;
+ Inc(i^.cpos);
+ Inc(curr);
+ Size:=GetBitMapSize64(node^.BitMapKey);
+ With curr^ do
+ begin
+ //new
+ bnode:=GetSubTrie64(node);
+ cnode:=bnode;
+ enode:=@bnode[Size];
+ end;
+ end else
+ begin
+ Exit(True);
+ end;
+ until false;
+end;
+
+//
+
+function _HAMT_prev64(i:PHAMT_Iterator64):Boolean;
+var
+ curr:THAMT_Iterator64.PStackNode;
+ node:PHAMTNode64;
+ Size:QWORD;
+begin
+ Result:=False;
+
+ curr:=@i^.data[i^.cpos];
+
+ repeat
+ if (curr^.cnode=Length(i^.data)) then Exit;
+
+ curr:=@i^.data[i^.cpos];
+
+ if (curr^.cnode=Length(i^.data)) then Exit;
+
+ curr:=@i^.data[i^.cpos];
+
+ if (curr^.cnode>=curr^.bnode) then
+ begin
+ //prev
+ Dec(curr^.cnode);
+ end;
+
+ Result:=_HAMT_prev64(i);
+end;
+
+function HAMT_get_value64(i:PHAMT_Iterator64;v:PPointer):Boolean;
+var
+ curr:THAMT_Iterator64.PStackNode;
+begin
+ Result:=False;
+ if (i=nil) or (v=nil) then Exit;
+ if (i^.cpos>=Length(i^.data)) then Exit;
+
+ curr:=@i^.data[i^.cpos];
+
+ if IsSubTrie64(curr^.cnode) then Exit;
+
+ v^:=GetValue64(curr^.cnode);
+ Result:=True;
+end;
+
+//
+
+
end.
diff --git a/rtl/ps4_handles.pas b/rtl/ps4_handles.pas
index 6840818..67b95dc 100644
--- a/rtl/ps4_handles.pas
+++ b/rtl/ps4_handles.pas
@@ -175,7 +175,7 @@ begin
Result:=False;
if (Keymax_key) then Exit;
rwlock_wrlock(FLock);
- Pointer(data):=HAMT_delete32(FHAMT,Key);
+ HAMT_delete32(FHAMT,Key,@data);
if Assigned(data) then
begin
data.Release;
diff --git a/src/audiodec/ps4_libsceaudiodec.pas b/src/audiodec/ps4_libsceaudiodec.pas
index e2a430c..c89408f 100644
--- a/src/audiodec/ps4_libsceaudiodec.pas
+++ b/src/audiodec/ps4_libsceaudiodec.pas
@@ -158,7 +158,7 @@ end;
procedure _DeleteDecoder(const handle:SceAudiodecHandle);
begin
spin_lock(hamt_lock);
- HAMT_delete32(@AudiodecHamt,handle);
+ HAMT_delete32(@AudiodecHamt,handle,nil);
spin_unlock(hamt_lock);
end;
diff --git a/src/ps4_libsceavplayer.pas b/src/ps4_libsceavplayer.pas
index 0a78d06..565d96d 100644
--- a/src/ps4_libsceavplayer.pas
+++ b/src/ps4_libsceavplayer.pas
@@ -377,7 +377,7 @@ var
data:TAvPlayerInfo;
begin
spin_lock(hamt_lock);
- data:=TAvPlayerInfo(HAMT_delete64(@AvHandleHamt,handle));
+ HAMT_delete64(@AvHandleHamt,handle,@data);
spin_unlock(hamt_lock);
if (data<>nil) then