• Welcome to SC4 Devotion Forum Archives.
 

News:

The SC4 Devotion Forums are no longer active, but remain online in an archived, read-only "museum" state.  It is not possible for regular members to post or use the private messaging system, and no technical support will be provided for any issues pertaining to the forums in their current state.  Attachments (those that still work) are accessible without login.

The LEX has been replaced with SC4Evermore (SC4E), and SC4E maintains an active Discord server.  For traditional forums, we recommend Simtropolis.

Main Menu

Obtaining the SC4 SDK

Started by simmaster07, September 06, 2010, 01:18:07 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

simmaster07

Quote from: null45 on October 27, 2010, 09:01:20 PM
In theory that should be the case, but when I tried to run this demo it try's to load the GZDllGetGZCOMDirector and would find something it didn't like and then would unload the dll and terminate the game.  ::) 

Perhaps this could be of assistance.

bool cGZCOMLibrary::Load()
{
   if(!mbLoaded){
      cRZString sOSEncodedPath;

      ::ConvertStringEncoding(msLibraryPath, sOSEncodedPath, kCodePageSystem);

      ///////////////////////////////////////////////////////////////
      //Platform-specific dynamic library loading
      //
      #if defined(K_WIN32)

         bool bCriticalFailure = false;

         #if defined(_UTF16)
            bCriticalFailure = !::GZCOMLoadLibrary(mHandle, sOSEncodedPath.c_str());         #else
            if(::GetVersion() & 0x80000000)     //Windows 95/98/ME -- use ANSI path
               bCriticalFailure = !::GZCOMLoadLibrary(mHandle, sOSEncodedPath.c_str());
            else{
               Uint32                        nWideLength = msLibraryPath.size();
               std::vector<RZUnicodeChar>    widePath(nWideLength+1);

               ::ConvertStringEncoding(msLibraryPath, &widePath[0], nWideLength, kCodePageUTF16);
               widePath[nWideLength] = 0;

               bCriticalFailure = !::GZCOMLoadLibraryW(mHandle, &widePath[0]);
            }
         #endif

         if(bCriticalFailure){
            RZ_DEBUG_OUTPUT("cGZCOMLibrary::Load() Error loading library %s\n", msLibraryPath.c_str() );
         }

         if(!mHandle){ //If the library load failed...
            cRZString sFailureMessage;
            RZChar*   pWin32Message = NULL;

            ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                            NULL, GetLastError(),
                            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&pWin32Message, 0, NULL);

            if(pWin32Message){
               sFailureMessage.Sprintf(RZText("Failed to load the requested dll \"%s\"\nWindows error message - \"%s\""), sOSEncodedPath.c_str(), pWin32Message);
               RZ_ASSERT_MESSAGE(false, sFailureMessage.c_str());
               ::LocalFree(pWin32Message);
            }
            return false;
         }
      #elif defined(RZ_HAS_DLOPEN)
         try {
            mHandle = ::dlopen(sOSEncodedPath.c_str(), RTLD_NOW);
         }
         catch(...){
            RZ_DEBUG_OUTPUT("cGZCOMLibrary::Load() Error loading library %s\n", msLibraryPath.c_str() );
         }

         if(!mHandle){ //If the library load failed...
            cRZString sFailureMessage;
            const char* const pdlError = dlerror();

            sFailureMessage.Sprintf("Failed to load the requested dll '%s' (%s)\n", msLibraryPath.c_str(), pdlError);
            RZ_ASSERT_MESSAGE(false, sFailureMessage.c_str());
            return false;
         }
      #else
         RZ_ASSERT(false);
      #endif
      ///////////////////////////////////////////////////////////////

      // Mark the library as loaded.
      mbLoaded = true;

      // Get the com director accessor method. GZCOM will perform all necessary
      // functions via the GZCOMDirector.
      typedef cIGZCOMDirector *(*FunctionTypeGD)();
      FunctionTypeGD pfn = NULL;

      ///////////////////////////////////////////////////////////////
      //Platform-specific dynamic library loading
      //
      #if defined(K_WIN32)
         if (!::GZCOMGetProcAddress( pfn, static_cast<HINSTANCE>(mHandle), kCOMDirectorFunctionName)){
            RZ_DEBUG_OUTPUT("cGZCOMLibrary::Load() Library %s does not have function %s(). Presumably it's not a GZCOM DLL.\n", kCOMDirectorFunctionName, msLibraryPath.c_str() );
         }
      #elif defined(RZ_HAS_DLOPEN)
         try {
            pfn = (FunctionTypeGD) ::dlsym(mHandle, kCOMDirectorFunctionName);
         }
         catch(...){
            RZ_DEBUG_OUTPUT("cGZCOMLibrary::Load() Library %s does not have function %s(). Presumably it's not a GZCOM DLL.\n", kCOMDirectorFunctionName, msLibraryPath.c_str() );
         }
      #else
         RZ_ASSERT(false);
      #endif
      ///////////////////////////////////////////////////////////////

      //Check if the function was found in the library. If not, it may not be a problem as the
      //library may simply not be one that we want to use.
      if(!pfn){
         RZ_DEBUG_OUTPUT("cGZCOMLibrary::Load: The function '%s()' was not found in library: \"%s\"\n", kCOMDirectorFunctionName, msLibraryPath.c_str());

         Free();
         return false;
      }

      //Call the COMDirector function
      cIGZCOMDirector* const pCOMDirector = pfn();
      if(!pCOMDirector){
         cRZString sMessage;
         sMessage.Sprintf("cGZCOMLibrary::Load: Failed to aquire GZCOM director from library: \"%s\"\n", msLibraryPath.c_str());
         RZ_ASSERT_MESSAGE(false, sMessage.c_str());

         Free();
         return false;
      }

      RZ_ASSERT(!mpDirector);
      mpDirector = pCOMDirector;

      // Toss over a pointer to GZCOM .. provides the ability for the dll to
      // call into the framework. Note: this function is called EVERY time
      // the dll is loaded.
      if(!pCOMDirector->InitializeCOM(GZCOM(), msLibraryPath)){
         cRZString sMessage;
         sMessage.Sprintf("cGZCOMLibrary::Load: GZCOM Director failed initialization in library: \"%s\"\n", msLibraryPath.c_str());
         RZ_ASSERT_MESSAGE(false, sMessage.c_str());

         Free();
         return false;
      }
   }
   return true;
}

