Python Performance and Interface Overhaul (PPIO)

@Fermongu: Ok, I'll get that fixed.

@Thunderbrd: I was trying to add a python hotkey that would call CyGame().toggleDebugMode(), without having to have "chipotle" cheat level in the ini file.
Ctrl+Alt+Shift+D

But this only toggled debug mode halfway.
CvGame.cpp has two global variables called:
m_bDebugMode
m_bDebugModeCache​
Without "Chipotle", only m_bDebugMode is set to true.
With "Chipotle", both are set to true.

The problem is that the function CyGame().isDebugMode() returns m_bDebugModeCache as its answer.
Meaning no python debug functions will turn on by using CyGame().toggleDebugMode().

Let's look at the relevant bit of code that is prcessed in the dll when CyGame.toggleDebugMode is called:
Code:
void CvGame::updateDebugModeCache()
{
    if ((gDLL->getChtLvl() > 0) || (gDLL->GetWorldBuilderMode()))
    {
        m_bDebugModeCache = m_bDebugMode;
    }
    else
    {
        m_bDebugModeCache = false;
    }
}
I believe gDLL->getChtLvl() > 0 will never be True without "chipotle" set in the ini cheat setting.

I don't really see why debugMode cannot be turned on properly without the "chipotle" cheat active...
chipotle does a lot of other stuff that is quite irrelevant to the debug mode.

There's two way's to go about this
1. m_bDebugModeCache is only used by CyGame().isDebugMode(), why not let that python function return the value of m_bDebugMode instead?
2. Change CvGame::updateDebugModeCache() to simply be: "m_bDebugModeCache = m_bDebugMode;" with no if/else statements at all.

Method number 1 would have the least risk of unforeseen consequences as I know pretty well what python does with the result from CyGame().isDebugMode(), and the exe doesn't care what that python function return one bit.
Method number 2 is risky if the exe somehow is privy to, and uses the value stored in the dll variables m_bDebugModeCache and m_bDebugMode. It is hard to know what the exe code needs those values to be in relation to the "chipotle" cheat.
If the exe doesn't use the dll variable m_bDebugModeCache at all then the variable could be removed from the dll completely. (I have a feeling the exe does know and use that variable though)​

I could of course make the python debug mode 100% internal within python, so that neither dll nor exe would be aware that python code is running in debug mode, but this would require me to change all the python related debug mode code to the new system, which is a lot of work.
 
Last edited:
PPIO v0.5.9.6.7.3
SVN rev.10232
  • Fix - Clicking F1 within the domestic screen causing errors.
  • Convenience - Changed the name of the folder and file from CustomDomAdv to DomesticAdv within the UserSetting folder.
    • This means that the UserSettings files within the SVN build is no longer used by the game with PPIO, which simplifies the installation of this modmod.
    • If you want to keep your PPIO settings for the custom domestic screen, you will need to rename the "CustomDomAdv" folder, and file, to "DomesticAdv".
      • Only needed to be done once when transitioning from older version of modmod to this or newer version of modmod.
If you do a fresh reinstall of C2C and then immediately install PPIO before starting it for the first time (as in, before UserSettings get generated) this bug happens.
Making sure the SVN CustomDomAdv usersetting doesn't exist in your C2C mod folder is no longer important with this modmod.
However, the advice in the opening post regarding the usersetting folder for first time users of this modmod should still be followed.
 
Last edited:
@Fermongu: Ok, I'll get that fixed.

@Thunderbrd: I was trying to add a python hotkey that would call CyGame().toggleDebugMode(), without having to have "chipotle" cheat level in the ini file.
Ctrl+Alt+Shift+D

But this only toggled debug mode halfway.
CvGame.cpp has two global variables called:
m_bDebugMode
m_bDebugModeCache​
Without "Chipotle", only m_bDebugMode is set to true.
With "Chipotle", both are set to true.

The problem is that the function CyGame().isDebugMode() returns m_bDebugModeCache as its answer.
Meaning no python debug functions will turn on by using CyGame().toggleDebugMode().

Let's look at the relevant bit of code that is prcessed in the dll when CyGame.toggleDebugMode is called:
Code:
void CvGame::updateDebugModeCache()
{
    if ((gDLL->getChtLvl() > 0) || (gDLL->GetWorldBuilderMode()))
    {
        m_bDebugModeCache = m_bDebugMode;
    }
    else
    {
        m_bDebugModeCache = false;
    }
}
I believe gDLL->getChtLvl() > 0 will never be True without "chipotle" set in the ini cheat setting.

