Adventure Game Studio | Forums

AGS Support => Advanced Technical Forum => Topic started by: Scavenger on Wed 27/11/2013 15:35:39

Title: [Lua] Palette Based Graphics Programming
Post by: Scavenger on Wed 27/11/2013 15:35:39
I'm trying to write a plugin to speed up pixel level functions in AGS, by converting an image into a string (AGS has the String.Chars[] array, which would be much faster to manipulate than Get/SetPixel). I hope to fake a kind of array setup when manipulating pixels, so I can speed up my translucency and colourisation functions for my next game, and maybe even write some more graphics programming type stuff.

I am ludicrously underskilled in C++. I did a bit of C in the old DOS days, but nothing fancy. I at least managed to get the plugin to compile in VS2008 Express. I suppose I gotta start somewhere!


Here's the code I wrote.
Code (C++) Select
const char SerialiseSprite (int id)
{
unsigned char serialised_image;
serialised_image = new signed char [engine->GetSpriteWidth (id) * engine->GetSpriteHeight (id)];
BITMAP *temp = engine->GetSpriteGraphic (id);
serialised_image = engine->GetRawBitmapSurface (temp);
engine->ReleaseBitmapSurface (temp);
return engine->CreateScriptString (serialised_image);
}

int UnSerialiseSprite (const char string, int width,int height)
{
int sprite = engine->CreateDynamicSprite (8,width,height);
BITMAP *temp = engine->GetSpriteGraphic (sprite);
unsigned char imagecontent = engine->GetRawBitmapSurface (sprite);
imagecontent = string;
engine->ReleaseBitmapSurface (sprite);
return sprite;
}

void DestroySprite (int id)
{
engine->DeleteDynamicSprite (id);
}


Quote.\dllmain.cpp(96) : error C2440: '=' : cannot convert from 'signed char *' to 'unsigned char'
1>        There is no context in which this conversion is possible
1>.\dllmain.cpp(98) : error C2440: '=' : cannot convert from 'unsigned char **' to 'unsigned char'
1>        There is no context in which this conversion is possible
1>.\dllmain.cpp(100) : error C2664: 'IAGSEngine::CreateScriptString' : cannot convert parameter 1 from 'unsigned char' to 'const char *'
1>        Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
1>.\dllmain.cpp(107) : error C2664: 'IAGSEngine::GetRawBitmapSurface' : cannot convert parameter 1 from 'int' to 'BITMAP *'
1>        Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
1>.\dllmain.cpp(109) : error C2664: 'IAGSEngine::ReleaseBitmapSurface' : cannot convert parameter 1 from 'int' to 'BITMAP *'
1>        Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast

This is the error it kicks out. I know this is simple stuff, but I don't understand it at all. Stuff I take for granted in AGSScript doesn't seem to carry over to C++, and it's a little embarrassing. Especially the "char" types. I'm not sure how to fix this?

Thankyou in advance :)
Title: Re: [C++] Need advice for setting types of variables?
Post by: Wyz on Wed 27/11/2013 16:36:16
There are some issues with types being incompatible. For instance you're trying to store an array in a scalar typed variable. Also you are mixing signed and unsigned types which is not really a problem but also something that makes the compiler spit errors. But there is also a general design issue: Converting something to a script string is very unlikely to make it faster. The engine will allocate new memory every time you use the CreateScriptString function which is pretty inefficient. There are also caveat with the null character, as that is used as a terminating character for C-strings. You're better of moving the actual calculation to the plugin and update the bitmap from there. Sorry to break it to you :)
Title: Re: [C++] Need advice for setting types of variables?
Post by: Scavenger on Wed 27/11/2013 16:46:23
That's pretty lame. I was hoping to make a pretty generic function so I could do much of the calculations in AGSScript and just convert it back and forth from array and sprite as needed. But if I really have to do it in-plugin, I probably could handle that given some practice.
Title: Re: [C++] Need advice for setting types of variables?
Post by: Crimson Wizard on Wed 27/11/2013 16:54:50
Scavenger, I can suggest for you to look into Calin's Blend and SpriteFont plugins: they work with bitmaps, so you could have an example.
https://github.com/adventuregamestudio/ags/blob/master/Plugins/agsblend/AGSBlend.cpp
https://github.com/CalinLeafshade/ags-spritefont

Regarding your code, you are not using a pointer type:
Code (cpp) Select

unsigned char * serialised_image; // see the '*' added here
serialised_image = new signed char [engine->GetSpriteWidth (id) * engine->GetSpriteHeight (id)];


More importantly
Code (cpp) Select

serialised_image = engine->GetRawBitmapSurface (temp);
engine->ReleaseBitmapSurface (temp);

when you assign the result of GetRawBitmapSurface to your pointer, you are not making a copy of bitmap, but a copy of bitmap's address in memory.
The following call to ReleaseBitmapSurface will destroy bitmap, leaving you with a pointer addressing freed memory. Using that address further won't do any good (if not crash your game right away).
Title: Re: [C++] Need advice for setting types of variables?
Post by: monkey0506 on Wed 27/11/2013 17:11:53
I also noticed that serialised_image was being allocated with new but never deleted anywhere. That's a memory leak! 8-0

For what you're trying to do, you would have to go through the image and copy the raw image data a line at a time into your buffer. Really though, the buffer isn't even necessary here since CreateScriptString is already going to make a copy, you could just pass the raw data directly through. As Wyz mentions though, any null bytes (decimal value 0) in your image data (which would not really be uncommon) would truncate the rest of the entire image. The speed you were hoping to gain would also have been severely diminished by the fact that AGS' String type is immutable, so you would constantly be making copies of the entire String just to change a single byte.
Title: Re: [C++] Need advice for setting types of variables?
Post by: Scavenger on Wed 27/11/2013 17:28:06
Interesting! I'm learning a lot here that I didn't know before.

I think, going forward what would be better is for me to try and implement the main bulk of my image processing (that is, the giant loops that iterate through the entire image and change it pixel by pixel) in the plugin. It'd be less flexible, but probably a lot faster for what I'm trying to do with it. Since it's basically just substituting values based on other values (in a look up table), and returning the resulting sprite, it might be easier to do, as well!

(I probably need to look up some more books on the language if I'm to fully understand what I'm doing.)
Title: Re: [C++] Need advice for setting types of variables?
Post by: Calin Leafshade on Wed 27/11/2013 23:21:56
@Scavenger

I did some benchmarking on this and the Get/Set pixel functions are not the bottleneck, it's the ags script language itself. It's *really* slow, especially in loops.

The AGS compiler, AFAIK, has no optimisation and uses no advanced CPU instructions. If you made a function to serialise it to a string it would be *far* slower than Get/Setpixel.

You could use Lua though. I used Lua to do the Mode7 emulation in the mario kart clone and I could get 40fps with no problem. That was using Get/SetPixel.
Doing the exact same calculations in AGS gave me about 7fps.
Title: Re: [C++] Need advice for setting types of variables?
Post by: Crimson Wizard on Wed 27/11/2013 23:37:05
Quote from: Calin Leafshade on Wed 27/11/2013 23:21:56
The AGS compiler, AFAIK, has no optimisation and uses no advanced CPU instructions.
Unfortunately, that's true. It produces very formal sequence of instructions, mimicing how real x86 processor (IIRC) works: putting values to registers, getting them back, calculating, putting result to register, getting it back once again for other use, etc, etc., and every action is processed separately. I think it does at least about 3-5 things more than needed (http://www.adventuregamestudio.co.uk/forums/index.php?topic=47320.0) per each primitive operation.
Title: Re: [C++] Need advice for setting types of variables?
Post by: Scavenger on Wed 27/11/2013 23:46:00
That's cool. While I'm more experienced with AGSScript, I may as well learn some Lua syntax and try that out. The plugin appears to be open source, so porting games made with it to other platforms can't be that hard.

If the speed of it is all that it's cracked up to be, this is exactly what I've been looking for! Though, it may take me some time to get used to it. At least it won't require me to wrangle with VS anymore! Ahaha. Does the Lua plugin have a manual I can look up to see how calling functions differs from AGSScript?
Title: Re: [C++] Need advice for setting types of variables?
Post by: Calin Leafshade on Thu 28/11/2013 00:02:32
This wiki is useful:

http://lua-for-ags.wikispaces.com/agsTable

but its basically like this for your purposes:

Code (ags) Select

function DoSomethingToDynamicSprite(DynamicSprite* myDS)
{
  LuaValueList *list = Lua.NewValueList()
  list.Add(myDS.AsLuaValue())
  Lua.Call("myLuaFunction", list)
}


Code (lua) Select

function myLuaFunction(ds)
    local surface = ds:GetDrawingSurface()
    for y=0,ds.Height - 1 do
        for x=0,ds.Width - 1 do
            --Do stuff with pixel here
        end
    end
    surface:Release()
end
Title: Re: [C++] Need advice for setting types of variables?
Post by: Scavenger on Thu 28/11/2013 03:10:37
Okay, I've been pottering around in Lua for a bit, it's not as daunting as I thought it would initially be. I managed to convert a function from AGSScript to Lua, and Lua, having 2D arrays, seems to be a better fit for it:

Code (lua) Select


function GetCLUTForRoom ()
    clut[0][0] = 0;
    local i,x,y,cdata
    x=0
    y=0
    i=0
    cdata = 0
    local CLUTSPR = ags.DynamicSprite.CreateFromExistingSprite (ags.GetRoomProperty ("TransCLUTSlot"), false)
    local surface = ags.CLUTSPR.GetDrawingSurface ()
    while (i < 8)
    do
        while (cdata < 65536)
        do
            clut[i][cdata] = ags.surface.GetPixel (x, y)
            if (x == 255 and y <2047) then
                y = y + 1 end
            if (x < 255) then
                x = x + 1
            else x = 0 end
            cdata = cdata + 1
        end
        i = i + 1
        cdata = 0
    end
    ags.surface.Release()
    ags.CLUTSPR.Delete()
end


And the syntax checked out! Hopefully I'm not doing this terribly wrong. I'll continue to convert some other functions later, and look up specific syntax when needed.
Title: Re: [C++] Need advice for setting types of variables? [Now with Lua!]
Post by: Calin Leafshade on Thu 28/11/2013 10:16:34
Tidied up with comments:

I made some style changes just to make it easier for me to read. The thing about nil tables is the only issue I saw.

Code (lua) Select


