Jump to content

ZT EMU API


Goosifer

Recommended Posts

Update to share what functions and classes @finnethen and I have worked out so far outside of the budget stuff. Finn has done a lot more than I have in this area while I'm focused on other bits of the API. I like to share this because I still think it would be cool to attract anyone else that might have experience with C++ RE and would like to help. Maybe a prospective programmer would also like to learn :) And who knows, maybe some people might find this interesting!

 

Note: I ripped the commentary from our project Discord. It's important to know that the original context behind how we talk about these functions is by denoting them with their address in virtual memory, so something like 0x00028F38 or something. All of the names given to functions or classes are what we have given these addresses as we slowly translate the game into an API.

 

  • ZTApp (class)
  • ZTAIMgr (class)
  • ZTWorldMgr (class)
  • ZTScenarioMgr (class)
  • ZTResearchMgr (class)
  • ZTMarketingMgr (class)
  • ZTGameMgr (class)
  • ZTHabitatMgr (class)
  • ZTMapView (class)
  • ZTAIMgr (class)
  • ZTMapView (class)
  • ZTMessageQueue (class)
  • UIButton (class)
  • UIText (class)
  • UIGraph (class)

 

Commentary by Finn regarding these classes: "There's this class called `BFRegistry` which essentially contains a mapping between class names as strings and some constructor functions. I need to do a proper write up of this but essentially when I was tracing how this worked through the code there were two groups of very similar code, one was for `ZTAIMgr`, `ZTHabitatMgr` etc and another was mostly `UIText`, `UIButton`, `UIGraph` but it also had `ZTMiniMap`, `ZTMessageQueue`, `ZTMapView`. `ZTMapView` and `ZTMiniMap` all seem obviously `UI` related so I assume `ZTMessageQueue` is too."

 

Functions within these classes:

 