I don't really see why debugMode cannot be turned on properly without the "chipotle" cheat active...
chipotle does a lot of other stuff that is quite irrelevant to the debug mode.

There's two way's to go about this
1. m_bDebugModeCache is only used by CyGame().isDebugMode(), why not let that python function return the value of m_bDebugMode instead?
2. Change CvGame::updateDebugModeCache() to simply be: "m_bDebugModeCache = m_bDebugMode;" with no if/else statements at all.

Method number 1 would have the least risk of unforeseen consequences as I know pretty well what python does with the result from CyGame().isDebugMode(), and the exe doesn't care what that python function return one bit.
Method number 2 is risky if the exe somehow is privy to, and uses the value stored in the dll variables m_bDebugModeCache and m_bDebugMode. It is hard to know what the exe code needs those values to be in relation to the "chipotle" cheat.
If the exe doesn't use the dll variable m_bDebugModeCache at all then the variable could be removed from the dll completely. (I have a feeling the exe does know and use that variable though)​

I could of course make the python debug mode 100% internal within python, so that neither dll nor exe would be aware that python code is running in debug mode, but this would require me to change all the python related debug mode code to the new system, which is a lot of work.
Apparently the purpose of this bit of code is to ensure that debug mode cannot be considered ON in python without 'chipotle' being active or being in the controlled environment of Worldbuilder where it seems Python is assumed to require some of the debug powers. It's a safety control to say that python cannot use debug features if not in either state.

I'm not personally against being able to toggle that mode in-game, myself. But I cannot say why the original designers may have determined this to be a bad idea. I don't know if there's regions in the exe that would easily come crashing down with the destabilization of an in-process switch over to debug mode or not but I can easily imagine it being something they were addressing here. That said, with worldbuilder being an alternative way to 'turn on cheat mode'... that's probably not the issue so much as ensuring game security in a more neutral PVP multiplayer environment - to literally stop people from being able to cheat against one another. Or even just to eliminate the psychological compulsion to ruin a cheat free environment on the fly by making it impossible to do so (not that this stops a single player from using worldbuilder so kinda ineffective ultimately).

In a multiplayer environment, this switch, even if accidental, would mean an immediate OOS of course.

Ok, here's a question, if you aren't in Debug mode and you go into worldbuilder, does the process of entering worldbuilder find a statement that makes m_bDebugMode true and does leaving it make it false? What else toggles the value of m_bDebugMode? I wonder if a change to this statement might make it so that on a game without chipotle, once you go into worldbuilder, you will always be on debug mode for that game thereafter.

So this could be a way to conditionally make worldbuilder the activating force for debug mode - When worldbuilder is entered, m_bDebugMode may become true and will stay that way thereafter without ever toggling back to false, thus making it so that it is only ever considered on when worldbuilder is in effect. If we change this, which may be the whole point of this, we might have to somehow find a way to turn it off when leaving worldbuilder, which they might not have found a good way to do so used this method instead.
 
The only way to turn on the debug mode is by having the chipotle cheat code active which allows the player to open a terminal in-game where they can write in game.toggleDebugMode.
I want to make it possible to activate debug mode for python without the chipotle cheat code, so that python can run debug code without running its chipotle code.
So that python debug features can work even though the terminal and the cheat functions are unavailable.

Perhaps the exe runs the toggleDebugMode function within the dll when it opens the world builder, but if it does then I'm sure it runs the toggleDebugMode function again when you exit the worldbuilder, effectively setting both of the boolean variables I mentioned to "false". Or else the python debug features would get activated after a visit to the worldbuilder, which they don't.

Right now it is ridiculous that python code can call toggleDebugMode() in the dll, and when python code afterwards asks the dll isDebugMode() it will still get "False" as an answer.
The only thing that happens now when toggleDebugMode() is called without the chipotle code is that fog of war is removed, that's pretty much it.
I've looked at nearly all python code that uses the isDebugMode() dll call, and I'm confident that that python code won't break if it receives "True" from the isDebugMode() call without the chipotle code activated.
 