cGZCOMLibrary::Free(){
   if(mbLoaded){
      DEBUG_OUTPUT_LOCAL("cGZCOMLibrary::Free: %s\n", msLibraryPath.c_str());

      if(mpDirector)
         mpDirector = NULL;

      ///////////////////////////////////////////////////////////////
      //Platform-specific dynamic library unloading
      //
      #if defined(K_WIN32)
         ::GZCOMFreeLibrary(static_cast<HINSTANCE>(mHandle), msLibraryPath.ToChar());      #elif defined(RZ_HAS_DLOPEN)
         ::dlclose(mHandle);       #else
         RZ_ASSERT(false);
      #endif
      ///////////////////////////////////////////////////////////////

      mHandle  = NULL;
      mbLoaded = false;
   }

   return true;
}

null45

I have looked at that code,  it fails somewhere after it calls the cCOMDllDirector constructor from the pointer returned by GZDllGetGZCOMDirector.

If the RZ_DEBUG_OUTPUT and RZ_ASSERT functions worked that would at least tell me where it failed.    &mmm


simmaster07

I have a DLL with the classes and stripped code. While the game doesn't terminate, it attaches and detaches with no error. :(

null45

Quote from: simmaster07 on October 29, 2010, 01:20:41 PM
I have a DLL with the classes and stripped code. While the game doesn't terminate, it attaches and detaches with no error. :(

The error messages would probably only show in a debug version of the game unfortunately, if they work in the retail version I have no idea how to enable them.   ()sad()

