Jump to content

Scout / Editor Framework 2010 (Make your own FMScout / FMEditor)


DrBernhard

Recommended Posts

Ok. Got the caching working alot more, it's truly gonna secure Genie like speed from the memory; yet buggy.

Anyhow, if you want to do some scout tool atm, you should instantiate the FMContext using DatabaseModeEnum.Cached, that should give higher loading, but shorter query time. It's quite useful already, yet not on large games.

Link to post
Share on other sites

  • Replies 134
  • Created
  • Last Reply
News for activeplayerobject? i try to modify the dll file with a disassembler but i have some problems with it. have u any advice to complete that function?

Why disassemble and modify the dll file when the source code is free and open??

Link to post
Share on other sites

Sorry havent had time to check the ActivePlayer object. Not home this weekend. Anyhow, anyone who wants to find this:

- Navigate to a player in FM

- Search him in the framework and note the memoryAddress field somewhere down

- Do an ArtMonkey search for this address somewhere around the current ActiveObject memoryoffset in MemoryOffsets.cs

This should get anyone the new offset quite fast.

Link to post
Share on other sites

I have a couple questions I hope someone can help me with ...

I'm a Mac programmer, and have successfully managed to attach a barebones application to the FM process and access it's memory. So far I have been able to read each VM region and determine it's address, it's size and whether or not it's accessible, readable and/or writeable. This is now making me think that creating something similar to this framework for the Mac is possible, which in turn will lead to the creation of real-time editors for the Mac, something we've not had before.

However, I am struggling to understand the offsets that are in this framework. I have downloaded the source hoping to gain a better understanding but so far I've failed. Partly because I have no knowledge of C# and the .Net frameworks, and partly because of the modular nature of this code which makes it difficult for someone not familar with the code to follow.

So if someone could take the time to answer the following questions it would be most appreciated ...

  • Am I right in thinking that objects appear in a strict order in memory, and that in order to find the offset of one particular object, every preceding object must be navigated first ?
  • If so, what is the order of the objects in memory and what is the offset of the very first object in the VM ?
  • Also, how do you determine when one object group ends and another starts (for example, if clubs precede players, how do you determine that the last club has been found and that the next byte in memory points to a player structure) ?

-Mic

Link to post
Share on other sites

How difficult would it be to make an Editor that simply allowed you to create a nation (like you can in the actual game editor with a club)??

That i could then load up via the actual game editor to create nation rules for etc etc

I've not touched VB.net in close to 18 months now but would get it reinstalled if this was a feasible project.

Link to post
Share on other sites

So if someone could take the time to answer the following questions it would be most appreciated ...

  • Am I right in thinking that objects appear in a strict order in memory, and that in order to find the offset of one particular object, every preceding object must be navigated first ?
  • If so, what is the order of the objects in memory and what is the offset of the very first object in the VM ?
  • Also, how do you determine when one object group ends and another starts (for example, if clubs precede players, how do you determine that the last club has been found and that the next byte in memory points to a player structure) ?

This is how it works: Every objecttype (each of the instances of BaseObject.cs, like Player, Club, etc.) are stored in an in-memory array. The location of the list inmemory are in the MemoryAddresses.cs, this is the baselocation of the process + the value inthere + the gameversion depended versionoffset in ProcessManager.VersionOffset.

When we know the base memoryaddress, we can now call 'ObjectManager.RetrieveObjects'. We now determine a couple of variables by reading parts of the memory based on the found baseAddress. This is quite clear in the code, so you'd be able to get that working.

The address then retrieved is the location of the array, and the number of items which are in there. You can now iterate like `for(int i = memoryAddress; i < memoryAddress + (numberOfItems*4); i += 4)`, as each item is referenced by 4 bytes. Then do a ProcessManager.ReadInt32 for each value of i. This is the memoryAddress of your object. When you want to get a property, check the Club.cs class for example, check the property you want to read (f.e. Reputation), then do `memoryAddress + offset` and read a number of bytes based on the type (Int32 = 4 bytes, short = 2 bytes, etc.) and you have the value.

How difficult would it be to make an Editor that simply allowed you to create a nation (like you can in the actual game editor with a club)??

That i could then load up via the actual game editor to create nation rules for etc etc

I've not touched VB.net in close to 18 months now but would get it reinstalled if this was a feasible project.

This isn't at this point, and isn't going to be possible. Adding objects is not supported due to the way memory is allocated in the original FM process.