Last edited:
The only way to turn on the debug mode is by having the chipotle cheat code active which allows the player to open a terminal in-game where they can write in CyGame().toggleDebugMode().
I want to make it possible to activate debug mode for python without the chipotle cheat code, so that python can run debug code without running its chipotle code.
So that python debug features can work even though the terminal and the cheat functions are unavailable.

perhaps the exe runs the toggleDebugMode function within the dll when it opens the world builder, but I'm sure it runs the toggleDebugMode function again when you exit the worldbuilder.

Right now it is ridiculous that python code can call toggleDebugMode() in the dll, and when python code afterwards asks the dll isDebugMode() it will still get "False" as an answer.
The only thing that happens now when toggleDebugMode() is called without the chipotle code is that fog of war is removed, that's pretty much it.
I've looked at nearly all python code that uses the isDebugMode() dll call, and I'm confident that that python code won't break if it receives "True" from the isDebugMode() call without the chipotle code activated.
Well, it certainly would be an easy enough thing to adjust. I'll try to find some time either tomorrow or early this week to compile a new dll and we can test it out. I kinda agree with you but am cautious. I can't claim to fully understand original motivations in the setup as it is.
 
Well, it certainly would be an easy enough thing to adjust. I'll try to find some time either tomorrow or early this week to compile a new dll and we can test it out. I kinda agree with you but am cautious. I can't claim to fully understand original motivations in the setup as it is.
The least risky way would be to not make any changes to
bool CvGame::isDebugMode() const (because this one is used a lot internally in the dll), but to make a change only to what is returned by:
bool CyGame::isDebugMode() const

Would it be possible to change this:
Code:
bool CyGame::isDebugMode() const
{
    return m_pGame ? m_pGame->isDebugMode() : false;
}
To something like this:
Code:
bool CyGame::isDebugMode() const
{
    return m_pGame ? m_pGame->m_bDebugMode;
}

If it can't reference variables within m_pGame directly, then perhaps one would have to make an alternate function called:
bool CvGame::isDebugModePython() const
Which returns m_bDebugMode instead of m_bDebugModeCache that the original function return.

Python doesn't really need to know whether the dll is running debugMode, only if debugMode has been activated in any way.
m_bDebugMode is always true when m_bDebugModeCache is true, the opposite is not always the case.
m_bDebugModeCache is the one that decides if dll debug code is run or not.

Doing it like this would mean that using my hotkey without chipotle turns on a lighter python only version of debug mode than if chipotle was activated.
Using the hotkey with chipotle activated would turn on debug mode for dll and python code.
 
Last edited:
PPIO v0.5.9.6.7.4
SVN rev.10232
  • Fix - Relation lines in the relation tab of the foregin advisor did not update correctly when selecting the leaderheads.
  • Tweaked the interaction of the resource icons in the "active deal" columns of the resource tab of the foreign advisor screen.
    • Deal information added to the tooltip
    • Left click to cancel deal, with an "are you sure" popup.
    • Right click for bonus pedia page. (This one is not new in this update though)
PPIO v0.5.9.6.7.5
SVN rev.10232
  • Overhauled the info tab within the foregin advisor screen.
 
Code:
void CvGame::updateDebugModeCache()
{
   //if ((gDLL->getChtLvl() > 0) || (gDLL->GetWorldBuilderMode()))
   //{
       m_bDebugModeCache = m_bDebugMode;
   //}
   //else
   //{
   //   m_bDebugModeCache = false;
   //}
}
This is what makes sense to me to do here. I don't get why they isolated the caching on this in this manner - though we should watch out for issues that result.
 
This is what makes sense to me to do here. I don't get why they isolated the caching on this in this manner - though we should watch out for issues that result.
Ok, if it doesn't pan out then I can always design a python exclusive debug mode that does not involve the dll or exe in any way.

PPIO v0.5.9.6.8
SVN rev.10232
  • Overhauled the tech tab within the foregin advisor screen.
    • The entire foreign advisor screen is now overhauled.
  • Tweaked tooltip mechanics some more.
    • e.g. Plot help tooltip should no longer show in diplomacy screen.
 
ok did what u said, i think, in the Bug thread:

1. The words r waaaay to large, can just imagine what it would look like when a unit has like 20 different thing in the unit itself to help descrip itself and how many u can build area. . pic 1

2. Words again too large it would take up the whole top of the screen when u do multiple thing .. pic 2

3. pic 3, where r the buildable units and where is the man and woman to start with, ??

