Conversion to patch 3.17

Status
Not open for further replies.

Maniac

Apolyton Sage
Joined
Nov 27, 2004
Messages
5,603
Location
Gent, Belgium
Conversion to 3.17 is complete.

***

I've managed to set up CodeBlocks myself to compile a DLL. Have already eradicated two error myself. However there's a problem with CvInfos.cpp, more specifically differences 10-14 (see below in old post) and surroundings of a comparison between unmodded 3.13 and 3.17 files.

The two const's added by Planetfall don't seem to be working. And the unit workshop seems to use the const's which were changed in patch 3.17. Thus causing a load of errors in this file.

See attached picture.

***Old post***

I've copied over the 3.17 changes into the Planetfall SDK. There are 43 files which have been changed both by 3.17 and Planetfall. Fortunately within these files, it are usually different areas which are changed, so mostly it was just a boring matter of time of merging them together.

The list of the files changed by both 317 and Planetfall:

Spoiler :
CvCity.h
CvCityAI.cpp
CvDeal.ccp
CvDefines.h
CvDLLButtonPopup.cpp
CvDLLWidgetData.cpp
CvEnums.h
CvGame.cpp
CvGameInterface.cpp
CvGameTextMgr.cpp
CvGameTextMgr.h
CvGlobals.cpp
CvGlobals.h
CvInfos.cpp
CvInfos.h
CvPlayer.cpp
CvPlayer.h
CvPlayerAI.cpp
CvPlot.cpp
CvSelectionGroup.cpp
CvSelectionGroup.h
CvSelectionGroupAI.cpp
CvTeam.cpp
CvTeam.h
CvTeamAI.cpp
CvUnit.cpp
CvUnit.h
CvUnitAI.cpp
CvXMLLoadUtility.h
CvXMLLoadUtilitySet.cpp
CyEnumsInterface.cpp
CyGame.cpp
CyGame.h
CyGameInterface.cpp
CyInfoInterface1.cpp
CyInfoInterface3.cpp
CyPlot.cpp
CyPlot.h
CyPlotInterface1.cpp
CyStructsInterface.cpp
CyUnit.cpp
CyUnit.h
CyUnitInterface1.cpp


There are a couple of cases though where code had been changed both by Planetfall and 317. In that case due to my limited understanding, I don't know what to do. I was hoping one of you guys could have a look.

The difference number indicated is that of a WinMerge comparison between 313 and 317 SDK files.

CvXMLLoadUtility.h - difference 4 of 21

Spoiler :
Patch 317 moves some code.

313 code

Code:
	// overloaded function that gets the child value of the tag with szName if there is only one child
	// value of that name
	DllExport void MapChildren();	// call this before GetChildXMLValByName to use fast searching
	DllExport bool GetChildXmlValByName(std::string& pszVal, const TCHAR* szName, char* pszDefault = NULL);
	DllExport bool GetChildXmlValByName(std::wstring& pszVal, const TCHAR* szName, wchar* pszDefault = NULL);
	// overloaded function that gets the child value of the tag with szName if there is only one child
	// value of that name
	DllExport bool GetChildXmlValByName(char* pszVal, const TCHAR* szName, char* pszDefault = NULL);
	DllExport bool GetChildXmlValByName(wchar* pszVal, const TCHAR* szName, wchar* pszDefault = NULL);
	// overloaded function that gets the child value of the tag with szName if there is only one child
	// value of that name
	DllExport bool GetChildXmlValByName(int* piVal, const TCHAR* szName, int iDefault = 0);
	// overloaded function that gets the child value of the tag with szName if there is only one child
	// value of that name
	DllExport bool GetChildXmlValByName(float* pfVal, const TCHAR* szName, float fDefault = 0.0f);
	// overloaded function that gets the child value of the tag with szName if there is only one child
	// value of that name
	DllExport bool GetChildXmlValByName(bool* pbVal, const TCHAR* szName, bool bDefault = false);

In Patch 317 its taken by simply this:

Code:
#ifdef _USRDLL
	FXml* GetXML() { return m_pFXml; }
#endif

The 313 code gets moved to a spot earlier in the file. In addition, this gets added after it:

