Mod Showroom

 Reply to this postStart new topic

[ASI] SuperVars (featuring Objective-SCM)

Deji
post Mar 2 2013, 04:01 AM
Post #1


Coding like a Rockstar!

Group Icon

Posts: 1,468
From: ???
Joined: 28-May 09



Download

Please avoid "wotzit" questions, as the readme (available on the download page) explains just about everything. There are demo scripts provided with the download. SuperVars is heavily used in The Black Market Mod, which is why I'm releasing it now. I've had SuperVars for about a year now, so it's heavily tested, I just kept it to myself for a while... Selfish.


And, here is a bonus: https://pastebin.com/46ayUR24

I call this Objective-SCM (difficulty: Brainfuck). Wotzit? It's a relatively low-level objective-oriented implementation for CLEO 4 (though it would only take replacing ALLOCATE_MEMORY to make it CLEO 3-friendly). Once you understand the example scripts given with SuperVars, this isn't too much to handle when using it but concentrate on the low-level source and your eyes may burn a bit. The source is pretty well commented, though. It's not included as part of the SuperVars example scripts as I consider it worthy of a bit more light, however this is a great example of SuperVars' power for this topic (its just best to see the example scripts with the download first).

Objective-SCM allows you to create your own virtual 'types' and create C++-like objects with them. For example:
CONST
CAnimal__SizeOf = 12
CHuman__SizeOf = 4
CDog__SizeOf = 0
CCat__Sizeof = 0
END

:CAnimal // type()
RET 3 @CAnimal_ctor 0 CAnimal__SizeOf

:CHuman // (inherits CAnimal)
0A8E: 0@ = CAnimal__SizeOf + CHumanSizeOf
RET 3 @CHuman_ctor 0 0@

:CDog // (inherits CAnimal)
0A8E: 0@ = CAnimal__SizeOf + CDogSizeOf
RET 3 @CDog_ctor 0 0@

:CCat // (inherits CAnimal)
0A8E: 0@ = CAnimal__SizeOf + CCatSizeOf
RET 3 @CCat_ctor 0 0@


@CCat, for example, can now be passed to @new (just like the C++ new, see the Objective-SCM :new source for more info) which initialises a 12 byte structure, or an array of 12 byte structures:

CALL @new @CCat 1 1@


@CCat_ctor is a constructor (0 is the destructor param, use 0 to not use a constructor/destructor), which will be automatically called by @new after allocation, or in the case of an array, will call the constructor for every object in the array after allocation:

CONST
this = 0@
CAnimal_Type = -1@
CAnimal_NumLegs = -2@
CAnimal_HasTail = -3@
CHuman_NumArms = -4@
ANIMAL_TYPE_UNSPECIFIED = -1
ANIMAL_TYPE_HUMAN = 0
ANIMAL_TYPE_DOG = 1
ANIMAL_TYPE_CAT = 2
SuperVar = string
END
VAR
this: array 4 of SuperVar
END

:CAnimal_ctor{\__(obj*)__}
// Using SuperVars, any variable can be treated more like a real object
0006: this[this] = @CAnimal_VTBL   // default VTBL for abstract class
0006: this[CAnimal_Type] = ANIMAL_TYPE_UNSPECIFIED
RET 0

:CHuman_ctor{\__(obj*)__}
CALL @CAnimal_ctor 1 this
0006: this[CAnimal_Type] = ANIMAL_TYPE_HUMAN
0006: this[CAnimal_NumLegs] = 2
0006: this[CAnimal_HasTail] = FALSE
0006: this[CHuman_NumArms] = 2
RET 0

:CDog_ctor{\__(obj*)__}
CALL @CAnimal_ctor 1 this
0006: this[this] = @CDog_VTBL
0006: this[CAnimal_Type] = ANIMAL_TYPE_DOG
0006: this[CAnimal_NumLegs] = 4
0006: this[CAnimal_HasTail] = TRUE
RET 0

:CCat_ctor{\__(obj*)__}
CALL @CAnimal_ctor 1 this
0006: this[this] = @CCat_VTBL
0006: this[CAnimal_Type] = ANIMAL_TYPE_CAT
0006: this[CAnimal_NumLegs] = 4
0006: this[CAnimal_HasTail] = TRUE
RET 0


Here we have a constructor setting the default (initial) values of a 'CDog', 'CCat' or 'CAnimal'. It also sets a 'virtual table', so lets have a look at them...


:CAnimal_VTBL
HEX
@_object_vtbl
@CAnimal_GetNumLegs
@CAnimal_Speak
END

:CDog_VTBL
HEX
@_object_vtbl
@CAnimal_GetNumLegs
@CDog_Speak
END

:CCat_VTBL
HEX
@_object_vtbl
@Animal_GetNumLegs
@CDog_Speak
END


Note that the first field of the VTBL must be a pointer to the object base VTBL. Actually, you could also have the first field point to another virtual table, and have that point to the object base VTBL, and so on...

:CAnimal_Speak
PRINTSTRING "Hello"
RET 0

:CCat_Speak
PRINTSTRING "Miaow"
RET 0

:CDog_Speak
PRINTSTRING "Woof"
RET 0

:CAnimal_GetNumLegs
RET 1 this[CAnimal_NumLegs]


So calling GetNumLegs with a cat would return 4, for a dog it would also return 4, but for a human it would return 2.