4. attached is the python err i am getting
 

Attachments

  • words.JPG
    words.JPG
    234.7 KB · Views: 85
  • words1.JPG
    words1.JPG
    256.1 KB · Views: 88
  • buildable.JPG
    buildable.JPG
    181.2 KB · Views: 62
  • PythonErr.zip
    PythonErr.zip
    478 bytes · Views: 42
That's the wrong font... Did you install linux libertine?
He has 1024x768 resolution or something similarly cramped.
Even on my 1280x1024 monitor I had downsacale font size size A LOT.

These are my font sizes:
Code:
{
                GFont .Size0_Normal    = GFont("Linux Libertine G","Regular",    13, GFlags(GFontFeature, GFC_FONT_ALPHA),                  0, GRectMargin(2));
                GFont .Size0_Bold    = GFont("Linux Libertine G","Semi Bold",13, GFlags(GFontFeature, GFC_FONT_ALPHA, GFC_FONT_BOLD),  0, GRectMargin(2));

                GFont .Size1_Normal    = GFont("Linux Libertine G","Regular",    14, GFlags(GFontFeature, GFC_FONT_ALPHA),                  0, GRectMargin(2));
                GFont .Size1_Bold    = GFont("Linux Libertine G","Semi Bold",14, GFlags(GFontFeature, GFC_FONT_ALPHA, GFC_FONT_BOLD),  0, GRectMargin(2));

                GFont .Size2_Normal    = GFont("Linux Libertine G","Regular",    15, GFlags(GFontFeature, GFC_FONT_ALPHA),                  0, GRectMargin(2));
                GFont .Size2_Bold    = GFont("Linux Libertine G","Semi Bold",15, GFlags(GFontFeature, GFC_FONT_ALPHA, GFC_FONT_BOLD),  0, GRectMargin(2));

                GFont .Size3_Normal    = GFont("Linux Libertine G","Regular",    16, GFlags(GFontFeature, GFC_FONT_ALPHA),                  0, GRectMargin(2));
                GFont .Size3_Bold    = GFont("Linux Libertine G","Semi Bold",16, GFlags(GFontFeature, GFC_FONT_ALPHA, GFC_FONT_BOLD),  0, GRectMargin(2));

                GFont .Size4_Normal    = GFont("Linux Libertine G","Regular",    17, GFlags(GFontFeature, GFC_FONT_ALPHA),                100, GRectMargin(2));
                GFont .Size4_Bold    = GFont("Linux Libertine G","Semi Bold",17, GFlags(GFontFeature, GFC_FONT_ALPHA, GFC_FONT_BOLD),200, GRectMargin(2));
}
It is in Caveman2Cosmos\Resource\Theme\C2CTheme_Common.thm (open it with Notepad)
 
That's the wrong font... Did you install linux libertine?
Did you copy everything from the modmod 7z into your C2C folder, and choose overwrite all when prompted?
Did you delete your UserSettings folder?
i guess i didnt, and i did figure out the buildable stuff . .i started the other game with the usesetting and now i re-started one and they are there . .

ok i dont like the new wonder/buildable etc area, liked it better when it was below the map area, kinda confusing . . and again the words r too BIG

He has 1024x768 resolution or something similarly cramped.
Even on my 1280x1024 monitor I had downsacale font size size A LOT.

It is in Caveman2Cosmos\Resource\Theme\C2CTheme_Common.thm (open it with Notepad)
Yes i only work with 1024X768

EDIT Plus i get this:

Traceback (most recent call last):
File "BugConfig", line 110, in unknown_endtag
File "BugConfig", line 334, in endChild
File "BugConfig", line 337, in end
File "BugConfig", line 318, in process
File "BugConfig", line 547, in handle
File "BugUtil", line 478, in callFunction
File "CvEnhancedTechConquestEventManager", line 14, in __init__
File "EnhancedTechConquest", line 39, in loadConfigurationData
File "e:/main/civilization4/warlords/assets/python/system\ConfigParser.py", line 520, in get
NoOptionError: No option 'check prereq' in section: 'Enhanced Tech Conquest'
Traceback (most recent call last):
File "BugEventManager", line 313, in _handleDefaultEvent
File "CvEnhancedTechConquestEventManager", line 22, in onWindowActivation
File "EnhancedTechConquest", line 39, in loadConfigurationData
File "e:/main/civilization4/warlords/assets/python/system\ConfigParser.py", line 520, in get
NoOptionError: No option 'check prereq' in section: 'Enhanced Tech Conquest'
 

