|
DMA documentation Displaying 1-8 of 8 total.
1
basil
|
Hate to nag, but I'd really appreciate some more information on v3 DMA if anybody has the time ... (mcgrue?). I'm fairly comfortable with the concepts of working in binary, I'd just like some explanation or examples of the specific behaviour of the v3 functions. Cheers.
Posted on 2004-10-22 06:29:16
|
zonker6666
|
// these attributes will be 1 byte in size
// so from 0 to 255
#define STRENGTH 0
#define WISDOM 1
#define HITPOINTS 2
#define LEVEL 3
#define TOTAL_SIZE 4
int CreateWhatever()
{
int retval=malloc(TOTAL_SIZE);
dma.byte[retval+STRENGTH]=random(1,6);
dma.byte[retval+WISDOM]=random(1,6);
dma.byte[retval+HITPOINTS]=random(1,6);
dma.byte[retval+LEVEL]=random(1,6);
return retval;
}
void DisplayWhatever(int this)
{
while(!key[SCAN_ESC])
{
rectfill(0,0,imagewidth(screen),imageheight(screen),0,screen);
printstring(0,0,screen,0, str(dma.byte[this+STRENGTH]));
printstring(0,0,screen,0, str(dma.byte[this+WISDOM]));
printstring(0,0,screen,0, str(dma.byte[this+HITPOINTS]));
printstring(0,0,screen,0, str(dma.byte[this+LEVEL]));
showpage();
}
key[SCAN_ESC]=0;
}
void autoexec()
{
DisplayWhatever(CreateWhatever());
}
/// Just a short and simple example of how you would use dma hope this helps you out some.
Posted on 2004-10-23 23:12:26 (last edited on 2004-10-24 05:28:06)
|
Feyr
|
#define STRENGTH 0
#define WISDOM 1
#define HITPOINTS 2
#define LEVEL 3
#define TOTAL_SIZE 4
int CreateWhatever()
{
int retval=malloc(TOTAL_SIZE);
dma.byte[retval+STRENGTH]=random(1,6);
dma.byte[retval+WISDOM]=random(1,6);
dma.byte[retval+HITPOINTS]=random(1,6);
dma.byte[retval+LEVEL]=random(1,6);
return retval;
}
And if the idea of typing stuff like that out all the time sounds like a one-way ticket to Bugsville in Boring County, you might want to check out my ClassBuilder code generating script, which automates that sort of thing. Just as an example, here's what the same code zonker6666 gave would look like with ClassBuilder:
Class:Whatever
Field:Strength:byte
Field:Wisdom:byte
Field:Hitpoints:byte
Field:Level:byte
Init:Whatever CreateWhatever()
$Strength$ = random(1,6);
$Wisdom$ = random(1,6);
$Hitpoints$ = random(1,6);
$Level$ = random(1,6);
EndCode
Code:void DisplayWhatever(Whatever this)
while(!key[SCAN_ESC]) {
RectFill(0,0,ImageWidth(screen),ImageHeight(screen),0,screen);
PrintString(0,0,screen,0,str($Strength$));
PrintString(0,0,screen,0,str($Wisdom$));
PrintString(0,0,screen,0,str($Hitpoints$));
PrintString(0,0,screen,0,str($Level$));
ShowPage();
}
key[SCAN_ESC]=0;
EndCode
Code:void autoexec()
// zonker6666 didn't do it like this, but I had to make
// the change because his version leaks memory. ;P
// If he had written it to avoid memory leaks, it would
// have looked like the comments after each line.
Whatever this = CreateWhatever(); // int this = CreateWhatever();
DisplayWhatever(this); // DisplayWhatever(this);
WhateverFree(this); // MemFree(this);
EndCode
EndClass
If you're interested, watch the 'New version of ClassBuilder' thread over in the general forum for the tutorial I'll be posting as soon as I get it finished, which will walk you through building a simple game of Pong using ClassBuilder to handle all of the DMA work.
*cough* Self-promotion aside, basically what you have with DMA is a big array of bytes. You can grab different numbers of bytes up (byte/sbyte gives you 1, word/sword gives you 2 and quad/squad gives you 4) and choose to view them as signed or unsigned numbers (byte gives you numbers from 0 through 255, while sbyte gives you numbers from -128 through 127, for instance). In general you want to come up with a format for your chunk of memory, as zonker6666 did with his #defines and I did with my Fields. Then you malloc a chunk of memory of the correct size to get a pointer to a location in memory, and use dma.byte, dma.sbyte, dma.word, dma.sword, dma.quad and dma.squad to grab the bytes you need by adding the pointer to the offset you decided on earlier.
ClassBuilder will handle the addition for you (all you have to remember is what you named the fields), as well as giving you type-checking ability so you can catch it if you happen to pass a pointer to the wrong type of data, plus letting you nest DMA-based structures MUCH more easily than doing it by hand...compare the following two examples:
// ClassBuilder way:
$this_player.Weapon.SpecialAbility.Type$ = SPECIAL_HEAL;
$this_player.Weapon.SpecialAbility.Power$ = 10;
// Manual way, separated into multiple lines to keep
// you from having to scroll too far. =P
dma.byte[
dma.quad[
dma.quad[
this_player + PLAYER_WEAPON
] + SPECIAL_ABILITY
] + ABILITY_TYPE
] = SPECIAL_HEAL;
dma.byte[
dma.quad[
dma.quad[
this_player + PLAYER_WEAPON
] + SPECIAL_ABILITY
] + ABILITY_POWER
] = 10;
It will also allow you to create a new data format that's based on an old one, which effectively allows you to treat the new format as either the old one or the new one, depending on what you want to do with it.
Posted on 2004-10-24 04:28:23 (last edited on 2004-10-24 04:35:22)
|
basil
|
Thanks for the response(s). Allow me to ask a more specific question.
My understanding is that the number you pass to malloc refers to the number of bytes you're allocating. So if I go
temp=malloc(10);
is it then correct to say
dma.word[temp]=3000;
low_byte=dma.byte[temp]
high_byte=dma.byte[temp+1]
And furthermore, if I say
dma.word[temp+5]=4000;
dma.word[temp+6]=5000;
have I overwritten a byte here? i.e. do I need to be careful to increment the pointer by 2 when dealing with words?
Lastly, I've never encountered quads before, am I to assume this allows storage of numbers up to 2^32 ?
Posted on 2004-10-24 10:08:22
|
Feyr
|
dma.word[temp+5]=4000;
dma.word[temp+6]=5000;
have I overwritten a byte here?
Yes, that is the case. And, yes, quads (you might know them better as dwords or double words) give you a range of 2^32 numbers. Also available are sbyte, sword and squad, which are the signed versions of byte, word and quad, with a range of -(2^7) through 2^7-1, -(2^15) through 2^15-1 and -(2^31) through 2^31-1, respectively.
Posted on 2004-10-24 10:18:50
|
basil
|
Excellent. Many thanks.
Posted on 2004-10-24 10:52:09
|
mcgrue
|
If anyone at all wants to compile this data in an easy-to-digest form, I'll gladly add it to the manual.
Posted on 2004-10-24 14:04:23
|
Feyr
|
I don't know about 'easy to digest', but this might help more than what's there at the moment.
----
DMA allows you to access raw memory as if it were an array of bytes.
The general idea is to come up with your own data format, allocate a chunk of memory using Malloc(), modify the memory with the dma.* arrays, and finally free the memory with MemFree().
The dma arrays come in the following forms:
dma.byte[] : access bytes, which store values from 0 through 2^8
dma.sbyte[] : access signed bytes, values -2^7 through 2^7-1
dma.word[] : access words, values 0 through 2^16
dma.sword[] : access signed words, values -2^15 through 2^15-1
dma.quad[] : access quads, values 0 through 2^32
dma.squad[] : access signed quads, values -2^31 through 2^31-1
To access memory at a given location, you use a pointer (which is obtained using the Malloc() function) as an index into one of the dma.* arrays, possibly with an additional offset added if you want to access memory that isn't found at the first byte of the memory chunk.
// HP is the 1st field in our format, and it takes up 4 bytes
// HP starts at byte 0, ends at 3
#define HIT_POINTS 0
// MP is the 2nd field in our format, and it takes up 2 bytes
// MP starts at byte 4, ends at 5
#define MAGIC_POINTS 4
// Level is the 3rd field in our format, and it takes up 1 byte
// Level starts and ends at byte 6
#define LEVEL 6
// And the total size of our format is 7 bytes (4 + 2 + 1)
#define TOTAL_SIZE 7
void autoexec() {
// Allocate a chunk of memory big enough to hold our format
int this_player = malloc(TOTAL_SIZE);
// Set the player's HP to 500
dma.quad[this_player + HIT_POINTS] = 500;
// Set the player's MP to 256
dma.word[this_player + MAGIC_POINTS] = 256;
// Set the player's level to 15
dma.byte[this_player + LEVEL] = 15;
// Print log messages with the player's stats:
// We want them to be able to be negative, so read them
// back using the signed versions of the dma arrays.
Log('HP: '+str( dma.squad[this_player + HIT_POINTS] ));
Log('MP: '+str( dma.sword[this_player + MAGIC_POINTS] ));
// ERROR: This will grab too much data and return an
// incorrect value. Even worse, since the level is at
// the end of the data format, it will attempt to access
// memory that we didn't allocate.
Log('Level != '+str( dma.sword[this_player + LEVEL] ));
// Free the memory taken by this_player
MemFree(this_player);
}
As shown in the sample above, you must take care to use the correct dma array. Using one that accesses too many bytes at once (quad when you should have used byte, for example) will cause you to overread or overwrite other data. Using one that's too small will only get you a fraction of the bytes that were originally written, which is not desirable in most cases.
Posted on 2004-10-24 18:57:05 (last edited on 2004-10-24 19:00:51)
|
Displaying 1-8 of 8 total.
1
|
|