function GetCLUTForRoom ()
    local i,x,y,cdata = 0,0,0,0
    local CLUTSPR = ags.DynamicSprite.CreateFromExistingSprite (ags.GetRoomProperty ("TransCLUTSlot"), false)
    local surface = ags.CLUTSPR.GetDrawingSurface ()
    while (i < 8) do
        clut[i] = clut[i] or {} -- make a new table if one doesnt exist or clut[x][y] will fail because clut[x] is nil.
        while (cdata < 65536) do
            clut[i][cdata] = ags.surface.GetPixel (x, y)
            if (x == 255 and y <2047) then
                y = y + 1
            end
            if (x < 255) then
                x = x + 1
            else
                x = 0
            end
            cdata = cdata + 1
        end
        i = i + 1
        cdata = 0
    end
    ags.surface.Release()
    ags.CLUTSPR.Delete()
end

Title: Re: [C++] Need advice for setting types of variables? [Now with Lua!]
Post by: Scavenger on Fri 29/11/2013 19:17:41
EDIT: Okay, no more crashes, as I fixed some of the syntax, but still, nothing happens when I run the Lua version of the code, where it DOES work with the AGS version.

My code looks like this:

Code (AGS) Select
function ProcessTranslucency(DynamicSprite* sprite, DynamicSprite* background, int ld, int sd, int trans)
{
  LuaValueList *list = Lua.NewValueList();
  list.Add(sprite.AsLuaValue());
  list.Add(background.AsLuaValue());
  list.Add (Lua.IntValue (ld));
  list.Add (Lua.IntValue (sd));
  list.Add (Lua.IntValue (trans));
  Lua.Call("ProcessTranslucency", list); //This is line 156
}

function noloopcheck DrawObject(this DrawingSurface*, Object *theObject) {
  if ((theObject == null) || (!theObject.Graphic) || (!theObject.Visible)) return;
  DynamicSprite *sprite;
  int graphic;
  if (objecttransparent [theObject.ID])
  {
    graphic = objecttruesprite [theObject.ID];
  }
  else graphic = theObject.Graphic;
  if (theObject.View) {
    ViewFrame *frame = Game.GetViewFrame(theObject.View, theObject.Loop, theObject.Frame);
    if (frame.Flipped) {
      sprite = DynamicSprite.CreateFromExistingSprite(frame.Graphic, true);
      sprite.Flip(eFlipLeftToRight);
    }
  }
  int scale = GetScalingAt(theObject.X, theObject.Y);
  if ((!theObject.IgnoreScaling) && (scale != 100)) {
    if (sprite == null) sprite = DynamicSprite.CreateFromExistingSprite(graphic, true);
    sprite.Resize((Game.SpriteWidth[graphic] * scale) / 100, (Game.SpriteHeight[graphic] * scale) / 100);
  }
  if (sprite != null) graphic = sprite.Graphic;
  {
    int ox = theObject.X;
    int oy = theObject.Y - Game.SpriteHeight[graphic];
    DynamicSprite *bgcopy = DynamicSprite.CreateFromDrawingSurface (this, ox, oy, Game.SpriteWidth [graphic], Game.SpriteHeight [graphic]);
    origspr[theObject.ID] = DynamicSprite.CreateFromExistingSprite (graphic);
    int sd = smallest_digit (objecttransparent[theObject.ID]);
    int ld = largest_digit  (objecttransparent[theObject.ID]);
    ProcessTranslucency(origspr[theObject.ID], bgcopy, ld, sd, objecttransparent[theObject.ID]); //Line 225. This function replaces the much slower code below.
    /*
    DrawingSurface *Surface = bgcopy.GetDrawingSurface ();
    DrawingSurface *OSSurface = origspr[theObject.ID].GetDrawingSurface ();
    int i;
    int j;
   
    int OSpixel;
    int BGpixel;
    while (j < origspr[theObject.ID].Height)
    {
      while (i < origspr[theObject.ID].Width)
      {
        OSpixel = OSSurface.GetPixel (i, j);
        if (OSpixel != COLOR_TRANSPARENT)
        {
        OSpixel = AbsInt (OSpixel);
         BGpixel = AbsInt (Surface.GetPixel (i, j));
                  if (objecttransparent[theObject.ID] > 90)
                  {
                   
                    bool alternate = true;
                    if (alternate == false)
                    {

                              OSSurface.DrawingColor = clut [ld -1].data[(BGpixel << 8) + OSpixel];
                              OSSurface.DrawPixel (i, j);
                              alternate = true;
                    }
                    else if (alternate == true)
                    {
                      OSSurface.DrawingColor = OSpixel;
                      OSSurface.DrawPixel (i, j);
                      alternate = false;
                    }
                  }
                  else if (objecttransparent[theObject.ID] > 10)
                 {

                      if (Random (sd) < sd)
                          {
                                        OSSurface.DrawingColor = clut [ld].data[(BGpixel <<8) + OSpixel];
                                        OSSurface.DrawPixel (i, j);
                          }
                      else
                          {
                 
                                        OSSurface.DrawingColor = clut [ld-1].data[(BGpixel <<8) + OSpixel];
                                        OSSurface.DrawPixel (i, j);
                          }
                 }
                 else     {
                              if (Random (sd) < sd)
                              {
                   
                                              OSSurface.DrawingColor = clut [0].data[(BGpixel <<8) + OSpixel];
                                              OSSurface.DrawPixel (i, j);
                              }
                              else {
                                              OSSurface.DrawingColor = COLOR_TRANSPARENT;
                                              OSSurface.DrawPixel (i, j);
                                   }
                          }
        }
        i++;
      }
      i = 0;
      j++;
    }
    Surface.Release ();
    OSSurface.Release ();
    */
  }
  this.DrawImage(theObject.X, theObject.Y - Game.SpriteHeight[graphic], origspr[theObject.ID].Graphic, theObject.Transparency);
  if (theObject.IgnoreScaling && objecttransparent[theObject.ID]) { theObject.Graphic = origspr[theObject.ID].Graphic; objecttranssprite[theObject.ID] = origspr[theObject.ID].Graphic; }
}


Code (Lua) Select

function GetCLUTForRoom ()
    local i,x,y,cdata = 0,0,0,0
    local CLUTSPR = ags.DynamicSprite.CreateFromExistingSprite (ags.GetRoomProperty ("TransCLUTSlot"), false)
    local surface = ags.CLUTSPR.GetDrawingSurface ()
    while (i < 8) do
        clut[i] = clut[i] or {} -- make a new table if one doesnt exist or clut[x][y] will fail because clut[x] is nil.
        while (cdata < 65536) do
            clut[i][cdata] = ags.surface.GetPixel (x, y)
            if (x == 255 and y <2047) then
                y = y + 1
            end
            if (x < 255) then
                x = x + 1
            else
                x = 0
            end
            cdata = cdata + 1
        end
        i = i + 1
        cdata = 0
    end
    ags.surface.Release()
    ags.CLUTSPR.Delete()
end


function ProcessTranslucency(ds,bg,ld,sd,trans)
    local OSSsurface = ds:GetDrawingSurface()
    local BGSurface = bg:GetDrawingSurface ()
    for y=0,ds.Height - 1 do
        for x=0,ds.Width - 1 do
        local OSpixel = ags.OSSurface.GetPixel (x, y)
        if (OSpixel > 0)
            then
                  local BGpixel = ags.BGSurface.GetPixel (x, y)
                  if (trans > 90)
                    then
                          if (alternate == nil)
                            then
                                alternate = 0
                            end
                   
                          if (alternate == 0)
                              then
                                  ags.OSSurface.DrawingColor = clut [ld -1][bit.blshift(BGPixel,8) + OSpixel]
                                  ags.OSSurface.DrawPixel (x, y)
                                  alternate = 1;
                          else if (alternate == 1)
                              then
                                  ags.OSSurface.DrawingColor = OSpixel;
                                  ags.OSSurface.DrawPixel (x, y)
                                  alternate = 0;
                              end
                     end
                  else if (trans > 10)
                    then

                          if (ags.Random (sd) < sd) then
                               ags.OSSurface.DrawingColor = clut [ld][bit.blshift(BGPixel,8) + OSpixel]
                               ags.OSSurface.DrawPixel (x, y)
                          else
                               ags.OSSurface.DrawingColor = clut [ld-1][bit.blshift(BGPixel,8) + OSpixel]
                               ags.OSSurface.DrawPixel (x, y)
                          end
                    else
                          if (Random (sd) < sd) then
                               ags.OSSurface.DrawingColor = clut [0][bit.blshift(BGPixel,8) + OSpixel]
                               ags.OSSurface.DrawPixel (x, y)
                          else
                               ags.OSSurface.DrawingColor = 0
                               ags.OSSurface.DrawPixel (x, y)
                          end
                    end
               end
            end
        end
    end
    surface:Release()
end

-- stuff
---function ColouriseArea(ds,bg,ld,sd)
--    local surface = ds:GetDrawingSurface()
--    local bgsurface
--    for y=0,ds.Height - 1 do
--        for x=0,ds.Width - 1 do
--            --Do stuff with pixel here
--        end
--    end
--    surface:Release()
--end


--function ColouriseSprite(ds,bg,ld,sd)
--    local surface = ds:GetDrawingSurface()
--    local bgsurface
--    for y=0,ds.Height - 1 do
--       for x=0,ds.Width - 1 do
--            --Do stuff with pixel here
--        end
--    end
--    surface:Release()
--end


What thing did I do wrong? I'm a little confused.

EDIT EDIT:

Quote
Illegal exception
An exception 0xC0000005 occurred in ACWIN.EXE at EIP = 0x01EB6D93 ; program pointer is +1004, ACI version 3.3.0.1148, gtags (0,50)

AGS cannot continue, this exception was fatal. Please note down the numbers above, remember what you were doing at the time and post the details on the AGS Technical Forum.

in "PAlgorithms2.asc", line 151 (list.Add(sprite.AsLuaValue()); )
from "PAlgorithms2.asc", line 225
from "PAlgorithms2.asc", line 837

I have no idea what's going on.
Title: Re: [C++] Need advice for setting types of variables? [Now with Lua!]
Post by: Crimson Wizard on Fri 29/11/2013 19:25:36
Have you tried this in AGS 3.2.1?
Title: Re: [C++] Need advice for setting types of variables? [Now with Lua!]
Post by: Scavenger on Fri 29/11/2013 19:29:50
Not yet, but I can quickly set something up in 3.2.1.