Link to post
Share on other sites

This is how it works: Every objecttype (each of the instances of BaseObject.cs, like Player, Club, etc.) are stored in an in-memory array. The location of the list inmemory are in the MemoryAddresses.cs, this is the baselocation of the process + the value inthere + the gameversion depended versionoffset in ProcessManager.VersionOffset.

When we know the base memoryaddress, we can now call 'ObjectManager.RetrieveObjects'. We now determine a couple of variables by reading parts of the memory based on the found baseAddress. This is quite clear in the code, so you'd be able to get that working.

The address then retrieved is the location of the array, and the number of items which are in there. You can now iterate like `for(int i = memoryAddress; i < memoryAddress + (numberOfItems*4); i += 4)`, as each item is referenced by 4 bytes. Then do a ProcessManager.ReadInt32 for each value of i. This is the memoryAddress of your object. When you want to get a property, check the Club.cs class for example, check the property you want to read (f.e. Reputation), then do `memoryAddress + offset` and read a number of bytes based on the type (Int32 = 4 bytes, short = 2 bytes, etc.) and you have the value.

Dr Bernhard,

Firstly thanks for responding, it's appreciated.

However, I'm still struggling to understand some of this :thdn:

I get the first part. The address of the array that holds the addresses to all the appropriate objects is found by adding the VM address + the object offset + the version offset. So if for example I wanted to find the person array for 10.1 and the VM address started at 0x0 the calculation would be 0x0 + 0x215e080 + 0x2E1A8.

But this is where I struggle to follow what happens next, and I think this is because I really can't follow the C# code in the repository.

Does the address from the above calculation point to the actual array, or to a simple structure holding the number of elements in the array and then the address of the array ? If it's the latter, do I then just need to read 8 bytes from this intial address, 4 for the number of elements, 4 for the address of the actual array ?

Also, if this is correct, do I then just need to iterate through the elements of the array using the address of the array from above, each of which will inturn be an address, pointing to an object of the relevant class ?

I hope you can follow this.

Thanks

-Mic

Link to post
Share on other sites

Also, how are strings managed in memory ?

I know from working with the save game format that strings are variable length and are stored with a preceeding integer denoting the length of the string that follows it. Is it a similar situation here ?

Thanks

-Mic

Link to post
Share on other sites

This is how it works: Every objecttype (each of the instances of BaseObject.cs, like Player, Club, etc.) are stored in an in-memory array. The location of the list inmemory are in the MemoryAddresses.cs, this is the baselocation of the process + the value inthere + the gameversion depended versionoffset in ProcessManager.VersionOffset.

When we know the base memoryaddress, we can now call 'ObjectManager.RetrieveObjects'. We now determine a couple of variables by reading parts of the memory based on the found baseAddress. This is quite clear in the code, so you'd be able to get that working.

The address then retrieved is the location of the array, and the number of items which are in there. You can now iterate like `for(int i = memoryAddress; i < memoryAddress + (numberOfItems*4); i += 4)`, as each item is referenced by 4 bytes. Then do a ProcessManager.ReadInt32 for each value of i. This is the memoryAddress of your object. When you want to get a property, check the Club.cs class for example, check the property you want to read (f.e. Reputation), then do `memoryAddress + offset` and read a number of bytes based on the type (Int32 = 4 bytes, short = 2 bytes, etc.) and you have the value.

This isn't at this point, and isn't going to be possible. Adding objects is not supported due to the way memory is allocated in the original FM process.

@DrBernhard & Thanoulas: It seems both of you are very busy these days but still care about this thread. It's very kind. Anyway, is there something new for two bugs I fired on 6-Nov about staff enumerate and editing player attrs.

Tks and nice weekend both of you.

Link to post
Share on other sites

Hehe, i downloaded it yesterday, fixed contracts and activeobjects, an issue with age (for staff i think) and nationality, but you fixed it first. Will check new version now... cheers

P.S. Did a small checkin myself, added:

- staff nationality and age

- hack to check if fm is running but game has not been loaded

- extra functionality in game loading to separate checking the process and loading fm data

- GetCurrentFMVersion now returns a string indicating the fm version rather than the version offset

P.S.2. If there's a way to sync realtime and cached version please do. In realtime version objects not found are initialized with 0's while in cached remain null...

Problems: There a a few bugged players with age really small. Just check for it until its fixed...

Link to post
Share on other sites

I am not sure whether cocontract and loancontract work.

