SRL Archive - MSI Suggestions

MSI Object loading and freeing methods


Daniel

2010-04-16 00:39:53

I got the FreeAll method done and whatnot.

Preliminary methods that should be in SCAR/Simba/SRL (only the first method (DeleteArrayIndex_Int) is required for my part to work):

{ Preliminary methods that should be included in (SCAR/Simba)/SRL }

// Made by Dan's The Man. Deletes specified Index from array and pushes to the left, reducing the length of the array by 1.
procedure DeleteArrayIndex_Int(var Arr: array of Integer; Index: Integer);
var
I, bI: Integer;
begin
bI := High(Arr) - 1;

if(not(InRange(Index, Low(Arr), bI + 1))) then
srl_Warn('DeleteArrayIndex_Int', 'Index (' + IntToStr(Index) + ') out of array range', warn_AllVersions);

for i := Index to bI do
Arr[i] := Arr[i + 1];

SetLength(Arr, bI + 1);
end;

procedure DeleteArrayIndex_Real(var Arr: array of Extended; Index: Integer);
var
I, bI: Integer;
begin
bI := High(Arr) - 1;

if(not(InRange(Index, Low(Arr), bI + 1))) then
srl_Warn('DeleteArrayIndex_Real', 'Index (' + IntToStr(Index) + ') out of array range', warn_AllVersions);

for i := Index to bI do
Arr[i] := Arr[i + 1];

SetLength(Arr, bI + 1);
end;

procedure DeleteArrayIndex_Str(var Arr: array of String; Index: Integer);
var
I, bI: Integer;
begin
bI := High(Arr) - 1;

if(not(InRange(Index, Low(Arr), bI + 1))) then
srl_Warn('DeleteArrayIndex_Str', 'Index (' + IntToStr(Index) + ') out of array range', warn_AllVersions);

for i := Index to bI do
Arr[i] := Arr[i + 1];

SetLength(Arr, bI + 1);
end;

procedure DeleteArrayIndex_Bool(var Arr: array of Boolean; Index: Integer);
var
I, bI: Integer;
begin
bI := High(Arr) - 1;

if(not(InRange(Index, Low(Arr), bI + 1))) then
srl_Warn('DeleteArrayIndex_Bool', 'Index (' + IntToStr(Index) + ') out of array range', warn_AllVersions);

for i := Index to bI do
Arr[i] := Arr[i + 1];

SetLength(Arr, bI + 1);
end;

And the MSI methods:

{ Constants defining loading and freeing methods of objects.
Purpose is self-explanatory }
const
MSI_Load_DTM = 0;
MSI_Load_Bitmap = 1;

MSI_Free_DTMsOnly = 0;
MSI_Free_BitmapsOnly = 1;
MSI_Free_All = 2;

{ The array which all MSI object are stored.
Supposed to be untouched by user/scripter }
var
LoadedInMemory: array[0..1] of array of Integer;