simmaster07

#24
Eh, I'm not giving up just yet.
(added comments marked with //--)


      //-- Since the game can run the DLL without identifying it as a GZCOM DLL,
      //-- we can safely presume that we're up to here.
      //-- Note: kCOMDirectorFunctionName = GZDllGetGZCOMDirector

      //-- If the DLLMain entry point is in the DLL, DLL_PROCESS_ATTACH
      //-- is executed.

      // Mark the library as loaded.
      mbLoaded = true;

      // Get the com director accessor method. GZCOM will perform all necessary
      // functions via the GZCOMDirector.
      typedef cIGZCOMDirector *(*FunctionTypeGD)();
      FunctionTypeGD pfn = NULL;

      ///////////////////////////////////////////////////////////////
      //Platform-specific dynamic library loading
      //
      #if defined(K_WIN32)
         //-- The game is trying to convert mHandle (DLL handle) to an instance of a handle(?)
         //-- Right now, pfn is NULL
         if (!::GZCOMGetProcAddress( pfn, static_cast<HINSTANCE>(mHandle), kCOMDirectorFunctionName)){
            RZ_DEBUG_OUTPUT("cGZCOMLibrary::Load() Library %s does not have function %s(). Presumably it's not a GZCOM DLL.\n", kCOMDirectorFunctionName, msLibraryPath.c_str() );
         }
         //-- pfn will now contain the address of the GZDllGetGZCOMDirector function, if it exists
         //-- Otherwise, RZ_DEBUG_OUTPUT() is called and pfn will remain null

      #elif defined(RZ_HAS_DLOPEN)
         try {
            //-- NON-WINDOWS systems: get the address of a symbol, or in this case, GZDllGetGZCOMDirector
            //-- This would imply that a library, such as .so files on Linux systems, can also be loaded
            pfn = (FunctionTypeGD) ::dlsym(mHandle, kCOMDirectorFunctionName);
         }
         catch(...){
            RZ_DEBUG_OUTPUT("cGZCOMLibrary::Load() Library %s does not have function %s(). Presumably it's not a GZCOM DLL.\n", kCOMDirectorFunctionName, msLibraryPath.c_str() );
         }

      #else
         //-- Cannot load a library on this system
         RZ_ASSERT(false);
      #endif
      ///////////////////////////////////////////////////////////////

      //Check if the function was found in the library. If not, it may not be a problem as the
      //library may simply not be one that we want to use.
      if(!pfn){
         RZ_DEBUG_OUTPUT("cGZCOMLibrary::Load: The function '%s()' was not found in library: \"%s\"\n", kCOMDirectorFunctionName, msLibraryPath.c_str());

         Free(); //-- DLLMain: DLL_PROCESS_DETACH
         return false; //-- Fail DLL loading, continue loading SC4
      }

      //Call the COMDirector function
      cIGZCOMDirector* const pCOMDirector = pfn(); //-- A pointer to GZDllGetGZCOMDirector()
      if(!pCOMDirector){
         //-- The function did not return a value
         cRZString sMessage;
         sMessage.Sprintf("cGZCOMLibrary::Load: Failed to aquire GZCOM director from library: \"%s\"\n", msLibraryPath.c_str());
         RZ_ASSERT_MESSAGE(false, sMessage.c_str());

         Free(); //-- DLL_PROCESS_DETACH
         return false; //-- Fail load, continue loading SC4
      }

      //-- mpDirector is currently null
      //-- Thus, !mpDirector would return true
      RZ_ASSERT(!mpDirector);

      //-- Now we assign mpDirector the value returned by GZDllGetGZCOMDirector()
      mpDirector = pCOMDirector;

      // Toss over a pointer to GZCOM .. provides the ability for the dll to
      // call into the framework. Note: this function is called EVERY time
      // the dll is loaded.

      //-- If the InitializeCOM function isn't found, unload and continue
      //-- InitializeCOM() provides access to the framework.
      if(!pCOMDirector->InitializeCOM(GZCOM(), msLibraryPath)){
         cRZString sMessage;
         sMessage.Sprintf("cGZCOMLibrary::Load: GZCOM Director failed initialization in library: \"%s\"\n", msLibraryPath.c_str());
         RZ_ASSERT_MESSAGE(false, sMessage.c_str());

         Free(); //-- DLL_PROCESS_DETACH
         return false; //-- Fail DLL loading and continue loading SC4
      }
   }
   return true;