The contract address indicates the pointer to what seems to be a list, not to a contract while the next 4 bytes indicate the size of that list.

So the extra contracts are found by reading the value of the pointed contract address + 4 and i think the type of contract indicates if its loan or anything else...might be wrong though.

Link to post
Share on other sites

Off-topic, but I figure you guys might know. Is there information available on how to read the actual 2010 db files, as opposed to extracting data from memory? I'd love to be able to read the full db and do some things not currently possible with the official editor.

I remember there used to be a header file for some older version but I can't seem to be able to find one for the current version. Seeing as there are no known 3rd party pre-game editors this time around, I suspect the answer is no, but can't hurt to ask.

Link to post
Share on other sites

Here's my code !

Imports Young3.FMSearch.Interface
Imports Young3.FMSearch.Core.Entities.InGame
Imports Young3.FMSearch.Core.Managers
Imports Young3.FMSearch.Core.Offsets
Imports Young3.FMSearch.Utils

Imports System.Reflection


Public Class Form1
   Inherits Form

   Public fm As FMContext

   Public Sub New()
       InitializeComponent()
   End Sub

   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load


       fm = New FMContext()
       fm.LoadData()

   End Sub
End class

I've got error when loading. There is nothing loaded !

La séquence ne contient aucun élément.

What is wrong ?

PS : i'm with v10.1.1f897736 on dvd

Link to post
Share on other sites

problem with the fmcontext. when i loaded it sometimes i've seen that some player was missing. i use the FMcontext.players(n) array to have the player object. Try to reload but the problem persist. the one solution is to close the game and re-start.

problem with .contract property of oject type Player. outofmemory error when try to check.

PS.: for goldorakiller.. at the end "End sub" before "end class" :D

Link to post
Share on other sites

Can you eventually add IDs as a public property for all the entities that don't expose it yet, i.e. Stadium, City...?

meanwhile, how would I go about accessing them without modifying the framework? I assume I should be able to get them using the memory address property and the offsets, but I'm not sure how.

Link to post
Share on other sites

Hi,

I'm running Steam version (fully patched) using the offset finding the offset is 0x2A260 I'm happy to test and do whatever changes need to be done to get it working however I can't see what I need to change at the moment.

N.B. I'm only using Express Edition of Visual Studio

Many thanks

Link to post
Share on other sites

Immuner - thanks for the response, sorry for being a bit "thick" done VB programming in the past but haven't done anything for awhile.

In Visual C# 2008 Express I have my project with the FMSE2010 Core dll added and I can see under Young3.FMSearch.Core.Managers.ProcessManager VersionOffset and VersionShort but I can't see anyway of changing the value.

Link to post
Share on other sites

you cannot change the dll.

download tortoise svn, create a new folder, rught click and select svn checkout and then type http://scoutframeworkfm2009.googlecode.com/svn/trunk/.

This will download you the source files which you can edit and play with.

However you cannot upload your changes. But you can see if it works, so you can post back here and I will check in the changes for you.

Link to post
Share on other sites

Hi Immuner, cheers for all your help.

I used the offset tool that was downloaded to double check I had the right offset so have done these changes:

To:

public static int VersionOffset

if (FmVersion == "10.1.1f89736") return 0x2D188; //Steam 10.1.1

public static string VersionShort

if (FmVersion == "10.1.1f89736") return "10.1.1 Steam"; //Steam 10.1.1

public static int StaffVersionOffset

if (FmVersion == "10.1.1f89736") return 0x20D0; //Steam 10.1.1

However I'm trying to run the tutorial example from http://www.100procentjan.nl/fm2009/tutorial.htm however despite no errors no players are returned to the list box.

Any ideas?

Link to post
Share on other sites

If this helps these are the offsets:

FM Version 10.1.1f89736

Found game in memory (10 ms)