But for 'Speak', different animal classes have to use different methods, as they all speak differently. If we knew our object type was definitely a CDog, we could just do:
CALL @CDog_Speak 1 1@   // 1@ was returned from @new


However, the idea of a virtual table is that we could also have a different VTBL for a similar object, but we could still call the same method:
CONST
CAnimal_Speak = -2@   // index of the Speak method for each CAnimal object's VTBL
END

CALL 1@(CAnimal_Speak,4s) 1@


If 1@ is a CCat, it will print "Miaow", if it's a CDog, it will print "Woof" and the default method is "Hello", which will cover a CHuman and any other CAnimal-based type which is created without it's own unique VTBL.



Don't worry, lots of confusion and questions are expected, unless you are both a CLEO and C++ pro, so fire away.

Cheerio.

Download


--------------------
Go to the top of the page
 
+Quote Post
badboy
post Mar 2 2013, 01:06 PM
Post #2


Trained Member

Posts: 76
From: Nederland, NL
Joined: 1-May 12



Is this going to slow the game down a lot? Adding classes to SCM seems to be a bit overkill imo.
Go to the top of the page
 
+Quote Post
Deji
post Mar 2 2013, 01:56 PM
Post #3


Coding like a Rockstar!

Group Icon

Posts: 1,468
From: ???
Joined: 28-May 09



QUOTE (badboy @ Mar 2 2013, 01:06 PM) *
Is this going to slow the game down a lot? Adding classes to SCM seems to be a bit overkill imo.

Only if you add so much CLEO code that the game would become slow anyway. It's just using arrays with a memory address as a base pointer. Besides, Objective-SCM is just a fancy show-off bonus of SuperVars, so it's not really about having classes in CLEO but having the ability to create such epic things with SuperVars, and that's only my imaginations limit so far... Most of the work is done exe-side and uses less memory than the PRINT opcode tongue.gif


--------------------
Go to the top of the page
 
+Quote Post
baileychalse
post Oct 13 2013, 12:45 AM
Post #4


The New Guy!

Posts: 2
Joined: 8-October 13



QUOTE (badboy @ Mar 2 2013, 01:06 PM) *
Is this going to slow the game down a lot? Adding classes to SCM seems to be a bit overkill imo.


For me, yes it slowed the game down. sad.gif
Go to the top of the page
 
+Quote Post
Deji
post Oct 14 2013, 12:39 PM
Post #5


Coding like a Rockstar!

Group Icon

Posts: 1,468
From: ???
Joined: 28-May 09



QUOTE (baileychalse @ Oct 13 2013, 01:45 AM) *
For me, yes it slowed the game down. sad.gif

^ignore.


--------------------
Go to the top of the page
 
+Quote Post
Sidewalk Surfer
post Oct 14 2013, 04:01 PM
Post #6


Newbie In Training

Posts: 16
From: NYC USA
Joined: 29-December 09



If it is posssible, could you give an example of iterating through an array with a for loop using SuperVars?


--------------------
Whoa dude! Mr. Turtle is my father.
Go to the top of the page
 
+Quote Post
Deji
post Oct 15 2013, 04:21 PM
Post #7


Coding like a Rockstar!

Group Icon

Posts: 1,468
From: ???
Joined: 28-May 09



QUOTE (Sidewalk Surfer @ Oct 14 2013, 05:01 PM) *
If it is posssible, could you give an example of iterating through an array with a for loop using SuperVars?


QUOTE
31@ contains a memory address - the start of your new variable
pool. -1@ is the array index. You may notice how it's actually
a negative variable index, well all constant indexes for
SuperVars should be negative, going up to -32768@. If you were
to use 1@ as the index, SuperVars would read the value of 1@
instead use that value as an index.


So it's basically just like iterating through a normal array:
SET_BIT_L 38@ 8
IF NOT IS_BIT_SET_L 38@ 9
THEN
    PRINT_HELP_STRING "This script needs SuperVars to run"
    
TERMINATE_THIS_CUSTOM_SCRIPT
END

1@ = @MEM
0006: 1@(1@,4s) = 100       // var1 (use SuperVar for 0-index)
0006: 1@(-1@,4s) = 200      // var2 (use negative for 1+ indexes)
0006: 1@(-2@,4s) = 300      // var3
0006: 1@(-3@,4s) = 400      // var4

FOR 0@ = 0 TO 3
    PRINTINT2 "var" 1@(0@,4s)   // reads the value of 0@ and uses as the index - e.g. 2 == -2@
END
{
  prints:
    var 100
    var 200
    var 300
    var 400
}

TERMINATE_THIS_CUSTOM_SCRIPT

:MEM
HEX
00 00 00 00     // var1
00 00 00 00     // var2
00 00 00 00     // var3
00 00 00 00     // var4
END


You could change the 4s in the array to a different value to change the multiplier (so it would increment by 8 bytes if you used 8s), just remember that most value operations work with 4 byte values regardless.

Aside from a few additional supporting features, that's basically the in and out of SuperVars. You assign a memory location to any var and the variable 'becomes' that memory location. All is explained in the readme as well as methods for making it easier to write.


--------------------
Go to the top of the page
 
+Quote Post
Reply to this postStart new topic

3 User(s) are reading this topic (3 Guests and 0 Anonymous Users)
0 Members: