Curse of the Azure Bonds – build 1.0.20

Build 1.0.20 has been released. Fixed in this version:

  • Issue 32, Fixed manual targeting
  • Issue 33, Fixed Magic-Users spell selection on levelling to show new spells, not current
  • Issue 34, Fixed the combat Aiming crash at the edges of the screen
  • Issue 35, Fixed Magic-Users spell selection on levelling to show level 5 spells
  • Issue 38, Loss of excess Exp when level, was in original DOS game, but I’ve removed it
  • Add new cheat to sort treasure (most valuable at top)
  • Screen Capture now save to “My Pictures” as “Curse – xxxx.png”
  • Settings are now kept across upgrades

I have some more issues to track down, but I’m hoping this build will solve the worst of them.

Enjoy.

Book: Cost & Management Accounting: An Introduction

cost-and-management-accounting-an-introductionI have just finish reading Cost & Management Account: An Introduction by M. R. Mathews. I purchased this book off TradeMe six years ago. So it’s not been on my must read list, but I have slowly read it over the years.

The book is old 1981, but it’s still an interesting read.

Funest example in the book, starts like this:

Mole Ltd, installed a small desk computer on 1 May 1979 at a cost of $18,750 ….

how many K for small desk computer….

Also nice old-school 50 cents on the cover…

SafeArrayTypeMismatchException

We extended our legacy C++ DCOM application last week, and when the developer wrote the C#.Net end to call the new method, we were getting the error:

System.Runtime.InteropServices.SafeArrayTypeMismatchException

The developer that had added the method stated it work, and pointed to his Delphi test app that worked happily.

Reviewing the method code it all looked fine. Single stepping through the code there where no problems.

The help for this exception says:

The exception thrown when the type of the incoming SAFEARRAY does not match the type specified in the managed signature.

But as we are dynamically calling the method like this:

objAddType = Type.GetTypeFromProgID("DCOM_OBJECT_NAME.COMPANY_CLASS_A");
objAdd = Activator.CreateInstance(objAddType);

object[] input = {};

object result = objAddType.InvokeMember("MethodName", BindingFlags.InvokeMethod, null, objAdd, input);

There was no was no signature.

This is for this Method:

VARIANT CompanyClassAObject::MethodName(void)
{
    VARIANT vaResult;
    VariantInit(&vaResult);

    SAFEARRAY* sfa = GetSafeArray();

    vaResult.vt = VT_UI1 | VT_ARRAY;
    vaResult.parray = sfa;

    return vaResult;
}

with the body of GetSafeArray looked like:

    SAFEARRAYBOUND sfabounds[1];
    sfabounds[0].lLbound = 0;
    sfabounds[0].cElements = bytes_needed;
    SAFEARRAY *sfa = SafeArrayCreate(VT_I1, 1, sfabounds);
    if(sfa)
    {
        void *data;
        if(SafeArrayAccessData(sfa, &data) == S_OK)
        {
            memcpy(data, buffer, bytes_needed);
            SafeArrayUnaccessData(sfa);

            delete buffer;
            return sfa;
        }
    }

The problem ended up being that the SafeArray is created as VT_I1 type but when it is put into the variant type it was typed as VT_UI1.  So the .Net runtime was picking up the conflict and correctly complaining, and once you know what the error is, the exception message make sense.  Funny that!

Setting the SafeArrayCreate to use VT_UI1 and every thing worked.