Game offset found: 0x2D188 (1678 ms

Staff offsets

0x1C5B08C: 8080

0x1C15044: 282

0x1C14CA4: 8794

0x1C2ADE4: 16183

0x1C26E34: 19196

0x1C7D46C: 59

0x1C2F35C: 2251

0x1C7C5AC: 352

0x1C7C964: 276

0x1C25DBC: 2

Found staff offset 0x20D0 (119 ms)

Link to post
Share on other sites

Are you sure the offset for steam is 1f89736? Because it seems it has the same offset with 10.1.1 DVD.

Since 10.1.1 DVD works you should not change that.

If steam 10.1.1 is indeed stored as 1f89736 then check to see if by default the players are loaded.

If by default this doesnt work, then there must be something else that identifies the 10.1.1 steam version compared to the DVD one.

Look at the GameManager.CheckProcessAndGame method for the checkNoPlayers region that i put there. Check the number of objects. If loaded correctly, it should return the total number of players.

Another way to find the offset, is to find the first pointer to the player list (you can use artmoney for that). Players are stored based on their ID. So you can look in artmoney for the memoryaddress that contains sequentially the first three-four players in the list.

But first try to load players and then try to find staff offset. Dont do them together you will get lost.

Link to post
Share on other sites

Ok Cheers - yes I'm sure that is correct - the info is copied and pasted from the offset finder - I noticed that 1f89736 was the same as the DVD version as well - sorry should have mentioned that.

It's strange as it does seem to be going through the database i.e. the list box gets a scroll bar like there are records but all the records have no information.

I'll have a further play and keep you posted on what I find.

Link to post
Share on other sites

Do not debug through the listbox.

Step through the framework code, from the point it checks the process.

Find the number of players it calculates and then step through that to figure out why players are not extracted correctly.

It can be that the number of objects you are getting is a random number in memory.

Since the player objects are just memory blocks, if they dont point to the correct pointer it's just random blocks of data.

Link to post
Share on other sites

I'm following the tutorial from the OP. whenever I try to list the players in the listbox, I get an error "The given key was not present in the dictionary." I'm running 10.1.1

Here's what the Offset Finder Says:

FM Version 10.1.1f89736

Found game in memory (9 ms)

Game offset found: 0x2E1A8 (1192 ms)

Staff offsets

0x1C26E04: 1

0x1C5C0D4: 1011

0x1C27E7C: 1902

0x1C15CEC: 5489

0x1C1608C: 20

0x1C7D5F4: 238

0x1C303A4: 672

0x1C7D9AC: 209

0x0: 838

0x1C7E4B4: 34

Found staff offset 0x20A8 (65 ms)

What's the problem? I note these offsets are different to the ones posted above.

Link to post
Share on other sites

Yes you can.

It seems they have changed the way some things are stored in memory.

I (think) the offset for 10.2 is 0x42028 but i am not sure.

I had to replace the following code in GetMemoryAddresses in ObjectManager.cs:

if (memoryAttribute.BytesToSkip > 0)

memoryAddress = ProcessManager.ReadInt32(memoryAddress + memoryAttribute.BytesToSkip); // bytes to skip is 24

memoryAddress += 4;

to

if (memoryAttribute.BytesToSkip > 0)

memoryAddress = ProcessManager.ReadInt32(memoryAddress + 40);

in order to get the same number of objects as in previous versions.

However, i have been trying and not been able to get staffoffset working properly.

One way to go is to find the first player-staff-whatever that is stored in a saved game of yours on a working version (10.1.1).

This has ID 1.

Then you need to play with a tool like ArtMoney in order to find the correct offsets.

If you can help in any way let me know. I had only a couple of hours free today so what i got is the following (could be TOTALLY wrong)

version offset 0x42028

staff offset -0x8198 (this is 99% way off)

address offset (the 252 you see in GetPersonMemoryAddresses in ObjectManager.cs) is now 284.

That seems to work to give me the staff but not properly (their names mostly...so i guess the offsets are wrong).

I cant get the players or anything else at all though.

Id suggest you should start from the beginning...

Link to post
Share on other sites

I ran the offset finder after making the changes to ObjectManager.cs that you suggested. I got a game offset of 0x1A6CDA

It crashed when trying to find the staff offsets on the line int lowestPointer = MemoryAddresses.Min();

It said the sequence contained no elements. I'm not a C# expert so I don't really know what to do with that. I'll try your other suggestions now.

Link to post
Share on other sites

When using your offsets for version and staff I still can't find anything, get this "given key not present in dictionary error". Does this error mean that the offsets are not correct? If not, could you send me/link to a download of whatever you're using to find the staff, so I nkow I've got a correct base to work from?

Link to post
Share on other sites

guys, anyone who can help, download the source code, have a look at how the game is loaded and how the code is structured for loading players/staff, etc and see whats different between fm versions.

The offset finder doesnt work for 10.2, so we follow another root.

Link to post
Share on other sites

Archived

This topic is now archived and is closed to further replies.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...