User Tag List

Page 1 of 3 1 2 3 LastLast
Results 1 to 10 of 23

Thread: Problem Writing a Function

  1. #1
    The Timelord
    QDB Manager
    ZC Developer

    Join Date
    Oct 2006
    Location
    Prydon Academy
    Posts
    1,396
    Mentioned
    112 Post(s)
    Tagged
    1 Thread(s)
    vBActivity - Stats
    Points
    4,760
    Level
    21
    vBActivity - Bars
    Lv. Percent
    68.72%

    Problem Writing a Function

    @Gleeok @Saffith

    I created some functions to write to Link's tiles (using setlinktile(), not something wholly new), as follows:

    Code:
    //Link.h/cpp
    
    void setTile(int state, int tile, int dir, int flip);
    void LinkClass::setTile(int state, int tile, int dir, int flip){
    	setlinktile(tile, flip, getExtend(state), state, dir);
    }
    
    int getExtend();
    int LinkClass::getExtend()
    {
    	return walkspr[dir][spr_extend];	
    }
    
    //ffasm.cpp
        { "SETLINKTILE",             0,   0,   0,   0}
    
    //ffscript.cpp
    
    case SETLINKTILE:
    		set_link_tile(false);
    		break;
    
    void set_link_tile(bool v)
    {
        int state   = SH::read_stack(ri->sp + 3) / 10000;
        int tile = SH::read_stack(ri->sp + 2) / 10000;
        int dir   = SH::read_stack(ri->sp + 1) / 10000;
        int flip   = SH::read_stack(ri->sp + 0) / 10000;
        Link.setTile(vbound(state,1,14),vbound(tile,0,65519),vbound(dir,0,16),vbound(flip,0,16));
    }
    //ffscript.h
    SETLINKTILE, //0x00F1
    
    //Bytecode.cpp
    
    string OSetLinkTile::toString()
    {
        return "SETLINKTILE";
    }
    
    //Bytecode.h
    
    class OSetLinkTile : public Opcode
    {
    public:
        string toString();
        Opcode *clone()
        {
            return new OSetLinkTile();
        }
    };
    
    //GLobalSymbols.cpp
    
    //void SetLinkTile(link, int,int,int,int)
        {
            int id = memberids["SetTile"];
            int label = lt.functionToLabel(id);
            vector<Opcode *> code;
            Opcode *first = new OSetLinkTile();
            first->setLabel(label);
            code.push_back(first);
            code.push_back(new OPopRegister(new VarArgument(EXP2)));
            code.push_back(new OPopRegister(new VarArgument(EXP2)));
            code.push_back(new OPopRegister(new VarArgument(EXP2)));
            code.push_back(new OPopRegister(new VarArgument(EXP2)));
            //pop pointer, and ignore it
            code.push_back(new OPopRegister(new VarArgument(NUL)));
            
            code.push_back(new OPopRegister(new VarArgument(EXP2)));
            code.push_back(new OGotoRegister(new VarArgument(EXP2)));
            rval[label]=code;
        }
    
     { "SetTile",                ScriptParser::TYPE_VOID,          FUNCTION,     0,                    1,      {  ScriptParser::TYPE_LINK,          ScriptParser::TYPE_FLOAT,         ScriptParser::TYPE_FLOAT,    ScriptParser::TYPE_FLOAT,   ScriptParser::TYPE_FLOAT,                           -1,                           -1,                           -1,                           -1,                           -1,                           -1,                           -1,                           -1,                           -1,                           -1,                           -1,                           -1,                           -1,                           -1,                           -1                           } },
    Does any of that look amiss? The function doesn't seem to do a blasted thing...

    Also, could someone define what the four values used after the string in the array inside ffasm.cpp do, individually?

    Number of args, is the stack inputs, AFAIK, buwhat do the next three values mean? It looks like the first two are meant as boolean flags; and what in the world is 'more'?


    These...
    Code:
    //ffasm.cpp
    script_command command_list[NUMCOMMANDS+1]=
    {
        //name                args arg1 arg2 more
        { "SETLINKTILE",             0,   0,   0,   0}
    It would be nice to have a basic reference on how these relate to the stack, and what arg1, arg2, and more are, specifically.

    Also, in the 'would be nice' category:

    Spoiler: show
    Code:
      { "GETTILEPIXELV",       1,   1,   0,   0},
        { "GETTILEPIXELR",       1,   0,   0,   0},
        { "SETTILEPIXELV",       1,   1,   0,   0},
        { "SETTILEPIXELR",       1,   0,   0,   0},


    I would love to finish these, once I fully comprehend the stack values and operations.

  2. #2
    Is this the end?
    ZC Developer
    Saffith's Avatar
    Join Date
    Jan 2001
    Age
    41
    Posts
    3,389
    Mentioned
    178 Post(s)
    Tagged
    6 Thread(s)
    vBActivity - Stats
    Points
    6,430
    Level
    24
    vBActivity - Bars
    Lv. Percent
    69.58%
    Link's tile is calculated in LinkClass::draw(). Any changes are overridden before they become visible.

  3. #3
    The Timelord
    QDB Manager
    ZC Developer

    Join Date
    Oct 2006
    Location
    Prydon Academy
    Posts
    1,396
    Mentioned
    112 Post(s)
    Tagged
    1 Thread(s)
    vBActivity - Stats
    Points
    4,760
    Level
    21
    vBActivity - Bars
    Lv. Percent
    68.72%
    Quote Originally Posted by Saffith View Post
    Link's tile is calculated in LinkClass::draw(). Any changes are overridden before they become visible.
    Oh.I thought that stuff like walkspr[dir][spr_extend] held the base tile and that the functions drawing Lijk, read [i[from it[/i], made their offsets based on the clocks, and selected the tile to draw...

    Isn't there somewhere that the base tile for each sprite category is stored, from which these calcs are made?

    Does the function set otherwise look right? It's my first attempt at making functions to interact directly with the stack, so I want to know if I did it wrongly.

    I also wrote some things for setting and getting the extend value, which should work. Would you mind proofing how I'm handling pushing values onto, and reading values from the stack; and outlining any errors?

    Extend Setter/Getter as a Link->Function()
    Spoiler: show

    Code:
    //Setter Link->SetExtend(int sprite, int dir, int value)
    
    void LinkClass::setExtend(int state, int dir, int value){
    	switch(state){
    		case 1: 
    			walkspr[dir][spr_extend] = value;
    			break;
    		case 2: 
    			floatspr[dir][spr_extend] = value;
    			break;
    		case 3: 
    			swimspr[dir][spr_extend] = value;
    			break;
    		case 4: 
    			divespr[dir][spr_extend] = value;
    			break;
    		case 5: 
    			slashspr[dir][spr_extend] = value;
    			break;
    		case 6:
    			jumpspr[dir][spr_extend] = value;
    			break;
    		case 7: 
    			chargespr[dir][spr_extend] = value;
    			break;
    		case 8:
    			stabspr[dir][spr_extend] = value;
    			break;
    		case 9: 
    			poundspr[dir][spr_extend] = value;
    			break;
    		case 10: 
    			castingspr[spr_extend] = value;
    			break;
    		case 11: 
    			holdspr[spr_landhold][spr_hold1][spr_extend] = value;
    			break;
    		case 12: 
    			holdspr[spr_landhold][spr_hold2][spr_extend] = value;
    			break;
    		case 13: 
    			holdspr[spr_waterhold][spr_hold1][spr_extend] = value;
    			break;
    		case 14: 
    			holdspr[spr_waterhold][spr_hold2][spr_extend] = value;
    		
    		default: break;
    	}
    }
    
    void set_link_extend(bool v)
    {
        int state   = SH::read_stack(ri->sp + 2) / 10000;
        int extend = SH::read_stack(ri->sp + 1) / 10000;
        int dir   = SH::read_stack(ri->sp) / 10000;
        Link.setExtend(vbound(state,1,14),vbound(dir,0,16),vbound(extend,0,16));
    }
    
    
        
    string OSetLinkExtend::toString()
    {
        return "SETLINKEXTEND";
    }
    
    { "SETLINKEXTEND",            0,   0,   0,   0},
        
    	
    case SETLINKEXTEND:
    	set_link_extend(false);
    	break;
    
    string OSetLinkExtend::toString()
    {
        return "SETLINKEXTEND";
    }
    
    
    
        //void SetLinkExtend(link, int,int,int,int)
        {
            int id = memberids["SetLinkExtend"];
            int label = lt.functionToLabel(id);
            vector<Opcode *> code;
            Opcode *first = new OSetLinkExtend();
            first->setLabel(label);
            code.push_back(first);
            code.push_back(new OPopRegister(new VarArgument(EXP2)));
            code.push_back(new OPopRegister(new VarArgument(EXP2)));
            code.push_back(new OPopRegister(new VarArgument(EXP2)));
            code.push_back(new OPopRegister(new VarArgument(EXP2))); //is this extraneous?
            //pop pointer, and ignore it
            code.push_back(new OPopRegister(new VarArgument(NUL)));
            
            code.push_back(new OPopRegister(new VarArgument(EXP2)));
            code.push_back(new OGotoRegister(new VarArgument(EXP2)));
            rval[label]=code;
        }
    
    class OSetLinkExtend : public Opcode
    {
    public:
        string toString();
        Opcode *clone()
        {
            return new OSetLinkExtend();
        }
    };
    
    
    //Getter Fuction: Link->GetExtend(int sprite, int dir)
    
    int LinkClass::getExtend(int state, int dir){
    	switch(state){
    		case 1: 
    			return walkspr[dir][spr_extend];
    		case 2: 
    			return floatspr[dir][spr_extend];
    		case 3: 
    			return swimspr[dir][spr_extend];
    		case 4: 
    			return divespr[dir][spr_extend];
    		case 5: 
    			return slashspr[dir][spr_extend];
    		case 6:
    			return jumpspr[dir][spr_extend];
    		case 7: 
    			return chargespr[dir][spr_extend];
    		case 8:
    			return stabspr[dir][spr_extend];
    		case 9: 
    			return poundspr[dir][spr_extend];
    		case 10: 
    			return castingspr[spr_extend];
    		case 11: 
    			return holdspr[spr_landhold][spr_hold1][spr_extend];
    		case 12: 
    			return holdspr[spr_landhold][spr_hold2][spr_extend];
    		case 13: 
    			return holdspr[spr_waterhold][spr_hold1][spr_extend];
    		case 14: 
    			return holdspr[spr_waterhold][spr_hold2][spr_extend];
    		default: return -1;
    	}
    }
    
    void get_link_extend(bool v)
    {
        int state   = SH::read_stack(ri->sp + 1) / 10000;
        int dir   = SH::read_stack(ri->sp) / 10000;
        int extend = Link.getExtend(state, dir);
        set_register(sarg1, extend*10000);
    }
    
    string OGetLinkExtend::toString()
    {
        return "GETLINKEXTEND " + getArgument()->toString();
    }
    
    { "GETLINKEXTEND",     1,   0,   0,   0},
        
    case GETLINKEXTEND:
    	get_link_extend(true);
    	break;
    
    string OGetLinkExtend::toString()
    {
        return "GETLINKEXTEND " + getArgument()->toString();
    }
    
      //int GetLinkExtend(link, int, int)
        {
            int id = memberids["GetLinkExtend"];
            int label = lt.functionToLabel(id);
            vector<Opcode *> code;
            Opcode *first = new OPopRegister(new VarArgument(EXP1));
            first->setLabel(label);
    	code.push_back(first);
            code.push_back(new OPopRegister(new VarArgument(EXP2)));
            code.push_back(new OPopRegister(new VarArgument(EXP2))); //Is this extraneous?
            //pop pointer, and ignore it
            code.push_back(new OPopRegister(new VarArgument(NUL)));
            code.push_back(new OGetLinkExtend(new VarArgument(EXP1)));
            code.push_back(new OPopRegister(new VarArgument(EXP2)));
            code.push_back(new OGotoRegister(new VarArgument(EXP2)));
            rval[label]=code;
        }
    
    class OGetLinkExtend : public UnaryOpcode
    {
    public:
        OGetLinkExtend(Argument *A) : UnaryOpcode(A) {}
        string toString();
        Opcode *clone()
        {
            return new OGetLinkExtend(a->clone());
        }
    };

  4. #4
    The Timelord
    QDB Manager
    ZC Developer

    Join Date
    Oct 2006
    Location
    Prydon Academy
    Posts
    1,396
    Mentioned
    112 Post(s)
    Tagged
    1 Thread(s)
    vBActivity - Stats
    Points
    4,760
    Level
    21
    vBActivity - Bars
    Lv. Percent
    68.72%
    @Gleeok : Clearly, my comprehension of how to create a ZScript [ii]function[/i], and opcodes to match, is lacking. I can make variables easily-enough, but I'm not using the correct accumulators, or something with these functions, or I'm failing somewhere in that department.

    Is there some chance that you could write up a procedural, that demonstrates how to make a simple zscript function, that accepts one arg, and passes it to an internal zc class.function; then how to add a second, and third input; and likewise for a function that returns a value instead of passing it to an internal call?

    What does Couldn't find function label #1820 mean, in context?

  5. #5
    Administrator DarkDragon's Avatar
    Join Date
    Oct 2001
    Posts
    6,228
    Mentioned
    70 Post(s)
    Tagged
    0 Thread(s)
    vBActivity - Stats
    Points
    11,025
    Level
    31
    vBActivity - Bars
    Lv. Percent
    8.17%
    Creating a ZScript function is fairly easy: take a look at GlobalSymbols.cpp. Find the appropriate symbol table and add your function and its parameters as a new row at the bottom. Then function implementations follow the symbol table; just add your implementation (in terms of ZASM opcodes) at the bottom of the appropriate block. You should be able to figure out the ropes by looking at how similar functions are implemented.

    If you are just adding a function, and no new syntax, to ZScript, that is all you need to do. You don't even need to touch the parser itself.

    EDIT: And if you are adding a new ZASM operator, you will need to add it to ByteCode.h / ByteCode.cpp in order for ZScript to use it. Again, it shouldn't be too tricky to follow the existing examples.

  6. #6
    The Timelord
    QDB Manager
    ZC Developer

    Join Date
    Oct 2006
    Location
    Prydon Academy
    Posts
    1,396
    Mentioned
    112 Post(s)
    Tagged
    1 Thread(s)
    vBActivity - Stats
    Points
    4,760
    Level
    21
    vBActivity - Bars
    Lv. Percent
    68.72%
    Quote Originally Posted by DarkDragon View Post
    Creating a ZScript function is fairly easy: take a look at GlobalSymbols.cpp. Find the appropriate symbol table and add your function and its parameters as a new row at the bottom. Then function implementations follow the symbol table; just add your implementation (in terms of ZASM opcodes) at the bottom of the appropriate block. You should be able to figure out the ropes by looking at how similar functions are implemented.

    If you are just adding a function, and no new syntax, to ZScript, that is all you need to do. You don't even need to touch the parser itself.

    EDIT: And if you are adding a new ZASM operator, you will need to add it to ByteCode.h / ByteCode.cpp in order for ZScript to use it. Again, it shouldn't be too tricky to follow the existing examples.
    That is in fact, precisely what I was doing, but somewhere in the process I crossed meself up. Look at the functions above, and all of my implementation. They (1) don' work, and (2) return a quirky error (each):
    Couldn't find function label #1820
    and
    Couldn't find function label #1821

    I don't know what this is supposed to mean. What does it mean by 'function label', specifically, and what are those numeric values, and to what do they correspond?!

    One function is supposed to take four inputs, and modify a variable based on them. A second, does the same, using three inputs. The last, takes two inputs, uses them to get a return in an internal function, and pass that return back to the user via ZScript.

    Would you be so kind as to look at those above, see if you can spot the flaws, point them out, and explain what I did wrongly?

    I believe one of my failings, is that I used functions intended to pass a value to an existing array pointer, but I've been reading, and re-reading these things all day, and I'm losing track of the accumulators, and such. That's why a simple procedural, do this, pop these stack registers (and why) would be useful.

    I'm trying to write a manual for this as I go along, and creating ZScript functions is my only real stumbling point. I've outlined the process of making new setters, getters; making new registers, making new script commands, and making new drawing commands; but this has me going in such circles, that I'm dripping sanity from me ears.

    Having some basic docs on how to properly read params passed into a ZScript function from the stack, and how to write values to the stack and return the to the user, would be delicious.

    My whole latest package is here:

    Beta 23 Sources

    Have a look at ChangeLog.txt if you diff it and get lost at all. The additions in question are all outlined in this thread though, so that may help.

    I know that the fault is in the stack functions, in GlobalSymbols.cpp, in the functions directly (ffscript.cpp), or in the string opcode redirects such as:

    Code:
    string OGetLinkExtend::toString()
    {
        return "GETLINKEXTEND " + getArgument()->toString();
    }
    in ByteCode.cpp.

    The defines, and script_commands entries are all fine, AFAIK. Certainly, I had no trouble adding to these in the past, unless I've surpassed some limit of them that I didn't know existed.

    I'd also rather know both how, and why something works the way that it does, and how and why to do things a set way; than to fake it with copy-paste-code.

    As an example:

    Code:
     //void SetLinkTile(link, int,int,int,int)
        {
            int id = memberids["SetTile"];
            int label = lt.functionToLabel(id);
            vector<Opcode *> code;
            Opcode *first = new OSetLinkTile();
            first->setLabel(label);
            code.push_back(first);
            code.push_back(new OPopRegister(new VarArgument(EXP2))); //!ZoriaRPG this can't be right
            code.push_back(new OPopRegister(new VarArgument(EXP2))); //only one expr accumulator?
            code.push_back(new OPopRegister(new VarArgument(EXP2)));
            code.push_back(new OPopRegister(new VarArgument(EXP2))); 
            //pop pointer, and ignore it
            code.push_back(new OPopRegister(new VarArgument(NUL)));
            
            code.push_back(new OPopRegister(new VarArgument(EXP2)));
            code.push_back(new OGotoRegister(new VarArgument(EXP2)));
            rval[label]=code;
        }
    I don't know if this is right, but if it is, why expression accumulator 2?

    I don't know what the two accumulators do, off-hand. I can guess, but it feels as if I should be using EXP1 to store the script args?

    I would be able to do so much more with just a small amount of documentation, from which I can build more comprehensive docs over time.

    ...or stuff like this...

    Code:
    long ID = SH::get_arg(sarg1, v) / 10000;
    So, is that a script arg, or is that EXPR1? If it's a script arg, why are only two defined? sarg3 and above don't exist.

    Obviously, I need to look at get_arg(), but you can see how easy it is to become lost.

    At least I understand this:

    Code:
    int state   = SH::read_stack(ri->sp + 2) / 10000;
        int extend = SH::read_stack(ri->sp + 1) / 10000;
        int dir   = SH::read_stack(ri->sp + 0) / 10000;
    ...but why is the arg order reversed? Is it because they are read off the stack in FILO? That's me guess, but I detest needing to guess.

  7. #7
    Administrator DarkDragon's Avatar
    Join Date
    Oct 2001
    Posts
    6,228
    Mentioned
    70 Post(s)
    Tagged
    0 Thread(s)
    vBActivity - Stats
    Points
    11,025
    Level
    31
    vBActivity - Bars
    Lv. Percent
    8.17%
    When are you getting these errors? At the time you compile the source? Compile the ZScript? Run the ZASM?

    What will help is if you install a fresh version of 2.50.3, and then create a patch containing the new command (and nothing else). If it's giving you the same errors, link me to the patch, and I will take a look.

  8. #8
    The Timelord
    QDB Manager
    ZC Developer

    Join Date
    Oct 2006
    Location
    Prydon Academy
    Posts
    1,396
    Mentioned
    112 Post(s)
    Tagged
    1 Thread(s)
    vBActivity - Stats
    Points
    4,760
    Level
    21
    vBActivity - Bars
    Lv. Percent
    68.72%
    Quote Originally Posted by DarkDragon View Post
    When are you getting these errors? At the time you compile the source? Compile the ZScript? Run the ZASM?

    What will help is if you install a fresh version of 2.50.3, and then create a patch containing the new command (and nothing else). If it's giving you the same errors, link me to the patch, and I will take a look.
    Those errors are dumped to allegro.log during compilation of the ZScript (in ZQuest). I need to search the source for the string that generates them, to see where it pulls the IDs.

    If what I'm doing now does the same thing, I'll try getting you a clean repo with only this, but literally everything else that I have implemented, that is enabled, works. 98% of it is script drawing, and class variable setter/getter stuff.

    ( If we had a clean repo for a 'next' build, i would clone it, patch all of this in, and add it to a fork of it, so that a diff would be easier. )

  9. #9
    Administrator DarkDragon's Avatar
    Join Date
    Oct 2001
    Posts
    6,228
    Mentioned
    70 Post(s)
    Tagged
    0 Thread(s)
    vBActivity - Stats
    Points
    11,025
    Level
    31
    vBActivity - Bars
    Lv. Percent
    8.17%
    I'm wondering, though, if one of your other changes might have accidentally screwed up the symbol table (so that the other feature itself works, but causes all later function labels to be wrong, or something).

  10. #10
    The Time-Loop Continues ZC Developer
    Gleeok's Avatar
    Join Date
    Apr 2007
    Posts
    4,817
    Mentioned
    259 Post(s)
    Tagged
    10 Thread(s)
    vBActivity - Stats
    Points
    12,940
    Level
    33
    vBActivity - Bars
    Lv. Percent
    24.2%
    Quote Originally Posted by DarkDragon View Post
    Creating a ZScript function is fairly easy:
    You have got to be kidding, dood!

    I'm usually not a fan of writing heavy c++ metatemplate wrappers and generators, and hiding the whole mess cleverly in MACROS, but if I were to start over with adding new major additions to ZScript I would do this and scrap the current system.

    @ZoriaRPG : This is why when you asked me to add new functions to ZScript I wait until I have to do a bunch of them first and then do them all at once.

    Since you were complaining about angelscript before: Here's how you add something new to scripts in angelscript:
    Code:
    engine->RegisterObjectMethod(className, "IGameObject@ create(const String &in)", asFUNCTIONPR(Create, callConvType);


    As for the errors, I need to take a look.
    This post contains the official Gleeok seal of approval. Look for these and other posts in an area near you.

Thread Information

Users Browsing this Thread

There are currently 5 users browsing this thread. (0 members and 5 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
About us
Armageddon Games is a game development group founded in 1997. We are extremely passionate about our work and our inspirations are mostly drawn from games of the 8-bit and 16-bit era.
Social