EDIT: Okay, tried it. Nothing happens. No crashes, but nothing happens.

I packaged both the 330 and 321 one in this zip: https://dl.dropboxusercontent.com/u/50882197/Game/Paltest.zip
Title: Re: [C++] Need advice for setting types of variables? [Now with Lua!]
Post by: Calin Leafshade on Fri 29/11/2013 20:35:55
That's odd. I've used the Lua plugin extensively and very rarely get crashes.

I will investigate with your packaged versions

EDIT:

Ok the problem is that you never actually run the script.. although I admit it doesnt fail very nicely.

You need to run the script to actually process the file.

Code (ags) Select

Lua.RunScript("ProcessTranslucency.lua");


in your game start

You also need to run the function like this if you want to see any errors:

Code (ags) Select

Lua.Call("ProcessTranslucency", list, eLuaUnprotectedMode);


otherwise Lua catches the errors.

EDIT AGAIN:

Ok there are actually a lot of errors with your script. I will fix them and post again.
Title: Re: [C++] Need advice for setting types of variables? [Now with Lua!]
Post by: Calin Leafshade on Fri 29/11/2013 21:04:18
Here's the fixed script. Works wonderfully at 40fps for me on linux. Looks really cool.

A few things you need to be mindful of:

- Watch case errors. Don't use the AGS built in Lua editor use ZeroBrane Studio or Notepad++ or something else with "special word" catching. It saves a lot of time.
- Colon syntax. Theres no such thing as a "method" in Lua. Objects have fields some of which may be functions but they are not methods like in an OOP language. So when calling a function which acts on the object of which it's a field it is called like this: object.function(object). This is a little messy though so Lua provides a shorthand which is object:function(). They mean the same thing and are entirely synonymous.
- Variable access. You don't need to prefix every variable with "ags." You only need do that when it's an AGS object you are interested in like ags.Display() or ags.DynamicSprite.Create. Once a variable has a local name you can refer to it by that. You can even do this to save typing and speed up access (Lua is faster at accessing local variables than globals)

Code (lua) Select

    local ds = ags.DynamicSprite
    ds.Create(320,200)


- Bitshifting. Lua doesnt have bitshifting built in so I got a module that does it and included it. The one I included is pure Lua so it's much slower than pure bitshifting but you can get the C library and include that instead if you find yourself needing the extra speed. I doubt you will.


Code (lua) Select

bit = require("bit").bit

function GetCLUTForRoom ()
    local i,x,y,cdata = 0,0,0,0
    local CLUTSPR = ags.DynamicSprite.CreateFromExistingSprite (ags.GetRoomProperty ("TransCLUTSlot"), false)
    local surface = CLUTSPR:GetDrawingSurface () -- Use : for method (i.e non static) calls. It's shorthand for object.method(object)
    clut = {} -- init clut
    while (i < 8) do
        clut[i] = clut[i] or {} -- make a new table if one doesnt exist or clut[x][y] will fail because clut[x] is nil.
        while (cdata < 65536) do
            clut[i][cdata] = surface:GetPixel (x, y)
            if (x == 255 and y <2047) then
                y = y + 1
            end
            if (x < 255) then
                x = x + 1
            else
                x = 0
            end
            cdata = cdata + 1
        end
        i = i + 1
        cdata = 0
    end
    surface:Release() -- you dont need to prefix everything with ags. only ags functions.
    CLUTSPR:Delete()
end


function ProcessTranslucency(ds,bg,ld,sd,trans)

    local OSSurface = ds:GetDrawingSurface()
    local BGSurface = bg:GetDrawingSurface ()
    for y=0,ds.Height - 1 do
        for x=0,ds.Width - 1 do
        local OSpixel = OSSurface:GetPixel (x, y) -- Colon notation again
        if (OSpixel > 0)
            then
                  local BGpixel = BGSurface:GetPixel (x, y)
                 
                  if (trans > 90)
                    then
                          if (alternate == nil)
                            then
                                alternate = 0
                            end
                   
                          if (alternate == 0)
                              then
                                  OSSurface.DrawingColor = clut [ld -1][bit.lshift(BGpixel,8) + OSpixel]
                                  OSSurface:DrawPixel (x, y)
                                  alternate = 1;
                          else if (alternate == 1)
                              then
                                  OSSurface.DrawingColor = OSpixel;
                                  OSSurface:DrawPixel (x, y)
                                  alternate = 0;
                              end
                     end
                  else if (trans > 10)
                    then

                          if (ags.Random (sd) < sd) then
                               OSSurface.DrawingColor = clut [ld][bit.lshift(BGpixel,8) + OSpixel]
                               ags.OSSurface:DrawPixel (x, y)
                          else
                              OSSurface.DrawingColor = clut [ld-1][bit.lshift(BGpixel,8) + OSpixel]
                               OSSurface:DrawPixel (x, y)
                          end
                    else
                          if (Random (sd) < sd) then
                               OSSurface.DrawingColor = clut [0][bit.lshift(BGpixel,8) + OSpixel]
                               OSSurface:DrawPixel (x, y)
                          else
                               aOSSurface.DrawingColor = 0
                               OSSurface:DrawPixel (x, y)
                          end
                    end
               end
            end
        end
    end
   
    OSSurface:Release()
    BGSurface:Release()
end

-- stuff
---function ColouriseArea(ds,bg,ld,sd)
--    local surface = ds:GetDrawingSurface()
--    local bgsurface
--    for y=0,ds.Height - 1 do
--        for x=0,ds.Width - 1 do
--            --Do stuff with pixel here
--        end
--    end
--    surface:Release()
--end


--function ColouriseSprite(ds,bg,ld,sd)
--    local surface = ds:GetDrawingSurface()
--    local bgsurface
--    for y=0,ds.Height - 1 do
--       for x=0,ds.Width - 1 do
--            --Do stuff with pixel here
--        end
--    end
--    surface:Release()
--end


And the bitshifting lib:

name it "bit.lua"

Code (lua) Select

--[[

LUA MODULE

  bit.numberlua - Bitwise operations implemented in pure Lua as numbers,
    with Lua 5.2 'bit32' and (LuaJIT) LuaBitOp 'bit' compatibility interfaces.

SYNOPSIS

  local bit = require 'bit.numberlua'
  print(bit.band(0xff00ff00, 0x00ff00ff)) --> 0xffffffff
 
  -- Interface providing strong Lua 5.2 'bit32' compatibility
  local bit32 = require 'bit.numberlua'.bit32
  assert(bit32.band(-1) == 0xffffffff)
 
  -- Interface providing strong (LuaJIT) LuaBitOp 'bit' compatibility
  local bit = require 'bit.numberlua'.bit
  assert(bit.tobit(0xffffffff) == -1)
 
DESCRIPTION
 
  This library implements bitwise operations entirely in Lua.
  This module is typically intended if for some reasons you don't want
  to or cannot  install a popular C based bit library like BitOp 'bit' [1]
  (which comes pre-installed with LuaJIT) or 'bit32' (which comes
  pre-installed with Lua 5.2) but want a similar interface.
 
  This modules represents bit arrays as non-negative Lua numbers. [1]
  It can represent 32-bit bit arrays when Lua is compiled
  with lua_Number as double-precision IEEE 754 floating point.

  The module is nearly the most efficient it can be but may be a few times
  slower than the C based bit libraries and is orders or magnitude
  slower than LuaJIT bit operations, which compile to native code.  Therefore,
  this library is inferior in performane to the other modules.

  The `xor` function in this module is based partly on Roberto Ierusalimschy's
  post in http://lua-users.org/lists/lua-l/2002-09/msg00134.html .
 
  The included BIT.bit32 and BIT.bit sublibraries aims to provide 100%
  compatibility with the Lua 5.2 "bit32" and (LuaJIT) LuaBitOp "bit" library.
  This compatbility is at the cost of some efficiency since inputted
  numbers are normalized and more general forms (e.g. multi-argument
  bitwise operators) are supported.
 
STATUS

  WARNING: Not all corner cases have been tested and documented.
  Some attempt was made to make these similar to the Lua 5.2 [2]
  and LuaJit BitOp [3] libraries, but this is not fully tested and there
  are currently some differences.  Addressing these differences may
  be improved in the future but it is not yet fully determined how to
  resolve these differences.
 
  The BIT.bit32 library passes the Lua 5.2 test suite (bitwise.lua)
  http://www.lua.org/tests/5.2/ .  The BIT.bit library passes the LuaBitOp
  test suite (bittest.lua).  However, these have not been tested on
  platforms with Lua compiled with 32-bit integer numbers.

API

  BIT.tobit(x) --> z
 
    Similar to function in BitOp.
   
  BIT.tohex(x, n)
 
    Similar to function in BitOp.
 
  BIT.band(x, y) --> z
 
    Similar to function in Lua 5.2 and BitOp but requires two arguments.
 
  BIT.bor(x, y) --> z
 
    Similar to function in Lua 5.2 and BitOp but requires two arguments.

  BIT.bxor(x, y) --> z
 
    Similar to function in Lua 5.2 and BitOp but requires two arguments.
 
  BIT.bnot(x) --> z
 
    Similar to function in Lua 5.2 and BitOp.

  BIT.lshift(x, disp) --> z
 
    Similar to function in Lua 5.2 (warning: BitOp uses unsigned lower 5 bits of shift),
 
  BIT.rshift(x, disp) --> z
 
    Similar to function in Lua 5.2 (warning: BitOp uses unsigned lower 5 bits of shift),

  BIT.extract(x, field [, width]) --> z
 
    Similar to function in Lua 5.2.
 
  BIT.replace(x, v, field, width) --> z
 
    Similar to function in Lua 5.2.
 
  BIT.bswap(x) --> z
 
    Similar to function in Lua 5.2.

  BIT.rrotate(x, disp) --> z
  BIT.ror(x, disp) --> z
 
    Similar to function in Lua 5.2 and BitOp.

  BIT.lrotate(x, disp) --> z
  BIT.rol(x, disp) --> z

    Similar to function in Lua 5.2 and BitOp.
 
  BIT.arshift
 
    Similar to function in Lua 5.2 and BitOp.
   
  BIT.btest
 
    Similar to function in Lua 5.2 with requires two arguments.

  BIT.bit32
 
    This table contains functions that aim to provide 100% compatibility
    with the Lua 5.2 "bit32" library.
   
    bit32.arshift (x, disp) --> z
    bit32.band (...) --> z
    bit32.bnot (x) --> z
    bit32.bor (...) --> z
    bit32.btest (...) --> true | false
    bit32.bxor (...) --> z
    bit32.extract (x, field [, width]) --> z
    bit32.replace (x, v, field [, width]) --> z
    bit32.lrotate (x, disp) --> z
    bit32.lshift (x, disp) --> z
    bit32.rrotate (x, disp) --> z
    bit32.rshift (x, disp) --> z

  BIT.bit
 
    This table contains functions that aim to provide 100% compatibility
    with the LuaBitOp "bit" library (from LuaJIT).
   
    bit.tobit(x) --> y
    bit.tohex(x [,n]) --> y
    bit.bnot(x) --> y
    bit.bor(x1 [,x2...]) --> y
    bit.band(x1 [,x2...]) --> y
    bit.bxor(x1 [,x2...]) --> y
    bit.lshift(x, n) --> y
    bit.rshift(x, n) --> y
    bit.arshift(x, n) --> y
    bit.rol(x, n) --> y
    bit.ror(x, n) --> y
    bit.bswap(x) --> y
   
DEPENDENCIES

  None (other than Lua 5.1 or 5.2).
   
DOWNLOAD/INSTALLATION

  If using LuaRocks:
    luarocks install lua-bit-numberlua

  Otherwise, download <https://github.com/davidm/lua-bit-numberlua/zipball/master>.
  Alternately, if using git:
    git clone git://github.com/davidm/lua-bit-numberlua.git
    cd lua-bit-numberlua
  Optionally unpack:
    ./util.mk
  or unpack and install in LuaRocks:
    ./util.mk install

REFERENCES

  [1] http://lua-users.org/wiki/FloatingPoint
  [2] http://www.lua.org/manual/5.2/
  [3] http://bitop.luajit.org/
 
LICENSE

  (c) 2008-2011 David Manura.  Licensed under the same terms as Lua (MIT).

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.
  (end license)

--]]

local M = {_TYPE='module', _NAME='bit.numberlua', _VERSION='0.3.1.20120131'}

local floor = math.floor

local MOD = 2^32
local MODM = MOD-1

local function memoize(f)
  local mt = {}
  local t = setmetatable({}, mt)
  function mt:__index(k)
    local v = f(k); t[k] = v
    return v
  end
  return t
end

local function make_bitop_uncached(t, m)
  local function bitop(a, b)
    local res,p = 0,1
    while a ~= 0 and b ~= 0 do
      local am, bm = a%m, b%m
      res = res + t[am][bm]*p
      a = (a - am) / m
      b = (b - bm) / m
      p = p*m
    end
    res = res + (a+b)*p
    return res
  end
  return bitop
end

local function make_bitop(t)
  local op1 = make_bitop_uncached(t,2^1)
  local op2 = memoize(function(a)
    return memoize(function(b)
      return op1(a, b)
    end)
  end)
  return make_bitop_uncached(op2, 2^(t.n or 1))
end

-- ok?  probably not if running on a 32-bit int Lua number type platform
function M.tobit(x)
  return x % 2^32
end

M.bxor = make_bitop {[0]={[0]=0,[1]=1},[1]={[0]=1,[1]=0}, n=4}
local bxor = M.bxor

function M.bnot(a)   return MODM - a end
local bnot = M.bnot

function M.band(a,b) return ((a+b) - bxor(a,b))/2 end
local band = M.band

function M.bor(a,b)  return MODM - band(MODM - a, MODM - b) end
local bor = M.bor

local lshift, rshift -- forward declare

function M.rshift(a,disp) -- Lua5.2 insipred
  if disp < 0 then return lshift(a,-disp) end
  return floor(a % 2^32 / 2^disp)
end
rshift = M.rshift

function M.lshift(a,disp) -- Lua5.2 inspired
  if disp < 0 then return rshift(a,-disp) end
  return (a * 2^disp) % 2^32
end
lshift = M.lshift

function M.tohex(x, n) -- BitOp style
  n = n or 8
  local up
  if n <= 0 then
    if n == 0 then return '' end
    up = true
    n = - n
  end
  x = band(x, 16^n-1)
  return ('%0'..n..(up and 'X' or 'x')):format(x)
end
local tohex = M.tohex

function M.extract(n, field, width) -- Lua5.2 inspired
  width = width or 1
  return band(rshift(n, field), 2^width-1)
end
local extract = M.extract

function M.replace(n, v, field, width) -- Lua5.2 inspired
  width = width or 1
  local mask1 = 2^width-1
  v = band(v, mask1) -- required by spec?
  local mask = bnot(lshift(mask1, field))
  return band(n, mask) + lshift(v, field)
end
local replace = M.replace

function M.bswap(x)  -- BitOp style
  local a = band(x, 0xff); x = rshift(x, 8)
  local b = band(x, 0xff); x = rshift(x, 8)
  local c = band(x, 0xff); x = rshift(x, 8)
  local d = band(x, 0xff)
  return lshift(lshift(lshift(a, 8) + b, 8) + c, 8) + d
end
local bswap = M.bswap

function M.rrotate(x, disp)  -- Lua5.2 inspired
  disp = disp % 32
  local low = band(x, 2^disp-1)
  return rshift(x, disp) + lshift(low, 32-disp)
end
local rrotate = M.rrotate

function M.lrotate(x, disp)  -- Lua5.2 inspired
  return rrotate(x, -disp)
end
local lrotate = M.lrotate

M.rol = M.lrotate  -- LuaOp inspired
M.ror = M.rrotate  -- LuaOp insipred


function M.arshift(x, disp) -- Lua5.2 inspired
  local z = rshift(x, disp)
  if x >= 0x80000000 then z = z + lshift(2^disp-1, 32-disp) end
  return z
end
local arshift = M.arshift

function M.btest(x, y) -- Lua5.2 inspired
  return band(x, y) ~= 0
end

--
-- Start Lua 5.2 "bit32" compat section.
--

M.bit32 = {} -- Lua 5.2 'bit32' compatibility


local function bit32_bnot(x)
  return (-1 - x) % MOD
end
M.bit32.bnot = bit32_bnot

local function bit32_bxor(a, b, c, ...)
  local z
  if b then
    a = a % MOD
    b = b % MOD
    z = bxor(a, b)
    if c then
      z = bit32_bxor(z, c, ...)
    end
    return z
  elseif a then
    return a % MOD
  else
    return 0
  end
end
M.bit32.bxor = bit32_bxor

local function bit32_band(a, b, c, ...)
  local z
  if b then
    a = a % MOD
    b = b % MOD
    z = ((a+b) - bxor(a,b)) / 2
    if c then
      z = bit32_band(z, c, ...)
    end
    return z
  elseif a then
    return a % MOD
  else
    return MODM
  end
end
M.bit32.band = bit32_band

local function bit32_bor(a, b, c, ...)
  local z
  if b then
    a = a % MOD
    b = b % MOD
    z = MODM - band(MODM - a, MODM - b)
    if c then
      z = bit32_bor(z, c, ...)
    end
    return z
  elseif a then
    return a % MOD
  else
    return 0
  end
end
M.bit32.bor = bit32_bor

function M.bit32.btest(...)
  return bit32_band(...) ~= 0
end

function M.bit32.lrotate(x, disp)
  return lrotate(x % MOD, disp)
end

function M.bit32.rrotate(x, disp)
  return rrotate(x % MOD, disp)
end

function M.bit32.lshift(x,disp)
  if disp > 31 or disp < -31 then return 0 end
  return lshift(x % MOD, disp)
end

function M.bit32.rshift(x,disp)
  if disp > 31 or disp < -31 then return 0 end
  return rshift(x % MOD, disp)
end

function M.bit32.arshift(x,disp)
  x = x % MOD
  if disp >= 0 then
    if disp > 31 then
      return (x >= 0x80000000) and MODM or 0
    else
      local z = rshift(x, disp)
      if x >= 0x80000000 then z = z + lshift(2^disp-1, 32-disp) end
      return z
    end
  else
    return lshift(x, -disp)
  end
end

function M.bit32.extract(x, field, ...)
  local width = ... or 1
  if field < 0 or field > 31 or width < 0 or field+width > 32 then error 'out of range' end
  x = x % MOD
  return extract(x, field, ...)
end

function M.bit32.replace(x, v, field, ...)
  local width = ... or 1
  if field < 0 or field > 31 or width < 0 or field+width > 32 then error 'out of range' end
  x = x % MOD
  v = v % MOD
  return replace(x, v, field, ...)
end


--
-- Start LuaBitOp "bit" compat section.
--

M.bit = {} -- LuaBitOp "bit" compatibility

function M.bit.tobit(x)
  x = x % MOD
  if x >= 0x80000000 then x = x - MOD end
  return x
end
local bit_tobit = M.bit.tobit

function M.bit.tohex(x, ...)
  return tohex(x % MOD, ...)
end

function M.bit.bnot(x)
  return bit_tobit(bnot(x % MOD))
end

local function bit_bor(a, b, c, ...)
  if c then
    return bit_bor(bit_bor(a, b), c, ...)
  elseif b then
    return bit_tobit(bor(a % MOD, b % MOD))
  else
    return bit_tobit(a)
  end
end
M.bit.bor = bit_bor

local function bit_band(a, b, c, ...)
  if c then
    return bit_band(bit_band(a, b), c, ...)
  elseif b then
    return bit_tobit(band(a % MOD, b % MOD))
  else
    return bit_tobit(a)
  end
end
M.bit.band = bit_band

local function bit_bxor(a, b, c, ...)
  if c then
    return bit_bxor(bit_bxor(a, b), c, ...)
  elseif b then
    return bit_tobit(bxor(a % MOD, b % MOD))
  else
    return bit_tobit(a)
  end
end
M.bit.bxor = bit_bxor

function M.bit.lshift(x, n)
  return bit_tobit(lshift(x % MOD, n % 32))
end

function M.bit.rshift(x, n)
  return bit_tobit(rshift(x % MOD, n % 32))
end

function M.bit.arshift(x, n)
  return bit_tobit(arshift(x % MOD, n % 32))
end

function M.bit.rol(x, n)
  return bit_tobit(lrotate(x % MOD, n % 32))
end

function M.bit.ror(x, n)
  return bit_tobit(rrotate(x % MOD, n % 32))
end

function M.bit.bswap(x)
  return bit_tobit(bswap(x % MOD))
end

return M
Title: Re: [C++] Need advice for setting types of variables? [Now with Lua!]
Post by: Crimson Wizard on Fri 29/11/2013 22:04:03
I am getting crashes in both 3.2.1 and 3.3.0 all the time, even if used last Calin's version of the lua script.

Can this be some bad version of lua plugin? Just a random thought. :-\

EDIT: Hmm, no, not all time. I get crash if I run the game from Compiled folder, and nothing at all if test-run from Editor. But the latter may be simply because lua scripts don't get loaded?

EDIT2: I honestly tried to debug the engine, but all I see so far is that the engine tries to call plugin functions at abnormal address.

EDIT3: And suddenly, after couple of more rebuilds, there are no crashes... But I do not see anything except for a static scene with some characters. What is supposed to happen?
Title: Re: [C++] Need advice for setting types of variables? [Now with Lua!]
Post by: Calin Leafshade on Fri 29/11/2013 22:25:07
It mimics transparency for paletted games by picking a palette colour close to the required blend. It's very clever and looks kinda cool.

To load the lua script you need to call

Code (ags) Select

Lua.RunScript("ProcessTranslucency.lua");


in game_start
Title: Re: [C++] Need advice for setting types of variables? [Now with Lua!]
Post by: Crimson Wizard on Fri 29/11/2013 22:28:48
I am using Scavenger's game project (AGS 3.2.1) with lua scripts from your previous post pasted over. I am getting crashes with exactly same error as Scavenger posted as soon as the loop counter reaches 100.

Sometimes it stops crashing after rebuild, but I suspect that may be because lua scripts get out of date? Not sure.
I do not see any transparency changes.

Wait a sec... You said you are running on Linux? Do you use JJS's port? In such case the engine uses built-in lua plugin plugin version from repository that may have some differences from the Windows plugin we are using.
Title: Re: [C++] Need advice for setting types of variables? [Now with Lua!]
Post by: Scavenger on Fri 29/11/2013 22:36:26
Thank you so much Calin! I never dreamed I'd get my module running fullspeed! Now I can use translucent images in my next game without losing any speed!

Now all I have to do is fiddle with it a bit to get it to work all across the spectrum, and possibly convert all the other parts of the module to Lua as well! I am so excited about the possibilities!
(And the CLUT generator definitely, that thing takes like an hour on this computer to render a CLUT.)

Though, now I'm getting this error:

Quote---------------------------
Adventure Game Studio
---------------------------
An internal error has occurred. Please note down the following information.
If the problem persists, post the details on the AGS Technical Forum.
(ACI version 3.3.0.1148)

Error: [Lua] [string "local select = select;local error = error;l..."]:1: bad argument #2 to 'setter' (number expected, got nil)

This happens every time there's an unclean crash in the AGS engine or editor. The project is thereafter ruined, even if the code is okay.
Title: Re: [C++] Need advice for setting types of variables? [Now with Lua!]
Post by: Calin Leafshade on Fri 29/11/2013 22:38:30
No, I'm using Wine.

I loaded the 3.2.1 project in the version of AGS I happen to have on my laptop which is:

AGS Editor .NET (Build 3.3.0.1132) ** BETA VERSION **
v3.3.0, April 2013

Title: Re: [C++] Need advice for setting types of variables? [Now with Lua!]
Post by: Calin Leafshade on Fri 29/11/2013 22:40:23
Quote from: Scavenger on Fri 29/11/2013 22:36:26
Though, now I'm getting this error:

Quote---------------------------
Adventure Game Studio
---------------------------
An internal error has occurred. Please note down the following information.
If the problem persists, post the details on the AGS Technical Forum.
(ACI version 3.3.0.1148)

Error: [Lua] [string "local select = select;local error = error;l..."]:1: bad argument #2 to 'setter' (number expected, got nil)

This happens every time there's an unclean crash in the AGS engine or editor. The project is thereafter ruined, even if the code is okay.

I have seen that error before but never found out what causes it. Maybe a Rebuild All Files might fix it, i'm not sure.
Title: Re: [C++] Need advice for setting types of variables? [Now with Lua!]
Post by: Crimson Wizard on Fri 29/11/2013 22:45:09
There's some mystery here.
3.2.1 crashes at loop count 100.
3.3.0 betas 1 - 9 do not crash, but I see no blending effect (just two opaque characters).
3.3.0 beta 10 crashes like 3.2.1.
:(

I'll check again tomorrow, maybe I am doing something wrong, or using older version of plugin or something.
Title: Re: [C++] Need advice for setting types of variables? [Now with Lua!]
Post by: Scavenger on Fri 29/11/2013 22:49:06
Rebuild All Files didn't work. Hmm. I just wish it was a little more stable on my end. :P This makes it very hard to want to use it in a real game, if there's a danger of an editor or engine crash that messes everything up. Not all script errors quit neatly!

I'll upload the project file - It works, you can see the translucency, but on Loop 17 it falls dead.

https://dl.dropboxusercontent.com/u/50882197/Game/paltest_ruined.zip (3.3.0)

And the version of Lua for AGS I'm using is the one from here: http://lua-for-ags.wikispaces.com/Downloads
Title: Re: [C++] Need advice for setting types of variables? [Now with Lua!]
Post by: Calin Leafshade on Fri 29/11/2013 22:53:10
My version works well into loop 500 with no issues.

I think this might be some issue with AGS itself. It does seem to be behaving oddly.

Posting your error into the Lua plugin thread might be helpful since I think the author monitors that thread.
Title: Re: [C++] Need advice for setting types of variables? [Now with Lua!]
Post by: Khris on Fri 29/11/2013 22:57:48
I tested this in 3.2.1 and it works fine for me.
Title: Re: [C++] Need advice for setting types of variables? [Now with Lua!]
Post by: Scavenger on Sat 30/11/2013 19:01:28
Okay, I've moved all of the necessary files over to 3.2.1 and I'll just work on this module from there until it can be confirmed that Lua and 3.3.0 can work nicely together. (And I'll hit up the Lua plugin thread to give my bug reports.)

I'm now converting this code:

Code (AGS) Select

static function PALgorithms::ProcessPalette (int palsiz, int palindex[])
{
  int paltemp [];
  paltemp = new int [palsiz];
  char i = 0;
  int i2 = 1;
  int upperboundary;
  while (i < palsiz)
  {
    paltemp [i] = (palette[palindex[i]].r +  // This algorithm produces an accurate, fast approximation of
                   palette[palindex[i]].r +  // The luminescence value of each of our palette slots.
                   palette[palindex[i]].r +  //
                   palette[palindex[i]].b +  // This ensures that when we colourise the final product, there
                   palette[palindex[i]].g +  // will be little to no weird artifacts or lightness shifts.
                   palette[palindex[i]].g +  //
                   palette[palindex[i]].g +  // By using addition and bit shifts instead of multiplication,
                   palette[palindex[i]].g    // the code will run a lot faster and more efficiently.
                   )>>3;
    i++;
  }
  i = 0;
  while (i < palsiz)
  {
      //Display ("%d , %d", i,  i+1);
      if (i > palsiz -2) upperboundary = 255;
      else upperboundary = (paltemp [i] + paltemp [i + 1])/2;
      //Display ("%d",upperboundary);

      while (i2 < upperboundary)
      {
        String output;
        _C8palgorithm [i2] = palindex[i];
        i2++;
      }
    i++;
    }
   
    i= 0;
    paltemp = new int [256];
    while (i < 255)
      {
       paltemp [i] = (palette[i].r +  // This algorithm produces an accurate, fast approximation of
                      palette[i].r +  // The luminescence value of each of our palette slots.
                      palette[i].r +  //
                      palette[i].b +  // This ensures that when we colourise the final product, there
                      palette[i].g +  // will be little to no weird artifacts or lightness shifts.
                      palette[i].g +  //
                      palette[i].g +  // By using addition and bit shifts instead of multiplication,
                      palette[i].g    // the code will run a lot faster and more efficiently.
                      )>>3;
                      i++;
      }
    i = 0;
    while (i < 255)
      {
       _C8PaletteMap [i] = _C8palgorithm [paltemp[i]];
       i++;
      }
  }


But I'm not sure how to pass a dynamic array to Lua. The wiki doesn't seem much help. :( Everything else is fine, I can deal with that, but there isn't much documentation on transferring arrays between AGS and Lua.
Title: Re: [C++] Need advice for setting types of variables? [Now with Lua!]
Post by: Calin Leafshade on Sat 30/11/2013 19:28:59
Make a new LuaValueList and add the values 1 by 1. It's not ideal but its probably the best you'll get.

(all code untested and done from memory)
Code (ags) Select

    LuaValueList *list = Lua.NewValueList();
    int i = 0;
    while (i < arrayCount)
    {
        list.Add(Lua.IntValue(array[i]))
        i ++;
    }
    Lua.Call("func", list)


Code (lua) Select

    function func(...) -- This means it has an arbitrary number of args
        local array = {...} -- This encapsulates those args into a table.
        --do shit with array
    end


If you want to have other values too you can do this:

Code (lua) Select

    function func(valA, valB, ...)
        -- now you can use valA and valB as normal and still encap the ... args.
    end
Title: Re: [C++] Need advice for setting types of variables? [Now with Lua!]
Post by: Crimson Wizard on Sat 30/11/2013 19:58:57
Quote from: Scavenger on Sat 30/11/2013 19:01:28
Okay, I've moved all of the necessary files over to 3.2.1 and I'll just work on this module from there until it can be confirmed that Lua and 3.3.0 can work nicely together.
Do you have a 3.2.1 project that works well for you? Having that will help to debug 3.3.0.
Title: Re: [C++] Need advice for setting types of variables? [Now with Lua!]
Post by: Scavenger on Sat 30/11/2013 20:24:41
The 3.2.1 files are here: https://dl.dropboxusercontent.com/u/50882197/Game/paltest321.zip

Also, how do you access the palette array with Lua? I've tried ags.palette.r et al but it just returns:
Error: [Lua][string "ProcessTranslucency.lua"]:99 attempt to index field 'palette' (a nil value)

Code (Lua) Select
function ProcessPalette (...)
  local palindex = {...}
  local paltemp = {...}
  local i = 0
  local i2 = 1
  local upperboundary
  C8Palgorithm = {}
  C8PaletteMap = {}
  while (i < table.getn(palindex))
  do
    paltemp [i] = ags.palette[i].r + ags.palette[i].r + ags.palette[i].r + ags.palette[i].b +  ags.palette[i].g + ags.palette[i].g + ags.palette[i].g + ags.palette[i].g
    paltemp [i] = bit.rshift(paltemp [i],3)
    i = i + 1
  end
  i = 0
  C8palgorithm = {}
  while (i < palsiz)
  do
      if (i > palsiz -2) then upperboundary = 255
      else upperboundary = (paltemp [i] + paltemp [i + 1])/2; end
     
      while (i2 < upperboundary)
      do
        C8palgorithm [i2] = palindex[i]
        i2 = i2 + 1
      end
    i = i + 1
  end
   
   i= 0
   paltemp = {}
   while (i < 255)
      do
       paltemp [i] = ags.palette[i].r + ags.palette[i].r + ags.palette[i].r + ags.palette[i].b +  ags.palette[i].g + ags.palette[i].g + ags.palette[i].g + ags.palette[i].g
       paltemp [i] = bit.rshift(paltemp [i],3)
       i = i+ 1
      end
    i = 0
    while (i < 255)
      do
       C8PaletteMap [i] = C8palgorithm [paltemp[i]]
       i = i + 1
      end
 
end
Title: Re: [Lua] Palette Based Graphics Programming
Post by: Calin Leafshade on Sat 30/11/2013 21:42:50
It doesn't look like there is a way to access the palette. I'd suggest posting that in the Lua Plugin thread to get it added.

You could just pass the palette to the plugin in the way I described in my last post though.
Title: Re: [Lua] Palette Based Graphics Programming
Post by: Crimson Wizard on Sat 30/11/2013 21:44:43
Hmm, interesting.

First of all, the effect I see in this game is different, the Jacob (name is right?) character is not translucent, but he has some weird effect applied on it, looks like running vertical scanlines. Is this what is expected to happen?

Secondly, I made a copy of the project, opened it in 3.3.0.1148 (beta 10) and made full rebuild. The game runs fine with same effect. No crashes so far  (waited till loop 500).
Title: Re: [Lua] Palette Based Graphics Programming
Post by: Scavenger on Sat 30/11/2013 21:48:08
I was testing the very edges of the translucency effect, since I only have 8 CLUTs at the moment, change the SetTransparency function in Room 1.asc to 50 to see a more spectacular effect.

And I'll do that, thanks Calin!
Title: Re: [Lua] Palette Based Graphics Programming
Post by: Crimson Wizard on Sat 30/11/2013 21:52:43
Quote from: Scavenger on Sat 30/11/2013 21:48:08
I was testing the very edges of the translucency effect, since I only have 8 CLUTs at the moment, change the SetTransparency function in Room 1.asc to 50 to see a more spectacular effect.
Ah, I see now. Yes, that's nice, although his legs do not look translucent. Maybe because the background color is too close, or that table missing some colors?
Anyway still works well in 3.2.1 and 3.3.0. Maybe the previous errors was due "project corruption" you mentioned?
I'll keep an eye on how this progresses, I must make sure that 3.3.0 works well with plugins.
Title: Re: [Lua] Palette Based Graphics Programming
Post by: Scavenger on Sun 01/12/2013 00:56:37
Yeah, there's probably not enough purples and purple-like colours in the palette for it to work properly. It DOES, however, work really nicely for a wide variety of effects - I'm not quite sure how to make characters translucent yet as that requires fiddling around with the ViewFrame functions and that is some deep stuff I don't want to mess around with.

I'm trying to code a workaround for passing the palette to Lua, but I don't think Lua likes having 256 parameters in it's functions.

Code (AGS) Select
function GiveLuaPalette ()
{
  LuaValueList *r = Lua.NewValueList();
    int i = 0;
    while (i < 255)
    {
        r.Add(Lua.IntValue(palette[i].r));
        i ++;
    }
    Lua.Call("CatchPalette_R", r, eLuaUnprotectedMode);
   
    LuaValueList *b = Lua.NewValueList();
    i = 0;
    while (i < 255)
    {
        b.Add(Lua.IntValue(palette[i].b));
        i ++;
    }
    Lua.Call("CatchPalette_B", b, eLuaUnprotectedMode);
   
      LuaValueList *g = Lua.NewValueList();
    i = 0;
    while (i < 255)
    {
        g.Add(Lua.IntValue(palette[i].g));
        i ++;
    }
    Lua.Call("CatchPalette_G", g, eLuaUnprotectedMode);
}


function ProcessPaletteLua (int palsiz, int palindex [])
{
  GiveLuaPalette ();
  LuaValueList *list = Lua.NewValueList();
    int i = 0;
    while (i < palsiz)
    {
        list.Add(Lua.IntValue(palindex[i]));
        i ++;
    }
    Lua.Call("ProcessPalette", list, eLuaUnprotectedMode);
}

static function PALgorithms::ProcessPalette (int palsiz, int palindex[])
{
  /*
  int paltemp [];
  paltemp = new int [palsiz];
  char i = 0;
  int i2 = 1;
  int upperboundary;
  while (i < palsiz)
  {
    paltemp [i] = (palette[palindex[i]].r +  // This algorithm produces an accurate, fast approximation of
                   palette[palindex[i]].r +  // The luminescence value of each of our palette slots.
                   palette[palindex[i]].r +  //
                   palette[palindex[i]].b +  // This ensures that when we colourise the final product, there
                   palette[palindex[i]].g +  // will be little to no weird artifacts or lightness shifts.
                   palette[palindex[i]].g +  //
                   palette[palindex[i]].g +  // By using addition and bit shifts instead of multiplication,
                   palette[palindex[i]].g    // the code will run a lot faster and more efficiently.
                   )>>3;
    i++;
  }
  i = 0;
  while (i < palsiz)
  {
      //Display ("%d , %d", i,  i+1);
      if (i > palsiz -2) upperboundary = 255;
      else upperboundary = (paltemp [i] + paltemp [i + 1])/2;
      //Display ("%d",upperboundary);

      while (i2 < upperboundary)
      {
        String output;
        _C8palgorithm [i2] = palindex[i];
        i2++;
      }
    i++;
    }
   
    i= 0;
    paltemp = new int [256];
    while (i < 255)
      {
       paltemp [i] = (palette[i].r +  // This algorithm produces an accurate, fast approximation of
                      palette[i].r +  // The luminescence value of each of our palette slots.
                      palette[i].r +  //
                      palette[i].b +  // This ensures that when we colourise the final product, there
                      palette[i].g +  // will be little to no weird artifacts or lightness shifts.
                      palette[i].g +  //
                      palette[i].g +  // By using addition and bit shifts instead of multiplication,
                      palette[i].g    // the code will run a lot faster and more efficiently.
                      )>>3;
                      i++;
      }
    i = 0;
    while (i < 255)
      {
       _C8PaletteMap [i] = _C8palgorithm [paltemp[i]];
       i++;
      }
      */
      ProcessPaletteLua (palsiz, palindex);
  }
 
function Colourise (DynamicSprite* sprite)
{
  LuaValueList *list = Lua.NewValueList();
  list.Add(sprite.AsLuaValue());
  Lua.Call("Colourise", list, eLuaUnprotectedMode);
}

function ColouriseArea (this DynamicSprite*, int x1,  int y1,  int w,  int h)
{
  DrawingSurface *Surface;
  DynamicSprite *Area;
  //Display ("Init C8");
  mouse.Visible = false;
  Wait (1);
  Area = DynamicSprite.CreateFromScreenShot (320, 200);
  //Display ("Screenshot created.");
  mouse.Visible = true;
  if (Area.ColorDepth != 8) AbortGame ("Error in COLOR8: Isn't an indexed image!");
  int realwidth = w;
  int realheight = h;
  if (x1 + w > 320) realwidth = 320 - x1;
  if (y1 + h > 200) realheight = 200 - y1;
  int realx = x1;
  int realy = y1;
  if (x1 == 320)
  {
    realx = 319;
    realwidth = 1;
  }
  if (y1 == 200)
  {
    realy = 199;
    realheight = 1;
  }
  Area.Crop (realx, realy, realwidth, realheight);
  Colourise (Area);
  /*Surface = Area.GetDrawingSurface ();
  int i;
  int j;
  int cpixel;
  while (j < h)
  {
    while (i < w)
    {
      cpixel = Surface.GetPixel (i, j);
      //Display ("Coordinates: %d, %d. Colour: %d",i, j,  Surface.GetPixel (i, j));
      if (cpixel == COLOR_TRANSPARENT) Surface.DrawingColor = COLOR_TRANSPARENT;
      else Surface.DrawingColor = _C8PaletteMap [cpixel];
      Surface.DrawPixel (i, j);
      i++;
    }
    i = 0;
    j++;
  }
  this.Crop (x1, y1, w, h);
  Surface.Release ();
  */
  this.Crop (realx, realy, realwidth, realheight);
  Surface = this.GetDrawingSurface ();
  Surface.DrawImage (0, 0, Area.Graphic);
  Surface.Release ();
  Area.Delete ();
  return this.Graphic;
}


Code (Lua) Select

function CatchPalette_R (...)
  local i = 0
  local r = {...}
  palette_r = {}
  while (i < 255)
  do
      palette_r [i] = r[i]
      i = i + 1
  end
end

function CatchPalette_B (...)
  local i = 0
  local b = {...}
  palette_b = {}
  while (i < 255)
  do
      palette_b [i] = b[i]
      i = i + 1
  end
end

function CatchPalette_G (...)
  local i = 0
  local g = {...}
  palette_g = {}
  while (i < 255)
  do
      palette_g [i] = g[i]
      i = i + 1
  end
end


function ProcessPalette (...)
  local palindex = {...}
  local paltemp = {...}
  local i = 0
  local i2 = 1
  local upperboundary
  C8Palgorithm = {}
  C8PaletteMap = {}
  while (i < table.getn(palindex))
  do
    --paltemp [i] = ags.palette[i].r + ags.palette[i].r + ags.palette[i].r + ags.palette[i].b +  ags.palette[i].g + ags.palette[i].g + ags.palette[i].g + ags.palette[i].g
    paltemp [i] = palette_r [i] + palette_r [i] + palette_r [i] + palette_b [i] +  palette_g [i] + palette_g [i] + palette_g [i] + palette_g [i]
    paltemp [i] = bit.rshift(paltemp [i],3)
    i = i + 1
  end
  i = 0
  C8palgorithm = {}
  while (i < palsiz)
  do
      if (i > palsiz -2) then upperboundary = 255
      else upperboundary = (paltemp [i] + paltemp [i + 1])/2; end
     
      while (i2 < upperboundary)
      do
        C8palgorithm [i2] = palindex[i]
        i2 = i2 + 1
      end
    i = i + 1
  end
   
   i= 0
   paltemp = {}
   while (i < 255)
      do
       --paltemp [i] = ags.palette[i].r + ags.palette[i].r + ags.palette[i].r + ags.palette[i].b +  ags.palette[i].g + ags.palette[i].g + ags.palette[i].g + ags.palette[i].g
       paltemp [i] = palette_r [i] + palette_r [i] + palette_r [i] + palette_b [i] +  palette_g [i] + palette_g [i] + palette_g [i] + palette_g [i]
       paltemp [i] = bit.rshift(paltemp [i],3)
       i = i+ 1
      end
    i = 0
    while (i < 255)
      do
       C8PaletteMap [i] = C8palgorithm [paltemp[i]]
       i = i + 1
      end
 
end

function Colourise (ds)
  local surface = ds:GetDrawingSurface ()
  local i;
  local j;
  local h = ds.Height
  local w = ds.Width
  local cpixel;
  while (j < h)
  do
    while (i < w)
    do
      cpixel = surface:GetPixel (i, j)
      if (cpixel == 0)
        then
          surface.DrawingColor = 0
      else
          surface.DrawingColor = C8PaletteMap [cpixel]
        end
      surface:DrawPixel (i, j)
      i = j + 1
    end
    i = 0
    j = j + 1
  end
  surface:Release ()
end


It just quits with an unspecified error.
Title: Re: [Lua] Palette Based Graphics Programming
Post by: Calin Leafshade on Sun 01/12/2013 01:10:26
Oh apparently you can pass arrays:

Code (ags) Select

    LuaValueList *r = Lua.NewValueList();
    int i = 0;
    while (i < 255)
    {
        r.Add(Lua.IntValue(palette[i].r));
        i ++;
    }
    Lua.Call("CatchPalette_R", r.ToArray(), eLuaUnprotectedMode);


Code (lua) Select

function CatchPalette_R (r)
  palette_r = r
end


Title: Re: [Lua] Palette Based Graphics Programming
Post by: Scavenger on Sun 01/12/2013 01:20:13
I get:

Quotepal2.asc(569): Error (line 569): '.ToArray' is not a public member of 'LuaValueList'. Are you sure you spelt it correctly (remember, capital letters are important)?

Maybe it's in a newer version than what I've got? Where's the latest version of the plugin?
Title: Re: [Lua] Palette Based Graphics Programming
Post by: Calin Leafshade on Sun 01/12/2013 02:11:56
Well its mentioned here: http://lua-for-ags.wikispaces.com/LuaValueList.ToArray%28%29

latest download woul dbe here i guess: http://lua-for-ags.wikispaces.com/Downloads
Title: Re: [Lua] Palette Based Graphics Programming
Post by: Scavenger on Sun 01/12/2013 02:27:28
Funny, I do have that version (LuaForAGS_v6_b), but it's not got ToArray in it. I'm not sure what's going on there. Perhaps it wasn't implemented yet?
Title: Re: [Lua] Palette Based Graphics Programming
Post by: Calin Leafshade on Sun 01/12/2013 02:38:59
It's not mentioned in the code so it looks like Denzil planned to implement it but never did.

you could try Lua.Evaluate.

Code (ags) Select

int i = 0;
while(i < 255)
    Lua.Evaluate(String.Format("palette_r[%d] = %d", i, value));
    i++;
end

Title: Re: [Lua] Palette Based Graphics Programming
Post by: Scavenger on Sun 01/12/2013 02:47:20
Got this:

QuoteScript link failed: Runtime Error: Unresolved import 'Lua::Evaluate^2'

I am really sorry I am having so much trouble with this. x3
Title: Re: [Lua] Palette Based Graphics Programming
Post by: Calin Leafshade on Sun 01/12/2013 02:49:15
Not a problem dude.

Seems that function is also missing.

try:

Code (ags) Select

Lua.SetVar(String.Format("palette_r[%d]",i), value)
Title: Re: [Lua] Palette Based Graphics Programming
Post by: Scavenger on Sun 01/12/2013 03:17:22
Okay, I managed to make ProcessPalette start working! It's pretty smooth up until Next error is this particularily nebulous one:

QuoteAttempt to compare nil with number

Code (Lua) Select
function ProcessPalette (...)
  local palindex = {...}
  local paltemp = {...}
  local i = 0
  local i2 = 1
  local upperboundary = 0
  C8Palgorithm = {}
  C8PaletteMap = {}
  while (i < table.getn(palindex))
  do
    --paltemp [i] = ags.palette[i].r + ags.palette[i].r + ags.palette[i].r + ags.palette[i].b +  ags.palette[i].g + ags.palette[i].g + ags.palette[i].g + ags.palette[i].g
    paltemp [i] = palette_r [i] + palette_r [i] + palette_r [i] + palette_b [i] +  palette_g [i] + palette_g [i] + palette_g [i] + palette_g [i]
    paltemp [i] = bit.rshift(paltemp [i],3)
    i = i + 1
  end
  i = 0
  C8palgorithm = {}
  while (i < table.getn(palindex))
  do
      if (i > table.getn(palindex)-2) then upperboundary = 255
      else upperboundary = (paltemp [i] + paltemp [i + 1])/2  --THIS IS THE LINE IT CHOKES AT
      end
     
      while (i2 < upperboundary)
      do
        C8palgorithm [i2] = palindex[i]
        i2 = i2 + 1
      end
    i = i + 1
  end
   
   i= 0
   paltemp = {}
   while (i < 255)
      do
       --paltemp [i] = ags.palette[i].r + ags.palette[i].r + ags.palette[i].r + ags.palette[i].b +  ags.palette[i].g + ags.palette[i].g + ags.palette[i].g + ags.palette[i].g
       paltemp [i] = palette_r [i] + palette_r [i] + palette_r [i] + palette_b [i] +  palette_g [i] + palette_g [i] + palette_g [i] + palette_g [i]
       paltemp [i] = bit.rshift(paltemp [i],3)
       i = i+ 1
      end
    i = 0
    while (i < 255)
      do
       C8PaletteMap [i] = C8palgorithm [paltemp[i]]
       i = i + 1
      end
 
end


Splitting the line into two:

Code (Lua) Select
        upperboundary = paltemp [i] + paltemp [i + 1]
        upperboundary = upperboundary /2 --It chokes here now.


I'm sure I'll be able to figure out errors like these when I get more used to Lua, but... choking on a simple division?
Title: Re: [Lua] Palette Based Graphics Programming
Post by: Calin Leafshade on Sun 01/12/2013 04:41:07
dont use table.getn use the # operator instead. #palindex returns the number of values in the array (numberically indexed) part of a table.

Quote
Attempt to compare nil with number

That error is for a comparison (i.e < > <= >= == ~=). If the value were nil you'd get an arithmatic error.
Are you sure thats the offending line?
Title: Re: [Lua] Palette Based Graphics Programming
Post by: Scavenger on Sun 01/12/2013 15:03:47
Okay, copied the lua file into Notepad++ to count the lines there, solved that issue.

But there are so many other issues cropping up I am beginning to lose hope that I'll ever get this done. I don't think I'm quite qualified to even do this.

1) The colourisation function crashes AGS with the same
Quote
Error: [Lua] [string "local select = select;local error = error;l..."]:1: bad argument #2 to 'setter' (number expected, got nil)
Error. I have no idea what is going wrong there. I added a UsingLua bool you can switch on and off to see the intended effect there.

2) Only Object 0 is affected by translucency. Even though in repeatedly_execute_always it iterates through all of the objects on screen, only Object 0 will be translucent.

3) Other objects are invisible behind a translucent object. I think this is related to 2, as somewhere along the line the function is just choking. Characters render fine. This is odd, as I knew I tested this in the AGSScript version. It just... stopped working.

