[Bug 30126] Matrix Games - Distant Worlds fails on startup

wine-bugs at winehq.org wine-bugs at winehq.org
Sat Mar 10 09:21:24 CST 2012


http://bugs.winehq.org/show_bug.cgi?id=30126

Anastasius Focht <focht at gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
          Component|-unknown                    |gdiplus

--- Comment #3 from Anastasius Focht <focht at gmx.net> 2012-03-10 09:21:24 CST ---
Hello,

using .NET SDK/debugger, "Reflector" tool and Wine patches to enable managed
debugging I was at least able to extract managed code sequence and parameters.

Unfortunately no IL debugging because this is already JIT compiled machine code
at this point.

Starting with backtrace and parameters at exception:

--- snip ---
(cordbg) w
Thread 0x30 Current State:GCUnsafe spot
0)* (AD 'DistantWorlds.exe', #1) System.Drawing!System.Drawing.Bitmap::.ctor(V
1, size 47) +0104[native] +0039[IL] in <Unknown File Name>:<Unknown Line
Number>
    width=0
    height=0
    format=(0x33d800) <System.Drawing.Imaging.PixelFormat>
1)  (AD 'DistantWorlds.exe', #1)
DistantWorlds!DistantWorlds.PlanetaryRingsGenerator::IP4s1vqiMTYbc(V 1, size
100) +0102[native] +0014[IL] in <Unknown File Name>:<Unknown Line Number>
    =(0x11a39fc) <System.Drawing.Bitmap>
    =(0x33d858) <System.Drawing.Rectangle>
2)  (AD 'DistantWorlds.exe', #1)
DistantWorlds!DistantWorlds.PlanetaryRingsGenerator::I5kqstLjxd9mGYbqaMBQ6MPMEDmSxAosD4j(V
1, size 26) +0127[native] +0009[IL] in <Unknown File Name>:<Unknown Line
Number>
    =(0x11a39fc) <System.Drawing.Bitmap>
    =0
3)  (AD 'DistantWorlds.exe', #1)
DistantWorlds!DistantWorlds.PlanetaryRingsGenerator::I0dnVLPuf6uVarpxEFTlj2r(V
1, size 682) +1992[native] +0668[IL] in <Unknown File Name>:<Unknown Line
Number>
    =(0x11a3028) <System.Drawing.Color[]>
    =-3.20360191431328
    =1186
    =196
    =-1
4)  (AD 'DistantWorlds.exe', #1)
DistantWorlds!DistantWorlds.PlanetaryRingsGenerator::GenerateRings(V 1, size
296) +0671[native] +0283[IL] in <Unknown File Name>:<Unknown Line Number>
    seed=0
    planetDiameter=700
5)  (AD 'DistantWorlds.exe', #1)
DistantWorlds!DistantWorlds.Main::IkVYGnH7jMvBhLaml(V 1, size 40) +0095[native]
+0010[IL] in <Unknown File Name>:<Unknown Line Number>
    =(0x1070c90) "C:\Matrix Games\Distant Worlds\images\"
    =0.5
6)  (AD 'DistantWorlds.exe', #1)
DistantWorlds!DistantWorlds.Main::IcAB016nyGW(V 1, size 224) +0234[native]
+0100[IL] in <Unknown File Name>:<Unknown Line Number>
7)  (AD 'DistantWorlds.exe', #1)
DistantWorlds!DistantWorlds.Main::IbMqCLIMV3FlOXLEMWhP(V 1, size 11468)
+9569[native] +4004[IL] in <Unknown File Name>:<Unknown Line Number>
    =1920
    =1080
8)  (AD 'DistantWorlds.exe', #1) DistantWorlds!DistantWorlds.Main::.ctor(V 1,
size 2657) +6560[native] +2656[IL] in <Unknown File Name>:<Unknown Line Number>
    width=1920
    height=1080
    splashForm=(0xee0af4) <DistantWorlds.Splash>
9)  (AD 'DistantWorlds.exe', #1)
DistantWorlds!DistantWorlds.Start::Igr8wn8mM1WnLht2ycuMoxHGm0Eh4c(V 1, size
2829) +2361[native] +0833[IL] in <Unknown File Name>:<Unknown Line Number>
    =(0xe638dc) <DistantWorlds.Start>
    =(0xe634d4) <System.EventArgs>
--- snip ---

DistantWorlds.PlanetaryRingsGenerator.GenerateRings ->
DistantWorlds.PlanetaryRingsGenerator.I0dnVLPuf6uVarpxEFTlj2r

Input params: 

--- snip ---
num13 = -3.20360191431328
num11 = 1186
num12 = 196
num1  = -1
--- snip ---

num8 = 1186

--- snip ---
private Bitmap I0dnVLPuf6uVarpxEFTlj2r(Color[] colorArray1, double num13, int
num11, int num12, int num1)
{
    if (num1 != -1)
    {
        this.IILC7Nv = num1;
        this.IOA7GLkiN9NHvPSGnRHCYsU = new Random(this.IILC7Nv);
    }
    int num = (int) ((int) (num11 * 0.22));
    Bitmap image = new Bitmap(num11, num11, PixelFormat.Format32bppPArgb);
    Graphics graphics = Graphics.FromImage(image);
    graphics.set_CompositingQuality(CompositingQuality.HighSpeed);
    graphics.set_InterpolationMode(InterpolationMode.Bilinear);
    graphics.set_SmoothingMode(SmoothingMode.AntiAlias);
    SolidBrush brush = new SolidBrush(Color.Transparent);
    graphics.FillRectangle(brush, 0, 0, num12, num);
    int index = this.IOA7GLkiN9NHvPSGnRHCYsU.Next(0, (int) colorArray1.Length);
    int num3 = (int) ((int) ((num12 * 0.5) + ((num12 *
this.IOA7GLkiN9NHvPSGnRHCYsU.NextDouble()) * 0.2)));
    Rectangle rectangle = this.Iro6aXBuEcuRl6K7sI8XXdXyuLQKgPrjsHSCqC(num11,
num, num12, num3);
    Pen pen = new Pen(colorArray1[index], (float) num3);
    graphics.DrawEllipse(pen, rectangle);
    int num4 = this.IOA7GLkiN9NHvPSGnRHCYsU.Next(2, 6);
    for (int i = 0; i < num4; i = (int) (i + 1))
    {
        index = this.IOA7GLkiN9NHvPSGnRHCYsU.Next(0, (int) colorArray1.Length);
        num3 = (int) ((int) ((num12 * 0.5) *
this.IOA7GLkiN9NHvPSGnRHCYsU.NextDouble()));
        rectangle = this.Iro6aXBuEcuRl6K7sI8XXdXyuLQKgPrjsHSCqC(num11, num,
num12, num3);
        pen = new Pen(colorArray1[index], (float) num3);
        graphics.DrawEllipse(pen, rectangle);
    }
    int num6 = this.IOA7GLkiN9NHvPSGnRHCYsU.Next(30, 50);
    for (int j = 0; j < num6; j = (int) (j + 1))
    {
        index = this.IOA7GLkiN9NHvPSGnRHCYsU.Next(0, (int) colorArray1.Length);
        num3 = (int) (1 + this.IOA7GLkiN9NHvPSGnRHCYsU.Next(0, 2));
        Color color = colorArray1[index];
        rectangle = this.Iro6aXBuEcuRl6K7sI8XXdXyuLQKgPrjsHSCqC(num11, num,
num12, num3);
        pen = new Pen(color, (float) num3);
        graphics.DrawEllipse(pen, rectangle);
    }
    Bitmap bitmap2 = new Bitmap(num11, num, PixelFormat.Format32bppPArgb);
    Graphics graphics2 = Graphics.FromImage(bitmap2);
    graphics2.set_InterpolationMode(InterpolationMode.HighQualityBilinear);
    graphics2.set_SmoothingMode(SmoothingMode.HighSpeed);
    graphics2.DrawImage(image, new Rectangle(0, 0, image.get_Width(), num), new
Rectangle(0, 0, image.get_Width(), image.get_Height()), GraphicsUnit.Pixel);
    int num8 = Math.Max(bitmap2.get_Width(), bitmap2.get_Height());
    Bitmap bitmap3 = new Bitmap(num8, num8, PixelFormat.Format32bppPArgb);
    Graphics graphics3 = Graphics.FromImage(bitmap3);
    int num9 = (int) ((num8 - bitmap2.get_Width()) / 2);
    int num10 = (int) ((num8 - bitmap2.get_Height()) / 2);
    graphics3.set_CompositingQuality(CompositingQuality.HighSpeed);
    graphics3.set_InterpolationMode(InterpolationMode.Bilinear);
    graphics3.set_SmoothingMode(SmoothingMode.HighSpeed);
    graphics3.DrawImage(bitmap2, num9, num10);
    bitmap2.Dispose();
    bitmap3 = this.Igr8wn8mM1WnLht2ycuMoxHGm0Eh4c(bitmap3, (float) num13);
    return this.I5kqstLjxd9mGYbqaMBQ6MPMEDmSxAosD4j(bitmap3, 0);
}
--- snip ---

There is no error returned by gdiplus in various transformation/drawing
operations prior creating the final "planetary rings" bitmap.
It's a huge log filtering for gdiplus related calls alone.

num1 = 0

--- snip ---
private Bitmap I5kqstLjxd9mGYbqaMBQ6MPMEDmSxAosD4j(Bitmap bitmap1, int num1)
{
    Rectangle rectangle = this.IGNof4F(bitmap1, num1);
    Bitmap bitmap = this.IP4s1vqiMTYbc(bitmap1, rectangle);
    bitmap1.Dispose();
    return bitmap;
}
...
private Rectangle IGNof4F(Bitmap bitmap1, int num1)
{
    return this.ILRXNme(bitmap1, num1, Color.Empty, 0, 4);
}
...
private Rectangle ILRXNme(Bitmap bitmap1, int num14, Color color1, int num1,
int num13)
{
    Rectangle rectangle = new Rectangle();
    FastBitmap bitmap = new FastBitmap(bitmap1);
    int num = 0;
    int num2 = 0;
    int num3 = 0;
    int num4 = 0;
    bool flag = false;
    for (int i = 0; i < bitmap1.get_Width(); i = (int) (i + num13))
    {
        for (int n = 0; n < bitmap1.get_Height(); n = (int) (n + num13))
        {
            if (!color1.get_IsEmpty())
            {
                Color pixel = bitmap.GetPixel(ref i, ref n);
                if (((pixel.get_R() <= (color1.get_R() + num1)) &&
(pixel.get_G() <= (color1.get_G() + num1))) && (pixel.get_B() <=
(color1.get_B() + num1)))
                {
                    continue;
                }
                num = Math.Max(0, (int) (i - num13));
                flag = true;
                break;
            }
            if (bitmap.GetPixel(ref i, ref n).get_A() > num14)
            {
                num = Math.Max(0, (int) (i - num13));
                flag = true;
                break;
            }
        }
        if (flag)
        {
            break;
        }
    }
    flag = false;
    for (int j = (int) (bitmap1.get_Width() - 1); j >= 0; j = (int) (j -
num13))
    {
        for (int num8 = 0; num8 < bitmap1.get_Height(); num8 = (int) (num8 +
num13))
        {
            if (!color1.get_IsEmpty())
            {
                Color color2 = bitmap.GetPixel(ref j, ref num8);
                if (((color2.get_R() <= (color1.get_R() + num1)) &&
(color2.get_G() <= (color1.get_G() + num1))) && (color2.get_B() <=
(color1.get_B() + num1)))
                {
                    continue;
                }
                num2 = Math.Min((int) (bitmap1.get_Width() - 1), (int) (j +
num13));
                flag = true;
                break;
            }
            if (bitmap.GetPixel(ref j, ref num8).get_A() > num14)
            {
                num2 = Math.Min((int) (bitmap1.get_Width() - 1), (int) (j +
num13));
                flag = true;
                break;
            }
        }
        if (flag)
        {
            break;
        }
    }
    flag = false;
    for (int k = 0; k < bitmap1.get_Height(); k = (int) (k + num13))
    {
        for (int num10 = 0; num10 < bitmap1.get_Width(); num10 = (int) (num10 +
num13))
        {
            if (!color1.get_IsEmpty())
            {
                Color color3 = bitmap.GetPixel(ref num10, ref k);
                if (((color3.get_R() <= (color1.get_R() + num1)) &&
(color3.get_G() <= (color1.get_G() + num1))) && (color3.get_B() <=
(color1.get_B() + num1)))
                {
                    continue;
                }
                num3 = Math.Max(0, (int) (k - num13));
                flag = true;
                break;
            }
            if (bitmap.GetPixel(ref num10, ref k).get_A() > num14)
            {
                num3 = Math.Max(0, (int) (k - num13));
                flag = true;
                break;
            }
        }
        if (flag)
        {
            break;
        }
    }
    flag = false;
    for (int m = (int) (bitmap1.get_Height() - 1); m >= 0; m = (int) (m -
num13))
    {
        for (int num12 = 0; num12 < bitmap1.get_Width(); num12 = (int) (num12 +
num13))
        {
            if (!color1.get_IsEmpty())
            {
                Color color4 = bitmap.GetPixel(ref num12, ref m);
                if (((color4.get_R() <= (color1.get_R() + num1)) &&
(color4.get_G() <= (color1.get_G() + num1))) && (color4.get_B() <=
(color1.get_B() + num1)))
                {
                    continue;
                }
                num4 = Math.Min((int) (bitmap1.get_Height() - 1), (int) (m +
num13));
                flag = true;
                break;
            }
            if (bitmap.GetPixel(ref num12, ref m).get_A() > num14)
            {
                num4 = Math.Min((int) (bitmap1.get_Height() - 1), (int) (m +
num13));
                flag = true;
                break;
            }
        }
        if (flag)
        {
            break;
        }
    }
    bitmap.Release();
    return new Rectangle(num, num3, (int) (num2 - num), (int) (num4 - num3));
}
--- snip ---

(FastBitmap seems to be a small internal wrapper class to access the pixel data
directly)

An empty bounding rectangle is returned, maybe alpha/transparency issue or the
pixel buffer content is wrong due to earlier operations.

One approach could be to reduce/transform the managed code snippets (C#) into
small .NET executable to test/play with (Wine vs. native gdiplus).

Regards

-- 
Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email
Do not reply to this email, post in Bugzilla using the
above URL to reply.
------- You are receiving this mail because: -------
You are watching all bug changes.



More information about the wine-bugs mailing list