{******************************************************************************}
{ function MSIFromString(const WhatType: Byte; Str: String; warn_Type: }
{ ShortInt): Integer; }
{ By: Dan's The Man }
{ Description: Loads' an object into memory. }
{******************************************************************************}
function MSIFromString(const WhatType: Byte; Str: String; warn_Type: ShortInt): Integer;
var
ArrLnth: Integer;
begin

case (WhatType) of
0: Result := DTMFromString(Str);
1: Result := BitmapFromString2(True, Str);
else begin
Result := -1;
srl_Warn('MSIFromString', 'Invalid type identifier', warn_Type);

exit;
end;
end;

ArrLnth := Length(LoadedInMemory[WhatType]);
SetLength(LoadedInMemory[WhatType], ArrLnth + 1);
LoadedInMemory[WhatType][ArrLnth] := Result;

end;

{******************************************************************************}
{ procedure MSIFree(const WhatType: Byte; Handle: Integer; }
{ warn_Type: ShortInt); }
{ By: Dan's The Man }
{ Description: Frees' specified object from memory. }
{******************************************************************************}
procedure MSIFree(const WhatType: Byte; Handle: Integer; warn_Type: ShortInt);
var
Index, ArrLnth: Integer;
begin

if(not(InRange(WhatType, MSI_Free_DTMsOnly, MSI_Free_BitmapsOnly))) then
srl_Warn('MSIFree', 'Invalid type identifier to free', warn_Type);

ArrLnth := Length(LoadedInMemory[WhatType]);
for Index := (ArrLnth - 1) downto -1 do
if(LoadedInMemory[WhatType][Index] = Handle) then
break;

if(Index = -1) then
srl_Warn('MSIFree', 'Unable to find Handle in array. Will free normally.', warn_Warning) else
DeleteArrayIndex_Int(LoadedInMemory[WhatType], Index);

case (WhatType) of
0: FreeDTM(Handle);
1: FreeBitmap(Handle);
end;

end;

{******************************************************************************}
{ procedure MSIFreeAll(const WhatType: Byte; warn_Type: ShortInt); }
{ By: Dan's The Man }
{ Description: Frees' specified objects' type from memory. }
{******************************************************************************}
procedure MSIFreeAll(const WhatType: Byte; warn_Type: ShortInt);
var
i, bI, Count, _To: Integer;
begin

if(WhatType = 1) then
Count := 1 else
Count := 0;

if(WhatType = 2) then
_To := 1 else
_To := WhatType;

while (Count <= _To) do
begin
bI := High(LoadedInMemory[Count]);
for i := bI downto 0 do
MSIFree(Count, i, warn_Type);

Inc(Count);
end;

end;

Sir R. M8gic1an

2010-04-16 04:39:10

Errr….

I'm not sure that matches the exact concept that was being discussed but..

http://villavu.com/forum/showthread.php?t=56132

Here's what I had in mind:
[php]
var
LoadedDTMs: array of Boolean[0..x];
DTMArray: array of integer[0..x];


function MSI_LoadDTM(which: integer): integer;
begin

if LoadedDTMs[which] then
begin
Result := DTMArray[which];
exit;
end;

case which of
PICK_BRONZE: DTMArray[PICK_BRONZE] := DTMFromString('');
PICK_IRON: DTMArray[PICK_IRON] := DTMFromString('');
end;

LoadedDTMs[which] := true;
Result := DTMArray[which];
end;

Procedure MSI_FreeDTM(which: integer);
begin
FreeDTM(DTMArray[which]);
LoadedDTMs[which] := false;
end;
[/php]

~RM

mastaraymond

2010-04-16 07:08:56

From: Rasta Magician
Errr….

I'm not sure that matches the exact concept that was being discussed but..

http://villavu.com/forum/showthread.php?t=56132

Here's what I had in mind:
[php]
var
LoadedDTMs: array of Boolean[0..x];
DTMArray: array of integer[0..x];


function MSI_LoadDTM(which: integer): integer;
begin

if LoadedDTMs[which] then
begin
Result := DTMArray[which];
exit;
end;

case which of
PICK_BRONZE: DTMArray[PICK_BRONZE] := DTMFromString('');
PICK_IRON: DTMArray[PICK_IRON] := DTMFromString('');
end;

LoadedDTMs[which] := true;
Result := DTMArray[which];
end;

Procedure MSI_FreeDTM(which: integer);
begin
FreeDTM(DTMArray[which]);
LoadedDTMs[which] := false;
end;
[/php]

~RM

Yeah, that would prevent a mass leak, and keep the memory-usage quite small :).

Might want to do a range check on the Which parameter, accessing value -1 is never a good try :p.

Sir R. M8gic1an

2010-04-16 07:10:31

[php]
if which < 0 then
//warn blabla


case which of
//…
else
//msi warn blablaba
[/php]

Cheers Ray

~RM

mastaraymond

2010-04-16 07:11:16

From: Rasta Magician
[php]
case which of
//…
else
//msi warn blablaba
[/php]

~RM


[php]
if LoadedDTMs[which] then[/php]

In case which is invalid ^ will throw an exception there

Daniel

2010-04-16 07:34:06

From: Rasta Magician
Errr….

I'm not sure that matches the exact concept that was being discussed but..

http://villavu.com/forum/showthread.php?t=56132

Here's what I had in mind:
[php]
var
LoadedDTMs: array of Boolean[0..x];
DTMArray: array of integer[0..x];


function MSI_LoadDTM(which: integer): integer;
begin

if LoadedDTMs[which] then
begin
Result := DTMArray[which];
exit;
end;

case which of
PICK_BRONZE: DTMArray[PICK_BRONZE] := DTMFromString('');
PICK_IRON: DTMArray[PICK_IRON] := DTMFromString('');
end;

LoadedDTMs[which] := true;
Result := DTMArray[which];
end;

Procedure MSI_FreeDTM(which: integer);
begin
FreeDTM(DTMArray[which]);
LoadedDTMs[which] := false;
end;
[/php]

~RM

My one can be used globally and not for specific scripts. I tried my best as to what I could decipher from Coh3n's post and put it into practice.

But this is ultimately up to you, as is everything around here.

Sir R. M8gic1an

2010-04-16 07:46:02

[QUOTE=Dan's The Man;702633]My one can be used globally and not for specific scripts. I tried my best as to what I could decipher from Coh3n's post and put it into practice.

Oki… well yours seemed a bit over complicated and with possible leaks to me; Also, MSI aims to be modular for the sakes of organization, so loading and unloading of BMP & DTMs from one function seemed over-crowded to me.

But this is ultimately up to you, as is everything around here.


Ultimately… I guess. Although most of MSI has been done by the SLs with only bits of guidance by me. And then again, there are also times when I'm wrong.

~RM

Coh3n

2010-04-16 11:13:04

Dan, I'm really glad to see you helping out! :) That's why have you make thread, so things like this can be discussed. My mistake if I was unclear with the idea of how the system should work. I'm not saying your code is bad, or that it wouldn't work, it just seems a little over complicated for what we're trying to accomplish.

Generally the MSI functions are kept simple (excluding some of the object finding) and will pass one or two integer parameters, like in RM's example. Why don't you try to get his up and running?

@RM: Do we need a DTMArray? We already have an Array of TItem, and the DTM can just be called upon from there as I'm assuming the length of the LoadedDTM array will be equal to MSI_ITEM_COUNT.

Hmm, I was just thinking, what do we need these functions for exactly? Naum has already written four MSI_Free functions in ItemInfo.scar. I think we just need to make sure they're being called when items are loaded. Unless I'm missing something?

Sir R. M8gic1an

2010-04-18 06:08:51

From: Coh3n

@RM: Do we need a DTMArray? We already have an Array of TItem, and the DTM can just be called upon from there as I'm assuming the length of the LoadedDTM array will be equal to MSI_ITEM_COUNT.

Hmm, I was just thinking, what do we need these functions for exactly? Naum has already written four MSI_Free functions in ItemInfo.scar. I think we just need to make sure they're being called when items are loaded. Unless I'm missing something?


I dont have the SVN bookmarked on me atm, but if I remember correctly, we don't keep our TItem array.

meaning:
[php]
var
MyItem: TItem;
begin
for Item := AXE_RUNE DownTO AXE_BRONZE do
begin
MyItem := Load_Item(Item);
//here the DTM has already been loaded. Then without the DTM array…
//….
FreeDTM(Item.DTM);
// Otherwise you'll leak memory when you overwrite var Item
if Found then
break;
end;

/*
With the DTM Array you can just go through the loop,
And since you have the array, you'll never lose the refference to the DTM
And therefore never leak memory.

Also, When you Load a DTM, a bit of memory is leaked.
If you load DTMs very often = Big Leak

Meaning that if you call LoadItem often,
everytime you do, you'll be re-loading the DTM


And we'll be using DTMs often.
By using the array,
we never need to Reload them / Free them until we are really done with them
(eg switch skill) and therefore we'll barely lose any memory
*/
[/php]

Hope that made sense. Memory management is one of the things that I find most complex (and somewhat interesting) about programming.

Edit: I've just been looking through Naums functions, and the memory management there already seems to be good and without leaks. Have Ray / Wizz / Nava giving it a look just to be sure.

~RM

Coh3n

2010-04-18 12:10:54

From: Rasta Magician

Edit: I've just been looking through Naums functions, and the memory management there already seems to be good and without leaks. Have Ray / Wizz / Nava giving it a look just to be sure.

~RM

Yeah, that's what I was saying. My issue it that I'm not 100% sure that his freeing functions are being used when they're suppose to.

For example, in MSI_FindItemSlots, the item isn't freed. I don't know, but may explain why I kept getting access violation errors when dropping logs. That's all I could find right now, but there may be others. I've fixed it in the latest version.

I was also thinking, should we use a similar memory management system for Objects.scar? I'm not a wiz on this stuff, so I don't know if it's necessary since there's no bitmaps/DTMs in the object record.

Sir R. M8gic1an

2010-04-18 12:25:04

From: Coh3n
Yeah, that's what I was saying. My issue it that I'm not 100% sure that his freeing functions are being used when they're suppose to.

For example, in MSI_FindItemSlots, the item isn't freed. I don't know, but may explain why I kept getting access violation errors when dropping logs. That's all I could find right now, but there may be others. I've fixed it in the latest version.

I was also thinking, should we use a similar memory management system for Objects.scar? I'm not a wiz on this stuff, so I don't know if it's necessary since there's no bitmaps/DTMs in the object record.


I guess it's time we both read up on memory management then.. Can be quite important in MSI as it is quite a big project..

~RM

Coh3n

2010-04-18 12:32:31

From: Rasta Magician
I guess it's time we both read up on memory management then.. Can be quite important in MSI as it is quite a big project..

~RM

Probably a smart idea. :p

Sir R. M8gic1an

2010-04-18 12:59:17

From: Coh3n
Probably a smart idea. :p


The basic idea is everything that is assigned will use up some memory. So if we are going to use something more than once we better make sure it is stored somewhere we can always access it without having to re-load it. Especially with types.

But a second link to it probably wouldn't waste much memory. Not sure.

eg

[php]
MSI_Objs[AXE_RUNE] := Load_Obj(AXE_RUNE);
//uses a lot of memory
Obj := MSI_Objs[AXE_RUNE];
// uses little memory because it's only linking to something that is loaded elsewhere.
//Not sure if scar would make it point or make it reload tho….
[/php]

~RM

Coh3n

2010-04-18 13:41:43

Yeah I see what you're saying. What if we edited the function that loads the items:
[php]
function MSI_GetItem(ID: Integer) : Boolean;
begin
if (isItemLoaded(ID)) then
begin
MSI_Debug('MSI_GetItem', 'Item ID: ' + IntToStr(ID) + ' is already loaded!', DEBUG_FUNCTIONS);
Exit;
end else
case ID of
HATCHET_BRONZE:
//etc. etc.

end;
end;
[/php]
But then would that mean that we would take out all the FreeItems functions, and only call them when we're finished with them? Like switching skills like you said, or ending the script.

Sir R. M8gic1an

2010-04-18 13:46:09

From: Coh3n
Yeah I see what you're saying. What if we edited the function that loads the items:
[php]
function MSI_GetItem(ID: Integer) : Boolean;
begin
if (isItemLoaded(ID)) then
begin
MSI_Debug('MSI_GetItem', 'Item ID: ' + IntToStr(ID) + ' is already loaded!', DEBUG_FUNCTIONS);
Exit;
end else
case ID of
HATCHET_BRONZE:
//etc. etc.

end;
end;
[/php]
But then would that mean that we would take out all the FreeItems functions, and only call them when we're finished with them? Like switching skills like you said, or ending the script.


Sounds perfect.

We can just add a boolean to TItem

if MSI_Items[ID].Loaded then
debug stuff

~RM

Coh3n

2010-04-18 13:48:22

From: Rasta Magician
Sounds perfect.

~RM

Awesome.

Now that we've established what exactly to do, maybe someone will do it. ;)

Sir R. M8gic1an

2010-04-18 13:56:37

From: Coh3n
Awesome.

Now that we've established what exactly to do, maybe someone will do it. ;)


Is that a hint? Revising for Information Sytems exam here :p

~RM

Coh3n

2010-04-18 14:00:37

From: Rasta Magician
Is that a hint? Revising for Information Sytems exam here :p

~RM

Lol yes, but it wasn't meant for you. :p