EDIT: Have to fix one compile-time error before I can do a test on a new DLL.

HappyDays


xannepan

It's good to see the support you get!
I'm looking forward to the magic!  :P

dedgren

D. Edgren

Please call me David...

Three Rivers Region- A collaborative development of the SC4 community
The 3RR Quick Finder [linkie]


I aten't dead.  —  R.I.P. Granny Weatherwax

Skype: davidredgren

deadwoods

So that's where the name "Pedriana's Plant" comes from &idea
David, aka deadwoods

JoeST

This is quite fantastic, thank you so much. If only I knew C++ XD

Joe
Copperminds and Cuddleswarms

DAB_City

Erm, and what happens to us loyal Mac users? We can't run .dll files  &mmm
Hello SimCity Devotees! If you want to find out more about me, why not visit my profile? Free drinks and biscuits, if that would tempt anyone ;)

http://www.simtropolis.com/forum/user/360022-dab-city/

j-dub

#31
I'm afraid not (yet)
http://en.wikipedia.org/wiki/Wine_(software)

I suppose Mac also don't run .ini files, and no one could convert the DLL's to .ini so SC4 could run thoes instead.

Jonathan

Most mac users can modify the EXE directly. It is possible and not that hard to add another (just one, more requires harder work) submenu to the networks menu. GoaSkin got far in that, the
Problem was legalities of distribution and that the windows EXE is encrypted (or something like that)

DAB_City

Quote from: j-dub on September 08, 2011, 09:48:26 AM
I'm afraid not (yet)
http://en.wikipedia.org/wiki/Wine_(software)

I suppose Mac also don't run .ini files, and no one could convert the DLL's to .ini so SC4 could run thoes instead.

I do own VMWare (I don't think SC4 will run, disk copy protection  &mmm ), but my main Mac is a PPC (I share Intels with others)... I guess .ini files are a no-no too. Time to dig out a PC, I think :L
Hello SimCity Devotees! If you want to find out more about me, why not visit my profile? Free drinks and biscuits, if that would tempt anyone ;)

http://www.simtropolis.com/forum/user/360022-dab-city/

j-dub

So its not like you can use Boot Camp to switch operating systems on Mac anymore and look at Windows files that way, instead of digging up a PC?

DAB_City

I could, VMWare supports the use of Boot Camp (so you can use the same installation in Boot Camp or VMWare)... PowerPC Macs (the one I am typing on) cannot run Windows, and I'm not using the other Macs most of the time (they're not exactly mine, I'll have to see what I can do). I'm on a rather restrictive budget which all but rules out Intel Macs, but I am planning on refitting one of my PC's to run CXL and other games. I'll see what I can do.  &idea
Hello SimCity Devotees! If you want to find out more about me, why not visit my profile? Free drinks and biscuits, if that would tempt anyone ;)

http://www.simtropolis.com/forum/user/360022-dab-city/

simmaster07

In the files Paul sent me, he also sent the code which actually loads the DLLs. It makes provisions for non-DLLs, so if it's possible to compile .so files on Macs, it should theoretically run.

Jonathan

Would it be possible for you to upload the file he gave you, or did he give them to you on condition that you didn't share them? That way if/when you go MIA, it is possible for someone to take the lead for a bit?

You've done so much, it would be a shame for it stop because of RL :)  (Please don't take that the wrong way)

HappyDays

Seconding the above request, for the same reasons.

There's a lot of potential in a .dll...

null45