Note: Just for readability, I 'redacted' (didn't know what other word to use lol) the assembly stuff in his commentary in square brackets. This isn't top secret stuff, it's mostly because it makes sense to us, but maybe not others:

 

  • ZTMarketingMgr::update() (function): Finn says "Looks like it does some kind of calculation to figure out what the marketing cost is and then calls [a function] with the result, which @goosifer previously identified as a function to subtract from the budget."
  • ZTApp::updategame() (function): Finn says "Managed to match up the ZTApp::updateGame in the beta to ZTCC. Each [constant variable in this function] represents a pointer to each class that is called as part of the core game update loop. For example [one of the constant variables] is `ZTResearchMgr`."

 

Other classes/functions we have sort of figured out:

 

  • GuestManager? (function): Not sure exactly what this does exactly but I traced the guest number counter to this function. It's the only function that uses the guest counter so I have to assume this is how guest names are assigned, plus a bunch of other guest-related functionality. It uses the _cdecl calling convention so it doesn't seem to be a part of a greater class, but I could  be wrong.
  • Cheat/Easter Egg (function): By looking for the function that calls the Jonathan Gilmour function, I found the one that calls all of  the other cheats in the game (at least ones that involve naming a guest something to get something cool in return). The coolest thing about this is it might show us how guests are getting named. The graph tree for this is massive btw.
  • AI Action Factory? (class): Finn says "This class contains two virtual methods (0x413a23, 0x413acd) that contain massive switch statements where each case initialises a different class. There's no overlap between the classes that the two functions can return, but all classes in both functions are 24 bytes. Only seems to be used when an AI actor is present on the map and the game is unpaused, which is what leads me to believe it's related to AI actions."
     

An assortment of other functions discovered by Finn and I that seem more utility in nature or are just older (everything above is new):

 

Note: if it sounds silly that our commentary speculates on the purpose behind a function despite the name sounding definitive, just remember that the names given to these functions are speculative until we can absolutely guarantee their purpose. Until we can test all of the functions in-game like I have extensively done the addToBudget, they will remain speculative:

 

  • jonathanGilmour() (function): In 2002, Jonathan Gilmour won the Ultimate  Zookeeper award from Microsoft. Blue Fang then decided to put him in the game as a tribute. Rename any male zookeeper 'Jonathan Gilmour' and you get $20,000. That triggers this function.
  • recalcBudget() (function): The idea that it's recalculating the budget is an educated guess, and honestly probably not an accurate name. More like an event listener? One of the things that I know this function is doing is taking action whenever the budget goes down to 0. It's a little more complicated than that though because the $10,000 you get when budget goes down lives somewhere else I believe.
  • main() (function): I think this might actually be the main message loop. It's looking likely that the game combined the message loop with the main loop. It makes sense since this isn't an input-heavy game and mostly relies on left clicking objects or menu presses.
  • jonathanGilmourCFGParse() (function): In order for the Gilmour cheat to work, you need a .cfg in the root Zoo Tycoon folder. I believe that this function parses that file.
  • addToBudget() (function): Adds funds to zoo budget. I have described this one to death in this thread lol.
  • subtractFromBudget() (function): Same as addToBudget but, well, the opposite actually.
  • logging() (function): Finn says "This function performs logging. I believe [parameters] 4, 5 and 6 are potential values for substituting into the log message via `sprintf`, but this doesn't seem to happen in ZTCC, only in the vanilla beta."
  •  

An important note is that we still have our work cut out for us in order to contextualize a lot of these classes found. Many of them have been mapped to virtual memory locations and that's why they're in this post, which means that as a result we laid the groundwork to get them into the API. I also say this because we still need to figure out what the methods/functions within the classes mentioned above actually do and potentially rewrite them to C++ so that they're usable.

  • Like 3
Link to comment
Share on other sites

  • 3 weeks later...
Khaydar

Interesting, would it be possible to combine those functions to get different results in mods? Something I wanted to make is custom endangered animals that give rewards when you breed them. This would require an event "breed", something to check for it, and activate that money donation message like when you breed pandas. As well as adding money to budget.

  • Like 1
Link to comment
Share on other sites

4 hours ago, Khaydar said:

Interesting, would it be possible to combine those functions to get different results in mods? Something I wanted to make is custom endangered animals that give rewards when you breed them. This would require an event "breed", something to check for it, and activate that money donation message like when you breed pandas. As well as adding money to budget.

Yeah this will be the eventual goal of the API. I've had a bit of trouble finding the event listeners but now that we have mappings for a lot of these classes, it's possible that this functionality exists in the ZTMessageQueue.

Because I started with the budget stuff, I've been focused a lot on ZTGameMgr lately. I'll be providing an update on this soon. Honestly I think with what I've found so far it might be possible to create our own 'pseudo' listeners. Something like:

 

if (NumGuests == 500 && NumTiredGuests < 50)
{

	ZooBudget += 5000;

}

 

Can technically be done right now.

  • Like 2
Link to comment
Share on other sites

I'll be super busy this coming week and maybe even the next one. I'll still be working on the API but there's not much I could share about what I'm doing since it's all utility for the API to work. I think I might share my source code soon and people who want to play with it can start doing so, though it's very much just a 'toy' at the moment. I won't consider the API interesting until I can find an object list in virtual memory, or rather a way to manipulate individual guest and animal attributes, among other things like events like Khaydar would like.

 

Before I release the code, I need to implement some basic features:

  • Mod loading. This will let people write their own extensions to the API so that they can create their own mods. Code has already been contributed by a college friend but I need to port it to C++ since he only knows C#.
  • Restructure the command console code. It's very messy right now.
  • Add 20 new commands to command console. It's no longer just a budget API.
  • Make sure my game loop function doesn't cause too many issues performance-wise. I haven't had many problems lately but then again I'm running a Radeon 6800 XT and Ryzen 7 5700X, so I can only hope my Windows XP virtual machine is actually reflective of what an older machine is capable of running. It's still just a temporary implementation until I can hook onto the real loop or message queue.

In addition to ZooBudget which has been explored to death in this entire thread, here are some new game resources that should be accessible soon in the API:

  • NumAnimals
  • NumGuests
  • NumExhibits
  • NetIncome
  • ZooValue
  • ZooRating
  • NumAngryGuests
  • NumTiredGuests
  • NumHungryGuests
  • NumThirstyGuests
  • NumGuestsNeedRestrm
  • NumGuestsInFilter
  • AdmissionsIncomeByMonth[12]
  • ConcessionsByMonth[12]
  • RecyclingBenefitByMonth[12]
  • IncomeExpenseTotalsByMonths[12]
  • ZooRatingOverTime[12]
  • ZooRatingByMonth[12]
  • AnimalPurchaseCostByMonth[12]
  • ConstructionCostByMonth[12]

For anyone who has been following the code talk, these are all part of the ZTGameMgr class, so it seems that the instantiated form of this class is where most of the save file game state is transferred to in virtual memory.

 

Something I found kind of cool is that the Zoo Status panel in the game only shows you the last four months-worth of budget information. With the API you will be able to see all 12 months in the console if you wanted to.

 

Thanks to @finnethen and @Gymnasiast for pooling their knowledge, we've been able to make quite a bit of progress reversing a few of areas of the game the past few weeks. Later this summer we're looking to add another to the project who has some malware analysis experience, so that will be fun. (This just means he chose reverse engineering as his career path)

 

I'll also see you guys in my [normal] project's thread soon. I've had to clear up some time to get that going again but my fennec fox is not abandoned lol.

🥷Ninja Edit 06/21/23: For anyone following: I renamed the project title from "Goosifer's ZT EMU" to what it says now. The project team has grown since I started this API and it's no longer just mine alone. :P I'll shout our newest members on the next update whenever that is.

  • Like 3
Link to comment
Share on other sites

Here's my last weekly update on this project until release day a few weeks from now (at most).

 

New additions to the team

 

Big welcome to the project to @Gymnasiast, Jay, and Dexter! Including @finnethen and myself, we are now a ragtag team of five :)

  • Jay's perspective as a programmer and as a longtime ZT1 modder has been absolutely invaluable, especially since most of us have only superficially played the game and have never modded for ZT1 before. Though he was willing to help us regardless as he does anyone, he was still receptive to being named part of the team. At this point our communication and note-trading has been near-daily so I think it would be weirder to say he wasn't! :)
  • @Gymnasiast is a long-time contributor and important voice to the development of OpenRCT2. We were able to connect a few weeks back after I let slip about this API on Reddit and we realized that we were working on similar projects. Recently he hacked the zoo files and released a 233x233 map. His RE experience has been incredibly helpful and I'm glad that we met!
  • Dexter is a fellow university student and happens to be my roommate. He's a computer information systems major with an interest in malware analysis as a career path. This means that he wants to reverse engineer malware to stop the bad guys. Our school requires both CINS and CS majors to learn a lot of this stuff to some degree, so his help will be great.