Code:
	// loads an xml file into the FXml variable.  The szFilename parameter has
	// the m_szXmlPath member variable pre-pended to it to form the full pathname
	DllExport bool LoadCivXml(FXml* pFXml, const TCHAR* szFilename);

Planetfall however added a new line of code right after the old 313 code copied here:

Code:
	bool GetChildXMLInfoClassByName(int* piIndex, const TCHAR* szName, int iDefault = -1);

Now I have no idea what this 313 code did in the first place, why it was moved in 317, if the place in the file plays a role at all, and why those extra lines were added to 317 and Planetfall. So here I have no idea at all what to do with this Planetfall line of code.


CvCity.cpp - difference 18 of 27

The 317 addition mentions unitinfos, but Ellestar has changed it so the great people rate accumulates points towards a specialist (and then looks what unit that specialist gives), instead of directly accumulating points toward a unit.

Of course turning off espionage is not an option I would recommend (after we've changed espionage to make it more interesting than vanilla BtS...), but I assume not including this piece of code might cause problems if someone gets the idea to play with espionage off?

More specifically, the problem here is "GC.getUnitInfo(eIndex).getEspionagePoints() > 0" which was added in the 317 code. Great People points in Planetfall are currently accumulated towards specialists, not towards units. Would a possible soluton be something like "getSpecialistInfo->getGreatPeopleUnitClass->getEspionagePoints() > 0"?? How do you say that in C++?

Spoiler :
3.13 code

Code:
void CvCity::setGreatPeopleUnitRate(UnitTypes eIndex, int iNewValue)										 
{
	FAssertMsg(eIndex >= 0, "eIndex expected to be >= 0");
	FAssertMsg(eIndex < GC.getNumUnitInfos(), "eIndex expected to be < GC.getNumUnitInfos()");
	m_paiGreatPeopleUnitRate[eIndex] = iNewValue;
	FAssert(getGreatPeopleUnitRate(eIndex) >= 0);
}

3.17 code

Code:
void CvCity::setGreatPeopleUnitRate(UnitTypes eIndex, int iNewValue)										 
{
	FAssertMsg(eIndex >= 0, "eIndex expected to be >= 0");
	FAssertMsg(eIndex < GC.getNumUnitInfos(), "eIndex expected to be < GC.getNumUnitInfos()");
	if (GC.getGameINLINE().isOption(GAMEOPTION_NO_ESPIONAGE) && GC.getUnitInfo(eIndex).getEspionagePoints() > 0)
	{
		return;
	}

	m_paiGreatPeopleUnitRate[eIndex] = iNewValue;
	FAssert(getGreatPeopleUnitRate(eIndex) >= 0);
}

Planetfall code

Code:
void CvCity::setGreatPeopleSpecialistRate(SpecialistTypes eIndex, int iNewValue)										 
{
	FAssertMsg(eIndex >= 0, "eIndex expected to be >= 0");
	FAssertMsg(eIndex < GC.getNumSpecialistInfos(), "eIndex expected to be < GC.getNumUnitInfos()");
	m_paiGreatPeopleSpecialistRate[eIndex] = iNewValue;
	FAssert(getGreatPeopleSpecialistRate(eIndex) >= 0);
}

CvCity.cpp - differences 20-25 of 27

These changes also involve Great People, which has also been modified by Ellestar. I have the suspicion a Planetfall DLL might work even without any changes here. Except for coding in a safety guard when enough Great People Points have been accumulated, but there is no Unit defined to appear, and except for changing the places some integers are introduced, the code seems just the same.
In any case, I've tried to merge the code here myself, but the blessing from an experienced SDKer would be welcome!

Spoiler :
313 code

Code:
void CvCity::doGreatPeople()
{
	UnitTypes eGreatPeopleUnit;
	int iTotalGreatPeopleUnitProgress;
	int iGreatPeopleUnitRand;
	int iI;

	CyCity* pyCity = new CyCity(this);
	CyArgsList argsList;
	argsList.add(gDLL->getPythonIFace()->makePythonObject(pyCity));	// pass in city class
	long lResult=0;
	gDLL->getPythonIFace()->callFunction(PYGameModule, "doGreatPeople", argsList.makeFunctionArgs(), &lResult);
	delete pyCity;	// python fxn must not hold on to this pointer 
	if (lResult == 1)
	{
		return;
	}

	if (isDisorder())
	{
		return;
	}

	changeGreatPeopleProgress(getGreatPeopleRate());

	for (iI = 0; iI < GC.getNumUnitInfos(); iI++)
	{
		changeGreatPeopleUnitProgress(((UnitTypes)iI), getGreatPeopleUnitRate((UnitTypes)iI));
	}

	if (getGreatPeopleProgress() >= GET_PLAYER(getOwnerINLINE()).greatPeopleThreshold(false))
	{
		changeGreatPeopleProgress(-(GET_PLAYER(getOwnerINLINE()).greatPeopleThreshold(false)));

		iTotalGreatPeopleUnitProgress = 0;

		for (iI = 0; iI < GC.getNumUnitInfos(); iI++)
		{
			iTotalGreatPeopleUnitProgress += getGreatPeopleUnitProgress((UnitTypes)iI);
		}

		iGreatPeopleUnitRand = GC.getGameINLINE().getSorenRandNum(iTotalGreatPeopleUnitProgress, "Great Person");

		eGreatPeopleUnit = NO_UNIT;

		for (iI = 0; iI < GC.getNumUnitInfos(); iI++)
		{
			if (iGreatPeopleUnitRand < getGreatPeopleUnitProgress((UnitTypes)iI))
			{
				eGreatPeopleUnit = ((UnitTypes)iI);
				break;
			}
			else
			{
				iGreatPeopleUnitRand -= getGreatPeopleUnitProgress((UnitTypes)iI);
			}
		}

		if (eGreatPeopleUnit != NO_UNIT)
		{
			for (iI = 0; iI < GC.getNumUnitInfos(); iI++)
			{
				setGreatPeopleUnitProgress(((UnitTypes)iI), 0);
			}

			createGreatPeople(eGreatPeopleUnit, true, false);
		}
	}
}

317 code

Code:
void CvCity::doGreatPeople()
{
	CyCity* pyCity = new CyCity(this);
	CyArgsList argsList;
	argsList.add(gDLL->getPythonIFace()->makePythonObject(pyCity));	// pass in city class
	long lResult=0;
	gDLL->getPythonIFace()->callFunction(PYGameModule, "doGreatPeople", argsList.makeFunctionArgs(), &lResult);
	delete pyCity;	// python fxn must not hold on to this pointer 
	if (lResult == 1)
	{
		return;
	}

	if (isDisorder())
	{
		return;
	}

	changeGreatPeopleProgress(getGreatPeopleRate());

	for (int iI = 0; iI < GC.getNumUnitInfos(); iI++)
	{
		changeGreatPeopleUnitProgress(((UnitTypes)iI), getGreatPeopleUnitRate((UnitTypes)iI));
	}

	if (getGreatPeopleProgress() >= GET_PLAYER(getOwnerINLINE()).greatPeopleThreshold(false))
	{
		int iTotalGreatPeopleUnitProgress = 0;
		for (int iI = 0; iI < GC.getNumUnitInfos(); iI++)
		{
			iTotalGreatPeopleUnitProgress += getGreatPeopleUnitProgress((UnitTypes)iI);
		}

		int iGreatPeopleUnitRand = GC.getGameINLINE().getSorenRandNum(iTotalGreatPeopleUnitProgress, "Great Person");

		UnitTypes eGreatPeopleUnit = NO_UNIT;
		for (int iI = 0; iI < GC.getNumUnitInfos(); iI++)
		{
			if (iGreatPeopleUnitRand < getGreatPeopleUnitProgress((UnitTypes)iI))
			{
				eGreatPeopleUnit = ((UnitTypes)iI);
				break;
			}
			else
			{
				iGreatPeopleUnitRand -= getGreatPeopleUnitProgress((UnitTypes)iI);
			}
		}

		if (eGreatPeopleUnit != NO_UNIT)
		{
			changeGreatPeopleProgress(-(GET_PLAYER(getOwnerINLINE()).greatPeopleThreshold(false)));

			for (int iI = 0; iI < GC.getNumUnitInfos(); iI++)
			{
				setGreatPeopleUnitProgress(((UnitTypes)iI), 0);
			}

			createGreatPeople(eGreatPeopleUnit, true, false);
		}
	}
}

Current Planetfall code

Code:
void CvCity::doGreatPeople()
{
	UnitTypes eGreatPeopleUnit;
	SpecialistTypes eGreatPeopleSpecialist;
	int iTotalGreatPeopleSpecialistProgress;
	int iGreatPeopleSpecialistRand;
	int iI;

	CyCity* pyCity = new CyCity(this);
	CyArgsList argsList;
	argsList.add(gDLL->getPythonIFace()->makePythonObject(pyCity));	// pass in city class
	long lResult=0;
	gDLL->getPythonIFace()->callFunction(PYGameModule, "doGreatPeople", argsList.makeFunctionArgs(), &lResult);
	delete pyCity;	// python fxn must not hold on to this pointer 
	if (lResult == 1)
	{
		return;
	}

	if (isDisorder())
	{
		return;
	}

	changeGreatPeopleProgress(getGreatPeopleRate());

	for (iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
	{
		changeGreatPeopleSpecialistProgress(((SpecialistTypes)iI), getGreatPeopleSpecialistRate((SpecialistTypes)iI));
	}

	if (getGreatPeopleProgress() >= GET_PLAYER(getOwnerINLINE()).greatPeopleThreshold(false))
	{
		changeGreatPeopleProgress(-(GET_PLAYER(getOwnerINLINE()).greatPeopleThreshold(false)));

		iTotalGreatPeopleSpecialistProgress = 0;

		for (iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
		{
			iTotalGreatPeopleSpecialistProgress += getGreatPeopleSpecialistProgress((SpecialistTypes)iI);
		}

		iGreatPeopleSpecialistRand = GC.getGameINLINE().getSorenRandNum(iTotalGreatPeopleSpecialistProgress, "Great Person");

		eGreatPeopleSpecialist = NO_SPECIALIST;

		for (iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
		{
			if (iGreatPeopleSpecialistRand < getGreatPeopleSpecialistProgress((SpecialistTypes)iI))
			{
				eGreatPeopleSpecialist = ((SpecialistTypes)iI);
				break;
			}
			else
			{
				iGreatPeopleSpecialistRand -= getGreatPeopleSpecialistProgress((SpecialistTypes)iI);
			}
		}

		if (eGreatPeopleSpecialist != NO_SPECIALIST)
		{
			for (iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
			{
				setGreatPeopleSpecialistProgress(((SpecialistTypes)iI), 0);
			}
			int iUnitClass = GC.getSpecialistInfo(eGreatPeopleSpecialist).getGreatPeopleUnitClass();
			if (iUnitClass != NO_UNITCLASS)
			{
				eGreatPeopleUnit = ((UnitTypes)(GC.getCivilizationInfo(GET_PLAYER(getOwner()).getCivilizationType()).getCivilizationUnits(iUnitClass)));

				if (eGreatPeopleUnit != NO_UNIT)
				{
					createGreatPeople(eGreatPeopleUnit, true, false);
				}
			}
		}
	}
}

Does this look good?

Code:
void CvCity::doGreatPeople()
{
	CyCity* pyCity = new CyCity(this);
	CyArgsList argsList;
	argsList.add(gDLL->getPythonIFace()->makePythonObject(pyCity));	// pass in city class
	long lResult=0;
	gDLL->getPythonIFace()->callFunction(PYGameModule, "doGreatPeople", argsList.makeFunctionArgs(), &lResult);
	delete pyCity;	// python fxn must not hold on to this pointer 
	if (lResult == 1)
	{
		return;
	}

	if (isDisorder())
	{
		return;
	}

	changeGreatPeopleProgress(getGreatPeopleRate());

	for (int iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
	{
		changeGreatPeopleSpecialistProgress(((SpecialistTypes)iI), getGreatPeopleSpecialistRate((SpecialistTypes)iI));
	}

	if (getGreatPeopleProgress() >= GET_PLAYER(getOwnerINLINE()).greatPeopleThreshold(false))
	{
		int iTotalGreatPeopleSpecialistProgress = 0;

		for (int iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
		{
			iTotalGreatPeopleSpecialistProgress += getGreatPeopleSpecialistProgress((SpecialistTypes)iI);
		}

		int iGreatPeopleSpecialistRand = GC.getGameINLINE().getSorenRandNum(iTotalGreatPeopleSpecialistProgress, "Great Person");

		SpecialistTypes eGreatPeopleSpecialist = NO_SPECIALIST;

		for (int iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
		{
			if (iGreatPeopleSpecialistRand < getGreatPeopleSpecialistProgress((SpecialistTypes)iI))
			{
				eGreatPeopleSpecialist = ((SpecialistTypes)iI);
				break;
			}
			else
			{
				iGreatPeopleSpecialistRand -= getGreatPeopleSpecialistProgress((SpecialistTypes)iI);
			}
		}

		if (eGreatPeopleSpecialist != NO_SPECIALIST)
		{
			changeGreatPeopleProgress(-(GET_PLAYER(getOwnerINLINE()).greatPeopleThreshold(false)));

			for (int iI = 0; iI < GC.getNumSpecialistInfos(); iI++)
			{
				setGreatPeopleSpecialistProgress(((SpecialistTypes)iI), 0);
			}
			int iUnitClass = GC.getSpecialistInfo(eGreatPeopleSpecialist).getGreatPeopleUnitClass();
			if (iUnitClass != NO_UNITCLASS)
			{
				UnitTypes eGreatPeopleUnit = ((UnitTypes)(GC.getCivilizationInfo(GET_PLAYER(getOwner()).getCivilizationType()).getCivilizationUnits(iUnitClass)));

				if (eGreatPeopleUnit != NO_UNIT)
				{
					createGreatPeople(eGreatPeopleUnit, true, false);
				}
			}
		}
	}
}

CvGameCoreDLL.vcproj

This file contains err I guess you could call it service code, not gameplay code. I'm even less sure here. Is it ok to just copy & paste these changes into the Planetfall file?

CvInfos.cpp - difference 3 of 66

3.17 removes some code here. Planetfall added lots of code right above. Does the new Planetfall code require the removed 313 code in some way? Or can the 313 code safely be removed?

Spoiler :
Code removed in 317

Code:
// replacement for strdup
char* copyString(const char* szString)
{
	if (!szString)
		return NULL;
	char* pBuf = new char[strlen(szString)+1];
	strcpy(pBuf, szString);
	return pBuf;
}

wchar* copyString(const wchar* szString)
{
	if (!szString)
		return NULL;
	wchar* pBuf = new wchar[wcslen(szString)+1];
	wcscpy(pBuf, szString);
	return pBuf;
}

Code added by Planetfall

Code:
////////////////////////////
//borrowed code for planetfall
////////////////////////////

int __fastcall StrToNum(const TCHAR *udata, int udatalen, int base)
{
	long index;
	const TCHAR numdigits[] = TEXT("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
	long digitValue = 0;
	long RetVal = 0;
	TCHAR digits[sizeof(numdigits)+1];
	TCHAR *dataVal;
	TCHAR data[512] ;
	//copy the data to our variable
	_tcscpy(data, udata);
	//convert it to upper case
	_tcsupr(data);
	ZeroMemory(digits, sizeof(digits));
	//copy the number of digits supported by base in digits
	_tcsncpy(digits, numdigits, base);
	for(index = 0; index < udatalen; index++)
	{
		//is the number there
		dataVal = _tcschr(digits, data[index] );
		if(dataVal != 0 )
		{
			//if it is subtract where to start point
			digitValue = long(dataVal - digits);
			//increment Retval with digitvalue
			RetVal = RetVal * base + digitValue;
		}
	}
	//return the result
	return RetVal;
}

TCHAR* __fastcall NumToStr(TCHAR *RetData, long number, int base)
{
	long index = 0;
	const TCHAR numdigits[] = TEXT("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
	long digitValue = 0;
	TCHAR digits[sizeof(numdigits) + 1];
	TCHAR RetVal[512];
	TCHAR CurVal = 0;
	ZeroMemory(RetVal, sizeof(RetVal));
	// only base supported are from 2 to 36
	if(base < 2 || base > 36 ) return NULL;
	ZeroMemory(digits, sizeof(digits));
	_tcsncpy(digits, numdigits, base);
	while(number)
	{
		digitValue = number % base;
		number = number / base;
		RetVal[index++] = digits[digitValue];
	}
	//since string we have got is in reversed format
	//eg 100 will be 001 so we have to reverse it
	//and put the value in our variable
	ZeroMemory(RetData, _tcslen(RetVal)+1);
	int i = 0;
	for(index = _tcslen(RetVal) - 1; index > -1; index--)
	{
		//start reversing
		RetData[i++] = RetVal[index];
	}
	//return the result
	return RetData;
}

////////////////////////////
//end borrowed code for planetfall
////////////////////////////

////////////////////////////
//added for planetfall
////////////////////////////
TCHAR* CombineTCHAR(TCHAR* szVal, const TCHAR* String1, const TCHAR* String2)
{
	int TotalLength;
	int LengthString1;
	int j = 0;

	TotalLength = _tcslen(String1) + _tcslen(String2) + 1;
	LengthString1 = _tcslen(String1);
	ZeroMemory(szVal, TotalLength + 1);
	for (j = 0; j < TotalLength; j++)
	{
		if (j < LengthString1)
		{
			szVal[j] = String1[j];
		}
		if (j >= LengthString1 + 1)
		{
			szVal[j] = String2[j - LengthString1 - 1];
		}
	}
	szVal[LengthString1] = '/';
	return szVal;
}
////////////////////////////
//end added for planetfall
////////////////////////////

CvInfos.cpp - difference 10-14 of 66

Many const's were rewritten in patch 317. Should same be done to the two const's added by Planetfall?

Spoiler :
Example of 313 code

Code:
const TCHAR* CvInfoBase::getType() const
{
	return m_szType;
}

const char* CvInfoBase::getXmlVal() const
{
	return m_szXmlVal;
}

const TCHAR* CvInfoBase::getButton() const
{
	return m_szButton;
}

const TCHAR* CvInfoBase::getTextKey() const
{
	return m_szTextKey;
}

const wchar* CvInfoBase::getTextKeyWide() const
{
	if(m_szCachedTextKey == NULL)
		m_szCachedTextKey = copyString(CvWString(m_szTextKey).GetCString());

	return m_szCachedTextKey;
}

317 code

Code:
const TCHAR* CvInfoBase::getType() const
{
	if (m_szType.empty())
	{
		return NULL;
	}

	return m_szType;
}

const TCHAR* CvInfoBase::getButton() const
{
	if (m_szButton.empty())
	{
		return NULL;
	}

	return m_szButton;
}

const wchar* CvInfoBase::getTextKeyWide() const
{
	return m_szTextKey;
}

Planetfall added these:

Code:
const TCHAR* CvInfoBase::getCivilopediaKey() const
{
	return m_szCivilopediaKey;
}

const TCHAR* CvInfoBase::getStrategyKey() const
{
	return m_szStrategyKey;
}

Should these be rewritten to this or something? :confused:

Code:
const TCHAR* CvInfoBase::getCivilopediaKey() const
{
	if (m_szCivilopediaKey.empty())
	{
		return NULL;
	}

	return m_szCivilopediaKey;
}

const TCHAR* CvInfoBase::getStrategyKey() const
{
	if (m_szStrategyKey.empty())
	{
		return NULL;
	}

	return m_szStrategyKey;
}



Here are the SDK files, in the Plf317SDK.zip. I haven't committed them to the SVN, because I figured it might be best to wait until the cause of the current SDK problem was found. However now Cadavares has determined it must be something post revision 627, I guess I could commit them.(?) Since changes after 627 are minor.

Edit: I also included a FourProblemFiles.zip archive. It contains the four problem files of the unmodded 313 SDK, unmodded 317 SDK, Planetfall 313 SDK and partially completed 317 SDK.
 
Well I think a good strategy could be to work over the 627 version and then test the rest of the versions one by one. I am leaving on holidays, though, and I'll be back after the first week of july. I can give a hand after that moment.
 
Have a nice vacation.

Except for the mentioned conficts between Planetfall and 317, all files have been succesfully merged and attached here.
 
So, is the main mod file (the Beta, as I assume it's still a Beta) converted yet then?
 
really none willing to compile the sdk ?
 
Status
Not open for further replies.
Back
Top Bottom