Jump to content

ZT EMU API


Goosifer

Recommended Posts

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

 

Scroll allllll the way down for a TLDR! I promise future updates will be muuuuch more less rambley. Writing techie stuff and getting to the point is hard you guys! I just wanted to get the nomenclature out of the way.

 

Hi all!  I heard that Zoo Tycoon 2 had a functioning API these days so I thought it would be fun to work on one for the original. An API stands for "Application Programming Interface", so if you can imagine, it would help modders access code that wasn't originally available to them and do cool things you can't do now. I will be using C++ to code my API, so apologies to anyone who enjoys Lua for the ZT2 API. It's also possible someone may be working on something similar, I don't know as I'm only active at Tek and recently the Zoo Tycoon Discord. I also need stuff on my portfolio for internships soon, so please don't be offended if I continue hacking away despite the hypothetical existence of another lol! I'm not very competitive, so I'm sure there's smarter people out there that can figure this out faster than I can.

 

Who is Goosifer?  That's my handle elsewhere on the 'net. Just trying to be consistent! Sometimes the number of 'o's increase depending on if my username was available...I thought I was being clever but I guess others also liked the name. Haha, it's all okay, but I will find them all one day and encourage them to strongly consider other options.

 

Tek Toolkit?  If this gets anywhere, I only plan on releasing it here, my Github, and Nexus Mods. Makes it easy to support. ☺️ Also, Tek Toolkit rolls off the tongue so nicely, and I've always liked you guys.  Has been renamed "ZT EMU (Extensible Modding Utility).

 

Okay here goes. I'll try to make this as accessible as I can because it won't be as exciting as seeing all of those awesome progress pictures all of you amazing artists share with us, but some might find it interesting!

 

Navigation:

 

- How does this work?

- Poking the memory

- Stretch goals

- TLDR

 

How does this work?:

 

I use a process debugger that lets me access system memory and binary instructions as they're fired off. If you've ever used an IDE debugger like Visual Studio Community, it's a similar idea to adding breakpoints to see where your code is breaking, except I'm doing it with code that is intentionally garbled and long-been compiled. The fun is finding out what this code does by seeing what I break when I poke and prod. If this sounds fun to you, you might be interested in looking up what assembly language/machine instructions are. I'll give a brief explanation in a minute.

 

Also, even though I do know assembly/machine language from courses at uni, I'm still no expert so we'll be learning together. So far I've only found functions for changing the zoo's budget and the zoo's rating--have not tried looking for more yet. More on that later. Here's what one looks like in the assembly code.

 

Original call to 'addToBudget' function:

mov eax,dword ptr ss:[esp+4]            
add ecx,8                               
push eax                                
call zoo.4B5F30                         

 

Breakdown:

  • addToBudget btw, is not the original name of the function, but is probably what I'll end up calling it for now since that's what it seems to be doing.
  • The above can be translated to this pretty much:
  • addToBudget(deposit);

     

The instructions 'inside' of the function:

fld st(0),dword ptr ss:[esp+4]          
fadd st(0),dword ptr ds:[ecx]           
fstp dword ptr ds:[ecx],st(0)           
ret 4                                  

 

Translation:

addToBudget(deposit) {
	budget = budget + deposit;
}

 

Breakdown:

  • Push the current budget into the starting position of the float register stack st(0) (a register is a temporary place in memory) (a stack is like PEZ candy, memory that gets pushed and popped)
  • Add the new money in the ecx register to st(0)
  • Store the final sum back in the ecx register
  • Return to function call

 

By the way: Assembly is a series of low-level hardware instructions that run at a very low level in your computer hardware. If you're familiar with C++ for example, it's what the code eventually compiles into so that your computer can make sense of it. Then, those assembly instructions translate to bits and bytes and all of those fun ones and zeroes you're familiar with. Assembly instructions are all different depending on your CPU architecture. For example, there are instruction sets for Intel x86 processors, ARM, M1, etc. Just when you think you might know one, another computer will be just slightly unfamiliar to warrant reading the manufacturer's manual. Intel's manual is a great resource if anyone wants to learn this stuff. It is incredibly boring, and the class I took for it was not fun, which is impossible to imagine because this is absolutely riveting stuff right?

 

Here's a diagram that shows how it goes from high level source code, to assembly, to machine language (I stole it from Florida):

 

Figure2.1-CompLang.gif

Source (University of Florida): https://www.cise.ufl.edu/~mssz/CompOrg/CDA-lang.html

 

Poking the Memory

 