Our goal as a team is a bit ambitious and a multi-year commitment to make this work. We are all busy and have different levels of availability, so we'll see where we are a year or two from now and what our team composition looks like. In the present, I'm happy we have a strong inaugural group for this effort. I hope one day we are able to share what else we are working on but for now, the API will have to do.

 

API Release Window

 

An early version of the API is getting very close to release, likely some time in the first half of July, second half at the latest. I will release it with one or two proof-of-concept mods that utilize the API and some basic documentation. After that, we should start seeing a regular release schedule with additional support and new API features.

 

Features on release:

  • Lua scripting. Lua scripts will give modders the power of a programming language (this goes way past what modifying configuration files let you do). The  API is an interface layer that speaks to the game's compiled assembly code and the resources in virtual memory but I am coding it in C++. Lua is a third layer ontop of the API that will make this tool a lot more accessible to everyone. Trust me, anyone will be able to learn how to make cool ZT1 'hacks' in the future. ;)
  • Command Console. The command console will mostly be useful to the developer team, but it's there if you want to use it. It's useful if you want to make changes to the game dynamically or modify game elements without exiting the game. As my personal tribute to Jay and a big thanks for all of his help (and for putting up with me), you open this command console with CTRL + J.
  • New ZT1 file type. The API will read in .emu files within its own folder inside of the ZT1 root. This will hopefully keep things organized.
  • At least 25 game resources to play with at release. All of those are related to the zoo game state (average guest and animal needs, zoo stats like budget, rating, total number of guests, etc).
  • Source code. I said I'd share the source code on Github and I will. And I'm always happy to connect if you'd like to contribute to the project.

System Requirements

 

As long as you own a computer with at least Windows XP with the Microsoft Visual Studio C++ 2008 runtime and above, you should be fine. This API does require that you own ZTCC, or otherwise have both expansions installed*. *We'll need to confirm this second point.

 

I mentioned this before, but the first API release will very much be a toy in the sense that we don't yet have access to entity lists (individual animals, guests, etc), so what you can do with those 25 game resources I mentioned will take a lot of imagination. Our tools tell us that the game has around 8,880 functions in the game alone, so we have our work cut out for us before we can start introducing stuff with more substance that people can play with. Variables are easier to expose than functions though, so they will have to do for the short term.

 

See you guys again on release day some time in July :)

  • Like 1
  • Love 3
Link to comment
Share on other sites

Savannahjan

Sounds like a great team doing amazing things!  :clap:  It's strange to hear a reference to Windows XP after 20 years.  That was the program I was using on a work laptop when I first bought ZT for my then 9 year old.

  • Like 2
Link to comment
Share on other sites

Right? My first computer had Windows XP when I first played Zoo Tycoon 2 back in 2006--I still love that startup sound. Originally this API only worked on Windows 10 and 11 and I had the hardest time even getting it to work on Windows 8. Then Jay told me he still rocks a Windows XP computer so I had to figure something out 😂

  • Like 1
Link to comment
Share on other sites

Savannahjan

I sure wish I had one.  I would love to have that Compac XP Professional laptop, new in the box.  It was solid as a rock with a cooling fan that was like an AC.  I was working at a university in an office as the clerical assistant to 18 Chinese scientists; it was the best job I ever had.  The boss got me that laptop so I could work from home sometimes and when I left the department to work part time, he insisted on me keeping it. Best computer I've had over the last 20 years.

  • Like 1
Link to comment
Share on other sites

They were hardy little computers. I remember the public outrage when Vista came out and no one wanted to switch 😂 That sounded like such an important job!

 

I had to install a Windows XP virtual machine on my computer in order to make sure the API is behaving, so just know that there are ways to keep the Windows XP dream alive if you're ever keen on jumping on a time machine haha. It trips me out every time I use it.

  • Like 1
Link to comment
Share on other sites

  • 2 months later...

I'm rebooting this project. I got busy with school and research over the summer so needed a couple-months-long break. Here's a short video explaining what this project is:

 

 

I had to be quiet for my roommates but I might do more of these in the future. We shalll seeee.

  • Like 2
  • Love 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...