I'll put the project here:
https://dl.dropboxusercontent.com/u/50882197/Game/paltest321_errors.zip
If anyone wants to take a look. It uses the FakeScreen functions (DrawObject, DrawCharacter) to build the background and the characters on it so that the translucency drawing functions know what is behind the object at the time. The workflow goes:

repeatedly execute always: Is there translucency to be rendered? If so, create a surface and start building on it until a translucent object needs to be rendered. Then, render the translucent object (DrawObject) and set that to be the object's graphic.
Title: Re: [Lua] Palette Based Graphics Programming
Post by: Denzil Quixode on Sun 01/12/2013 23:32:46
Hi, hi, really sorry you've been having all these issues with the Lua plugin! Please bear with me a little. This is a really cool project and I always wanted people to use the plugin for ambitious interesting things so I feel like I've really dropped the ball on this one. I have posted some stuff in the plugin thread about where the problem seems to be in issue 1.) there. I will address missing API functions and the lousy documentation as soon as I can. Sorry again!
Title: Re: [Lua] Palette Based Graphics Programming
Post by: Denzil Quixode on Mon 02/12/2013 12:59:03
Two problems I noticed in the Lua Colourise() function:
Code (lua) Select
while (i < w) do

  -- ( . . . ) --

  i = j + 1
end


Also, this bit in ProcessPalette:
Code (Lua) Select
while (i < palsiz)
do
  if (i > palsiz) then upperboundary = 255
  -- ... --


...looks like it should probably have "-2" added, to be equivalent to the AGSScript version in pal2.asc:

Code (AGS) Select
while (i < palsiz)
{
  if (i > palsiz -2) upperboundary = 255;
Title: Re: [Lua] Palette Based Graphics Programming
Post by: Scavenger on Tue 03/12/2013 02:25:27
It's cool, Denzil, I'm really liking this plugin and it can do some amazing things compared to plain AGSScript. It's mostly my newness to Lua that is holding me back.

I corrected those errors, but I'm still getting the same problem:

Code (Lua) Select
function Colourise (ds)
  local surface = ds:GetDrawingSurface ()
  local i = 0;
  local j= 0;
  local h = ds.Height
  local w = ds.Width
  local cpixel;
  while (j < h)
  do
    while (i < w)
    do
      cpixel = surface:GetPixel (i, j)
      if (cpixel == -1)
        then
          surface.DrawingColor = 0
      else
          surface.DrawingColor = C8PaletteMap [cpixel]
        end
      surface:DrawPixel (i, j)
      i = i + 1
    end
    i = 0
    j = j + 1
  end
  surface:Release ()
end
Title: Re: [Lua] Palette Based Graphics Programming
Post by: Calin Leafshade on Tue 03/12/2013 03:19:19
Here are some tricks to simplify your code:

Code (lua) Select

function Colourise (ds)
  local surface = ds:GetDrawingSurface ()
  local h = ds.Height
  local w = ds.Width
  local cpixel;
  for j=0, h-1 do
    for i=0, w-1 do
        cpixel = surface:GetPixel (i, j)
        surface.DrawingColor = C8PaletteMap[cpixel] or 0
        surface:DrawPixel (i, j)
    end
  end
  surface:Release ()
end


See if that crashes. It makes it so that DrawingColor can never be nil.
Title: Re: [Lua] Palette Based Graphics Programming
Post by: Denzil Quixode on Tue 03/12/2013 09:11:51
^^ Yeah, a good suggestion from Calin there. So it looks like Lua's C8PaletteMap has some holes in it, not all palette slots are being set in ProcessPalette().

One thing I notice about ProcessPalette() is that you're taking an array of parameters using palindex = {...} but this array will start from 1 rather than 0, and later code adapted from AGSScript naturally isn't expecting this. So to change it to a 0-based array, you could change the first few lines of ProcessPalette() from:

Code (Lua) Select
function ProcessPalette (...)
  local palindex = {...}
  local paltemp = {...}
  local palsiz = #palindex


...to:

Code (Lua) Select
function ProcessPalette (...)
  local palindex = {}
  local paltemp = {}
  local palsiz = select('#', ...) -- get number of arguments
  for n = 1, palsiz do
    palindex[n - 1] = select(n, ...) -- get nth argument
    paltemp[n - 1] = select(n, ...)
  end


A second thing in ProcessPalette(): it looks like, in the first while-loop, where the original AGSScript version of the function uses ags.palette[palindex[ i ]].r etc. the Lua version uses (the equivalent of) ags.palette[ i ].r
Title: Re: [Lua] Palette Based Graphics Programming
Post by: Scavenger on Tue 03/12/2013 17:07:55
Alright! With Calin and Denzil's amendments to the code, it no longer crashes, and it shows the effect! I fixed the palette[palindex[ i ]].r bit and the colours got more accurate, but they still aren't correct compared to the AGSScript version.

Code (AGS) Select
int paltemp [];
  paltemp = new int [palsiz];
  char i = 0;
  int i2 = 1;
  int upperboundary;
  while (i < palsiz)
  {
    paltemp [i] = (palette[palindex[i]].r +  // This algorithm produces an accurate, fast approximation of
                   palette[palindex[i]].r +  // The luminescence value of each of our palette slots.
                   palette[palindex[i]].r +  //
                   palette[palindex[i]].b +  // This ensures that when we colourise the final product, there
                   palette[palindex[i]].g +  // will be little to no weird artifacts or lightness shifts.
                   palette[palindex[i]].g +  //
                   palette[palindex[i]].g +  // By using addition and bit shifts instead of multiplication,
                   palette[palindex[i]].g    // the code will run a lot faster and more efficiently.
                   )>>3;
    i++;
  }
  i = 0;
  while (i < palsiz)
  {
      //Display ("%d , %d", i,  i+1);
      if (i > palsiz -2) upperboundary = 255;
      else upperboundary = (paltemp [i] + paltemp [i + 1])/2;
      //Display ("%d",upperboundary);

      while (i2 < upperboundary)
      {
        _C8palgorithm [i2] = palindex[i];
        i2++;
      }
    i++;
    }
   
    i= 0;
    paltemp = new int [256];
    while (i < 255)
      {
       paltemp [i] = (palette[i].r +  // This algorithm produces an accurate, fast approximation of
                      palette[i].r +  // The luminescence value of each of our palette slots.
                      palette[i].r +  //
                      palette[i].b +  // This ensures that when we colourise the final product, there
                      palette[i].g +  // will be little to no weird artifacts or lightness shifts.
                      palette[i].g +  //
                      palette[i].g +  // By using addition and bit shifts instead of multiplication,
                      palette[i].g    // the code will run a lot faster and more efficiently.
                      )>>3;
                      i++;
      }
    i = 0;
    while (i < 255)
      {
       _C8PaletteMap [i] = _C8palgorithm [paltemp[i]];
       i++;
      }


Code (Lua) Select
function ProcessPalette (...)
  local palindex = {}
  local paltemp = {}
  local palsiz = select('#', ...) -- get number of arguments
  for n = 1, palsiz do
     palindex[n - 1] = select(n, ...) -- get nth argument
     paltemp[n - 1] = select(n, ...)
  end
  local i = 0
  local i2 = 1
  local upperboundary = 0
  C8palgorithm = {}
  C8PaletteMap = {}
  C8PaletteMap [0] = C8PaletteMap [0] or {}
  C8palgorithm [0] = C8palgorithm [0] or {}
  while (i < palsiz)
  do
    --paltemp [i] = ags.palette[i].r + ags.palette[i].r + ags.palette[i].r + ags.palette[i].b +  ags.palette[i].g + ags.palette[i].g + ags.palette[i].g + ags.palette[i].g
    paltemp [i] = palette_r [palindex[i]] + palette_r [palindex[i]] + palette_r [palindex[i]] + palette_b [palindex[i]] +  palette_g [palindex[i]] + palette_g [palindex[i]] + palette_g [palindex[i]] + palette_g [palindex[i]]
    paltemp [i] = bit.rshift(paltemp [i],3)
    i = i + 1
  end
  i = 0
  C8palgorithm = {}
  while (i < palsiz)
  do
      if (i > palsiz - 2) then upperboundary = 255
      else
        upperboundary = paltemp [i] + paltemp [i + 1]
        upperboundary = upperboundary /2
        end
     
      while (i2 < upperboundary)
      do
        C8palgorithm [i2] = palindex[i]
        i2 = i2 + 1
      end
    i = i + 1
  end
   i= 0
   paltemp = {}
   while (i < 255)
      do
       --paltemp [i] = ags.palette[i].r + ags.palette[i].r + ags.palette[i].r + ags.palette[i].b +  ags.palette[i].g + ags.palette[i].g + ags.palette[i].g + ags.palette[i].g
       paltemp [i] = palette_r [i] + palette_r [i] + palette_r [i] + palette_b [i] +  palette_g [i] + palette_g [i] + palette_g [i] + palette_g [i]
       paltemp [i] = bit.rshift(paltemp [i],3)
       i = i+ 1
      end
    i = 0
    while (i < 255)
      do
       C8PaletteMap [i] = C8palgorithm [paltemp[i]]
       i = i + 1
      end
 
end


Is the problem that Lua is counting from 1 again in the latter part of it?

The effect now looks like this:
(https://dl.dropboxusercontent.com/u/50882197/temp/comparison.PNG)

The code looks identical, but the effect is very off. I'm not even sure how it's getting those non-blue colours.

ALSO, I'm trying to fix the translucency things, and I've noticed something very odd about the FakeScreen code I'm using:

Code (AGS) Select
while ((i < Game.CharacterCount) || (i < Room.ObjectCount)) {
    if ((i < Game.CharacterCount) && (character[i].Room == player.Room)) surface.DrawCharacter(character[i]);
    if (i < Room.ObjectCount) {
      if (object[i].Visible) surface.DrawObject(object[i]);
      if (object[i].Graphic && object[i].Visible) {
        int scale = GetScalingAt(object[i].X, object[i].Y);
        int ow = (Game.SpriteWidth[object[i].Graphic] * scale) / 100;
        int oh = (Game.SpriteHeight[object[i].Graphic] * scale) / 100;
        if (object[i].IgnoreScaling) {
          ow = Game.SpriteWidth[object[i].Graphic];
          oh = Game.SpriteHeight[object[i].Graphic];
        }
        int ox1 = object[i].X;
        int ox2 = ox1 + ow;
        int j = 0;
        while (j < Game.CharacterCount) {
          if (character[j].Room == player.Room) {
            ViewFrame *frame = Game.GetViewFrame(character[j].View, character[j].Loop, character[j].Frame);
            int cw = (Game.SpriteWidth[frame.Graphic] * character[j].Scaling) / 100;
            int cx1 = character[j].x - (cw / 2);
            if ((((cx1 + cw) >= ox1) && (cx1 <= ox2)) && (character[j].y > object[i].Baseline) && ((character[j].y - character[j].z) >= (object[i].Y - oh))) surface.DrawCharacter(character[j]);
          }
          j++;
        }
      }
    }
    i++;
  }


It doesn't take into account the baseline of the objects, and it only seems to ever draw one object on it's surface. How do I sort objects by their baseline and draw them top-to-bottom, instead of by their object IDs? Otherwise I get stuff like this:

(https://dl.dropboxusercontent.com/u/50882197/temp/transerror.PNG)

Which makes the effect kind of pointless. (The other object is invisible even when it's Y coordinate is above the translucent sprite. I have no idea what's going on!)

I'm really sorry for being so useless at solving these problems. This must be getting really irritating. x3
Title: Re: [Lua] Palette Based Graphics Programming
Post by: Denzil Quixode on Wed 04/12/2013 18:03:57
Quote from: Scavenger on Tue 03/12/2013 17:07:55
The effect now looks like this:
(https://dl.dropboxusercontent.com/u/50882197/temp/comparison.PNG)

The code looks identical, but the effect is very off. I'm not even sure how it's getting those non-blue colours.
I think there's something odd going on when you use DrawingColor zero. I tried changing Lua's Colourise() to draw every pixel to zero, and got a lot more of that colourful effect:

(http://i.imgur.com/UTrtM2s.png)

Then I tried the same as Calin's except with or 255 instead of or 0:

(http://i.imgur.com/J2bP8Vq.png)

So it looks like (I'm guessing here) drawing with DrawingColor 0 is adding transparency, punching a "hole" in the image, but what is showing up "behind" it happens to be a lot of weird pixels when Lua does it, but solid black when AGSScript does it. I've got no idea why though.
Title: Re: [Lua] Palette Based Graphics Programming
Post by: Scavenger on Wed 04/12/2013 18:47:32
Yeah, that works! Weird that Lua is doing that with DrawingColor=0. I'm guessing it doesn't show up on the Translucency because Lua doesn't actually write pixels of the 0 colour.

This is a weird bug - does it do the same thing in 16 bit and 32bit with magic pink?