Attachments

  • w.JPG
    w.JPG
    196.2 KB · Views: 80
i guess i didnt, and i did figure out the buildable stuff . .i started the other game with the usesetting and now i re-started one and they are there . .

ok i dont like the new wonder/buildable etc area, liked it better when it was below the map area, kinda confusing . . and again the words r too BIG

Yes i only work with 1024X768

EDIT Plus i get this:

Traceback (most recent call last):
File "BugConfig", line 110, in unknown_endtag
File "BugConfig", line 334, in endChild
File "BugConfig", line 337, in end
File "BugConfig", line 318, in process
File "BugConfig", line 547, in handle
File "BugUtil", line 478, in callFunction
File "CvEnhancedTechConquestEventManager", line 14, in __init__
File "EnhancedTechConquest", line 39, in loadConfigurationData
File "e:/main/civilization4/warlords/assets/python/system\ConfigParser.py", line 520, in get
NoOptionError: No option 'check prereq' in section: 'Enhanced Tech Conquest'
Traceback (most recent call last):
File "BugEventManager", line 313, in _handleDefaultEvent
File "CvEnhancedTechConquestEventManager", line 22, in onWindowActivation
File "EnhancedTechConquest", line 39, in loadConfigurationData
File "e:/main/civilization4/warlords/assets/python/system\ConfigParser.py", line 520, in get
NoOptionError: No option 'check prereq' in section: 'Enhanced Tech Conquest'
Did you replace this file: Caveman2Cosmos Config.ini ?
It is in Caveman2Cosmos directory in same place as readme or notes for breaking savegame.

Maybe those values for font size will be better?
Code:
{
                GFont .Size0_Normal    = GFont("Linux Libertine G","Regular",    13, GFlags(GFontFeature, GFC_FONT_ALPHA),                  0, GRectMargin(2));
                GFont .Size0_Bold    = GFont("Linux Libertine G","Semi Bold",13, GFlags(GFontFeature, GFC_FONT_ALPHA, GFC_FONT_BOLD),  0, GRectMargin(2));

                GFont .Size1_Normal    = GFont("Linux Libertine G","Regular",    14, GFlags(GFontFeature, GFC_FONT_ALPHA),                  0, GRectMargin(2));
                GFont .Size1_Bold    = GFont("Linux Libertine G","Semi Bold",14, GFlags(GFontFeature, GFC_FONT_ALPHA, GFC_FONT_BOLD),  0, GRectMargin(2));

                GFont .Size2_Normal    = GFont("Linux Libertine G","Regular",    14, GFlags(GFontFeature, GFC_FONT_ALPHA),                  0, GRectMargin(2));
                GFont .Size2_Bold    = GFont("Linux Libertine G","Semi Bold",14, GFlags(GFontFeature, GFC_FONT_ALPHA, GFC_FONT_BOLD),  0, GRectMargin(2));

                GFont .Size3_Normal    = GFont("Linux Libertine G","Regular",    15, GFlags(GFontFeature, GFC_FONT_ALPHA),                  0, GRectMargin(2));
                GFont .Size3_Bold    = GFont("Linux Libertine G","Semi Bold",15, GFlags(GFontFeature, GFC_FONT_ALPHA, GFC_FONT_BOLD),  0, GRectMargin(2));

                GFont .Size4_Normal    = GFont("Linux Libertine G","Regular",    15, GFlags(GFontFeature, GFC_FONT_ALPHA),                100, GRectMargin(2));
                GFont .Size4_Bold    = GFont("Linux Libertine G","Semi Bold",15, GFlags(GFontFeature, GFC_FONT_ALPHA, GFC_FONT_BOLD),200, GRectMargin(2));
}
Or didn't you try to scale down font size?
Even on my monitor (1280x1024) Interface Overhaul fonts are too big and I have to downscale them :p

As for separate window for units buildings and wonders it is extremely useful in later game:
You can disable hiding unconstructable buildings/unit options, and you can always see buildings/units that you can't build now - they are separated.
This is what you would see in Ancient era.

Spoiler :