Using the instructions above, I found the 'bucket' that stores admission fees. This gets updated every time guests come in and pay. I could be wrong, but I learned that the game seems to only admit 3 adults + 1 child at a time, and sometimes only half that. I don't know what the half means yet (does half a child come in?) but for example, if 3 adults + 1 child = $35, then sometimes this 'bucket' will say $17.50 in fees were paid out if only two guests enter instead. It's kind of funny, but not haha funny, you know?

 

The 'bucket' is 1 byte of code. As Zoo Tycoon is a 32-bit game as most games were back then, every row below represents 32 bits of data at each memory address. Actually, I've got my computer maths wrong here, it was late at the time sorry! The budget value is actually stored as a 32-bit floating point, which means every cell below is actually 4 bytes. Every address contains within it different values that track the game at a stepsize of 8 bits 4 bytes at a time, many of which I'm going to have fun discovering their significance. Notice the highlighted byte below? That's how much in admission fees was deposited into my zoo at that given moment.

 

hex.PNG.818cf30d674166711753a57df5b2f42c.PNG

 

Below is the memory address that stores the budget after my fees were added with a comparison shot.

 

zoo2.PNG.daabe4b079025e15425e16c825c92b5f.PNG

 

I paid myself $500,000 because $75,000 to run a zoo in 2023? Please, not in this economy.

 

zoo3.PNG.56e7f616bfc756837093f419cf76075e.PNG

 

There's other interesting quirks I've learned...for example, I have a test zoo with only one exhibit, no other buildings and only a short path that leads to the animals. It's quite sad, and honestly I should have been shut down by now but the game couldn't have predicted that a sophisticated gentlemen such as myself would artificially modify his Zoo Rating and his Budget with a process debugger, so they'll never take me down. What is confusing is that even when I remove the ability to accept any budget from this function, I still am getting income elsewhere. I'll post screenshots next time I'm ready to document this, but I'll be getting random contributions that range from $1-$5. They're not donations I think because the income chart in the game sometimes shows I have not earned any donations. I wonder if the game just helps you out a little bit by design be sneaking you in money? I'm still new to ZTCC so maybe it's just newbie pains and not understanding things.

 

zoo1.PNG.6f3c48816543cf6bdd88c80d30d4d0b0.PNG

 

Please pay no mind to Patricia near the bottom-left. We just let her do her thing.

 

Stretch Goals

 

Short term in order of priority:

  • Translate the first two functions I found into C++ (almost done!)
  • Create a .dll wrapper that will allow my API to hook onto the zoo.exe file when it runs
  • Test, test, test. Any volunteers? Highly recommend a virtual machine setup. I can show you how.
  • Start pushing code to Github and share repository with community
  • Discover more functions

 

Long term:

  • Figure out why there are ID limitations for some objects/buildings. Is there a way to expand capacity?
  • Create functionality in my dll that looks for a separate mod folder from the usual one in Zoo Tycoon. That way mods that use the API are separate.

 

I'll add more goals in the future but I like to keep it simple in the beginning with what I know I can do to start.

 

So what does this all mean? Well, the way an API is made from here is that as I figure out what does what, I make a source file in C++ that makes calls to these memory locations I mentioned above. I can make functions in C++ that make reference to the budget 'bucket' (or the memory address) so that other folks can then import my API as a library and make their own mods. For example--there's not much to my API yet outside of two functions, but maybe someone can make a statue that randomly grants you $100 given certain conditions, or a 'hack' that gives you a lot of money...things like that. This will be a long and arduous process because I'm a busy boi with plenty to do at university, so you can expect updates from me only when I meet stretch goals, remove stretch goals because they were too hard or unreachable, or discover new processes in the assembly that look interesting.

 

If you have knowledge to share or want to work on this with me, please reach out! I think that would be fun. You don't need to be a computer science student or a programmer, I could definitely use the help testing the toolkit before I release my sourcecode, which I will do when there is a good baseline to share. Maybe when I finish the first two functions.

 

TLDR

 

I'm making a ZTCC API, weee! API means more options for modders! Goosifer = me, Tek Toolkit  ZT EMU = name of tool. I'm a busy CS student, so I will share progress as I can! Please reach out if you want to know how you can help!

  • Love 2
Link to comment
Share on other sites

Vondell

Fascinating ... 👀

 

The backend of this game may as well be an alien world to me. Not even strictly sure where the boundaries of possibility lie with an approach like this.

Very curious to see where your exploring leads!

  • Like 1
Link to comment
Share on other sites

Thank you Fern!  Tell Jay I've been reading through his modding guides, they have been so helpful and were actually what tempted me to try this. Is he active here on Tek if I have a question?

Link to comment
Share on other sites

No. I am his go-between here. He is Admin at Zoo Keeper's Lounge which is still around. He is also Admin at the Download Directory and the Designer Guild. I keep him busy there. If you want to go direct you can contact him at DD. If you have problems joining let me know and you need to make two posts before you can use the pms there or get me to bypass that for you. The questions area might be useful or not.

His menu hack and purchasing young hack came about from finding how BF did their testing.

I have masses of random info lurking behind the scenes at both sites.

Link to comment
Share on other sites

I see, got it! Absolutely I'll be sending questions your way when I get stuck, and I don't doubt it would be sooner than later! I think after this weekend I'll have a little more time to *check out some of those resources and reach out.

 

Right now I'm mostly concerned with finding a good way to hook into the zoo.exe without hurting anything but my debugger is only letting me 'nop' out instructions (mute them if that makes sense?) instead of modifying them. If I can just remove the addToBudget function above and redirect it to another location, that would be the biggest first hurdle solved.

 

Looks like the zoo.exe has left a loooooot of room to add new code at the bottom (these are called code caves!).

 

itsfreerealestate.png.92a0db8189c427efcbd305b0ea6a6a3f.png

 

Look at all of that free real estate!

 

*Edit: Some of my message didn't send.

  • Like 1
Link to comment
Share on other sites

Is it just me or is the world spinning ? :bloos1:

I wish you goodluck with this all but most of all fun!

  • Like 2
  • Haha 1
Link to comment
Share on other sites

You’ll see the asterisk in my original response where I went back and made my my edit. It trailed off because I didn’t finish my thought the first time. lol

  • Haha 1
Link to comment
Share on other sites

Hello, new progress update!

 

I finally figured out how to always get the correct memory location of my target values. Sadly not much time to get into detail this time (midterms tomorrow!), but it's probably best for everyone's sanity. 😂 I am not kidding when I say I have been obsessing over this project, it's so much fun! Not great for my grades though...

 

Anyway, first two API functions complete: getBudgetValue(..) and setBudgetValue(..). They're pretty easy to understand.

 

Here's some screenshots (keep track of the budget!):

 

nzoo1.png.ec648f5ca5d79f10c393a45be6f0f08b.png

 

My API code that runs the mod:

 

// read the value and pointer to budget location
DWORD budgetPointer = getBudgetValue(ptr, 0x08, 4, bytes_read, budget);

// write new value to budget location
bool success = setBudgetValue(zooHandle, budgetPointer, floatToUint(100000.0), oldprotect, bytes_written);

// error handling
if (success == FALSE)
{
  std::cerr << "Failed to write process memory. Error code: " << GetLastError() << std::endl;

  return 1;
}
else
{
	std::cout << "SUCCESS: You have set the zoo's budget from " << uintToFloat(budget) << " to " << uintToFloat(newBudget) << "\n";
}

 

*beep boop, robot noises*

 

Success screenshot:

 

nzoo2.png.895806b1a3cd0e83d3391da010f9acd3.png

 

Zoo right after budget update:

 

nzoo3.png.076b7d39de7f328747a6f82c9bd767ab.png

 

I mentioned before that I haven't looked for other values yet, and that's because I want to make sure that I test everything out first and make sure I understand how APIs are made. Here is that list again:

 

Stretch Goals

 

Short term in order of priority:

  • Translate the first two functions I found into C++ (almost done!)
  • Create a .dll wrapper that will allow my API to hook onto the zoo.exe file when it runs
  • Test, test, test. Any volunteers? Highly recommend a virtual machine setup. I can show you how.
  • Start pushing code to Github and share repository with community
  • Discover more functions

 

Long term:

  • Figure out why there are ID limitations for some objects/buildings. Is there a way to expand capacity?
  • Create functionality in my dll that looks for a separate mod folder from the usual one in Zoo Tycoon. That way mods that use the API are separate.
     

Next goal is to find a way to hook a .dll wrapper that will let people use my API. Mods using my API would require running an exe otherwise, and I'd rather it just be a dll file to copy/paste. Maybe I'll make a few mods afterward as proof-of-concept, I got a few ideas!

 

Speaking of which, I think I accidentally found the bit of code responsible for automatically naming guests ("Guest 1, 2, 3, 4..."). I happen to use a library often that generates synthetic data for things like data sets (statistics and data science nerds love this stuff). I think it would be cool to use it to make random, original names for our guests. I'll see if I can probe the assembly code and figure it out! Actually, I think I’m the nerd…🤓

 

Question for you guys: what API calls would be interesting to probe for? In other words: I found the budget and made it modifiable (I reckon it already was though). Anyone have a wishlist?

 

Alright, bedtime. Considering my pace, see you guys in two weeks lol.

  • Love 1
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...