Civ4BeyondSword 2018-11-06 21-37-55-51.jpg
Civ4BeyondSword 2018-11-06 21-37-45-38.jpg
Civ4BeyondSword 2018-11-06 21-37-49-53.jpg

 
ok re-tried and the second font u sent is better at 1024, but the bottom of the screen c is tooo large see pic .. .it will take i think alot for me to get used to this???

also i still get this:

Traceback (most recent call last):
File "BugConfig", line 110, in unknown_endtag
File "BugConfig", line 334, in endChild
File "BugConfig", line 337, in end
File "BugConfig", line 318, in process
File "BugConfig", line 547, in handle
File "BugUtil", line 478, in callFunction
File "CvEnhancedTechConquestEventManager", line 14, in __init__
File "EnhancedTechConquest", line 39, in loadConfigurationData
File "e:/main/civilization4/warlords/assets/python/system\ConfigParser.py", line 520, in get
NoOptionError: No option 'check prereq' in section: 'Enhanced Tech Conquest'
Traceback (most recent call last):
File "BugEventManager", line 313, in _handleDefaultEvent
File "CvEnhancedTechConquestEventManager", line 22, in onWindowActivation
File "EnhancedTechConquest", line 39, in loadConfigurationData
File "e:/main/civilization4/warlords/assets/python/system\ConfigParser.py", line 520, in get
NoOptionError: No option 'check prereq' in section: 'Enhanced Tech Conquest'
 

Attachments

  • 1.JPG
    1.JPG
    205.9 KB · Views: 54
Last edited:
ok re-tried and the second font u sent is better at 1024, but the bottom of the screen c is tooo large see pic .. .it will take i think alot for me to get used to this???
The unit action buttons can be made smaller in BUG options. The first or third tab within BUG options I think.
Yes i only work with 1024X768
I thought you had a full HD widescreen? I think you said that last time we talked about resolutions.
Do you play with the image stretched horizontally so that everything is wider than it's supposed to or do you play with a large black bar on the left and right of the screen?

Can you try a higher resolution? This modmod is specifically designed to make high resolution interface much better than what vanilla offered.

Don't forget to check the pedia now while you have my modmod installed.
Check foreign, finance, domestic and espionage adviser screens too for that matter.
 
ok re-tried and the second font u sent is better at 1024, but the bottom of the screen c is tooo large see pic .. .it will take i think alot for me to get used to this???
Go to bug options, here is button named "Action Icon Size" and select 33 or something slightly bigger - smaller ones should be best here.
 
also i still get this:

Traceback (most recent call last):
File "BugConfig", line 110, in unknown_endtag
File "BugConfig", line 334, in endChild
File "BugConfig", line 337, in end
File "BugConfig", line 318, in process
File "BugConfig", line 547, in handle
File "BugUtil", line 478, in callFunction
File "CvEnhancedTechConquestEventManager", line 14, in __init__
File "EnhancedTechConquest", line 39, in loadConfigurationData
File "e:/main/civilization4/warlords/assets/python/system\ConfigParser.py", line 520, in get
NoOptionError: No option 'check prereq' in section: 'Enhanced Tech Conquest'
Traceback (most recent call last):
File "BugEventManager", line 313, in _handleDefaultEvent
File "CvEnhancedTechConquestEventManager", line 22, in onWindowActivation
File "EnhancedTechConquest", line 39, in loadConfigurationData
File "e:/main/civilization4/warlords/assets/python/system\ConfigParser.py", line 520, in get
NoOptionError: No option 'check prereq' in section: 'Enhanced Tech Conquest'
You didn't install everything correctly then.

Overwrite your "Caveman2Cosmos Config.ini" (found in "Beyond the Sword\Mods\Caveman2Cosmos")

with the file inside the attached 7z archive.​
 

Attachments

You didn't install everything correctly then.

Overwrite your "Caveman2Cosmos Config.ini" (found in "Beyond the Sword\Mods\Caveman2Cosmos")

with the file inside the attached 7z archive.​
ok that solved that, now this:

pic 1 words, see pic . . still dont like the pop-when a new buildable unit is avail, cant it be like it used to?? also the line for techs from 3 to 2 to 1 is missing??

pic 2 the tech adviser is waaay too long now in unused space???
 

Attachments

  • words.JPG
    words.JPG
    264.4 KB · Views: 56
  • tec.JPG
    tec.JPG
    83.3 KB · Views: 57
Last edited:
Back
Top Bottom