Page 1 of 1
Posted: 18 Feb 2010, 23:12
jigebren
This topic is following a disscussion in WolfR4 topic.

Cat was asking about including carfix (TMMCC) in WolfR4.

I though it was simple, and I was wrong. I look at at the code sources, and I think I have found the reason of the bug. If I'm not mistaken, it's clearly a bug/mistake from acclaim developers.
It's likely that they didn't expected in a fisrt time to support custom cars, and when they did it after, some old code just became wrong.


About the TMMCC fix, it is quite probably fixing this bug in a very rough/brutal way, by forcing revolt to believe that there is just a little number of cars. That's why I think that when you use this fix, some custom cars are never selected as your opponents (to be verified).
But unfortunately, there is probably no other way to do, without rewritting the whole function in code source (and that's a job for the RVDEV team, I just can't patch this).

Posted: 19 Feb 2010, 04:52
Adamodell
jigebren @ Feb 18 2010, 06:42 PM wrote: About the TMMCC fix, it is quite probably fixing this bug in a very rough/brutal way, by forcing revolt to believe that there is just a little number of cars. That's why I think that when you use this fix, some custom cars are never selected as your opponents (to be verified).
No need to verify, this is absolutely correct.

Posted: 19 Feb 2010, 08:03
jigebren
Well, maybe I can do something, in fact.
I'm trying to increase the size of the stack dedicated to the buggy function, which is used in this case as a local array, to prevent this array to overwrite other part of the stack. But I also have to modify accordingly the way each element of the array is accessed, and that's not easy, because it looks like the c++ compiler use some tricks to optimize code that make it difficult to understand in disassembly... And as usual, we're very limited by the available place to add new patched instructions.

Keep in mind that even if I achieve this, there will still be a car limit, but greater than now. And revolt will still crash when that value is reached...

Can you tell me what number of custom cars of the same category could be enough for a normal use of revolt, according to your opinion/practice. And please don't tell me 32000, try to find a reasonable value.
Thanks.
EDIT: Well, I can't do better than 127 cars of the same category (maybe 128 with a trick). Hope it will be enough. And even that, I still can't get it to work for now (modifying array accesses is quite tough).

Posted: 19 Feb 2010, 21:52
GWC
You could try contacting Antimorph, he may well be around (MM got in touch with him a few years ago). TMMC fix was part of a much larger project, named 'Reprter', that he was working on.

Posted: 19 Feb 2010, 22:22
jigebren
Thanks, GWC, but I think I achieved it finally. And in a better way than I was expecting in the beginning. Well, I can't hide I'm quite proud of this patch. ;)

If I'm not mistaken, the crash limit is on the number of cars per category, so with this new patch, we can have up to 128 cars in each category.
And moreover the game won't crash if you add more cars, they will just be ignored.
And each of these 128 cars can be selected by revolt as AI opponents. Not absolutely sure of it, but I think the TMMC fix just allows the very first cars in the list to be selected as AI opponents (see the post above, and Adamodell's answer).

I'm implementing this fix in WolfR4, of course.


EDIT: oh, and I'm curious, what was this larger project Antimorph was working on? Never heard of it.

Posted: 20 Feb 2010, 02:13
antimorph
jigebren @ Feb 19 2010, 05:52 PM wrote: And each of these 128 cars can be selected by revolt as AI opponents. Not absolutely sure of it, but I think the TMMC fix just allows the very first cars in the list to be selected as AI opponents (see the post above, and Adamodell's answer.

EDIT: oh, and I'm curious, what was this larger project Antimorph was working on? Never heard of it.
Hi. It was rough and brutal ! :D

TMMCC set up a number of timers, and polled particular memory offsets 10 times each second looking for an opportunity to do something that might have some kind of effect, you can see in this snippet why it might limit AI car selection to the first 60.

Code: Select all

	
	case ID_CLOCK_TIMER: // This is our 100 millisecond Timer
	
	if (ghandle != 0) //Revolt is running
	{
  if ((timename == "rontend") && (racetype == 2))    {

  	// We're on the frontend and not in multiplayer
  	//Set the carmax value, which we'll use to seed the race
  	
        //As others have noted, this would very likely 
        //limit the ai car selection to
  	//the first 60. 

  	if &#40;numcars < 60&#41; { 
     &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;carmax = numcars;
  	} else { 
     &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;carmax = 60;
  	}      	
  	
  	//87 is the letter W in FWD, 4WD, 2WD on car info screen
        // This occurs before car select and just as we will 'enter' to start the race
  	if &#40;&#40;GetByte&#40;ghandle, Titlepos&#41;&#41; != 87&#41;  
  	{
         //tick tock, set to 60 on every beat of the clock.
    
 &nbsp; &nbsp;PutShort&#40;ghandle, NumCars, carmax&#41;; 
    
    if&#40;!SuppressCheats&#41;{
    	
    	PutByte&#40;ghandle, Num_Opponents, 8&#41;; 
    	
    	PutByte&#40;ghandle, 0x0084D2FC, 0&#41;; //Suppress URCO
    	
    	PutByte&#40;ghandle, 0x0084D2F8, 0&#41;; //Suppress Changeling
    	
    	PutByte&#40;ghandle, 0x0084D2F4, 0&#41;; //Suppress Drinkme
    	
    	PutByte&#40;ghandle, 0x0084D2E8, 0&#41;; //Suppress Sadist
    	
    	PutByte&#40;ghandle, 0x0084D2F0, 1&#41;; //Enable TVTime
    	
    	SuppressCheats = 1;
    }
    
    DoNumCars = 0;
    DoOnceOnRaceStart = 0;
    
  	} else {

    // Use the real car number figure
    // When we are at the car select screen or are 
                                // not just about to start the race
    
    PutShort&#40;ghandle, NumCars, numcars&#41;; 
    
    SuppressCheats = 0;
    
  	}
  }
	}
The reporter part watched the memory locations that recorded lap times during a race. I'll paste up the memory locations shortly.

Posted: 20 Feb 2010, 02:29
antimorph
jigebren @ Feb 19 2010, 05:52 PM wrote: what was this larger project Antimorph was working on?
These days of course there may be more productive avenues to explore.

Code: Select all

#define Max_Laps 0x0084CD00
#define onlap_Driver1 0x007B772C
#define onlap_Driver2 0x007BB97C
#define onlap_Driver3 0x007BFBCC
#define onlap_Driver4 0x007C3E1C
#define onlap_Driver5 0x007C806C
#define onlap_Driver6 0x007CC2BC
#define onlap_Driver7 0x007D050C
#define onlap_Driver8 0x007D475C
#define onlap_Driver9 0x007D89AC
#define onlap_Driver10 0x007DCBFC
#define onlap_Driver11 0x007E0E4C
#define onlap_Driver12 0x007E509C

#define Last_Lap 0x007B7734
#define Best_Lap 0x007B7738

#define CARID 0x00774F5C
// #define InRace 0x007B7718 // byte
// #define InRace 0x007b7530 // car on its wheels
#define InRace 0x007B4476

#define Track_Dir 0x00782e38
#define Track_Name2 0x00782E48
#define ScanLocName 0x00782E49

#define Current_TrackZone 0x007BA998
#define Current_TrackPos 0x007BAA34

#define Num_Opponents 0x0084CD04
#define Handling_Mode 0x0048FECC
#define loc_racetype 0x0078a3c0

#define IsPickups 0x0084CD24
#define IsInstances 0x0084CD88
#define IsMirrored 0x0084CD20
#define IsReversed 0x0084CD1C

#define bestlap_Driver1 0x007b7738 //offset
#define bestlap_Driver2 0x007bb988	//
#define bestlap_Driver3 0x007bfbd8	//
#define bestlap_Driver4 0x007c3e28	//
#define bestlap_Driver5 0x007c8078	//
#define bestlap_Driver6 0x007cc2c8	//
#define bestlap_Driver7 0x007d0518	//4250
#define bestlap_Driver8 0x007d4768	//4250

#define lastlap_Driver1 0x007b7734 //offset
#define lastlap_Driver2 0x007bb984	//
#define lastlap_Driver3 0x007bfbd4	//
#define lastlap_Driver4 0x007c3e24	//
#define lastlap_Driver5 0x007c8074	//
#define lastlap_Driver6 0x007cc2c4	//
#define lastlap_Driver7 0x007d0514	//4250
#define lastlap_Driver8 0x007d4764	//4250

#define NumCars 0x004DBCB4

#define rr_pos1time 0x007b6858
#define rr_pos2time 0x007b6860
#define rr_pos3time 0x007b6868
#define rr_pos4time 0x007b6870
#define rr_pos5time 0x007b6878
#define rr_pos6time 0x007b6880
#define rr_pos7time 0x007b6888
#define rr_pos8time 0x007b6890

//Err.
#define rr_itsDriver1 8087888
#define rr_itsDriver2 8104864
#define rr_itsDriver3 8121840
#define rr_itsDriver4 8138816
#define rr_itsDriver5 8155792
#define rr_itsDriver6 8172768
#define rr_itsDriver7 8189744
#define rr_itsDriver8 8206720

//Maybe a way to set which car is chosen as the AI opponent
//I think these may offer a way to change which AI is chosen at the start.
#define AI1 0x00774f5c
#define AI2 0x00774fa0
#define AI3 0x00774fe4
#define AI4 0x00775028
#define AI5 0x0077506c
#define AI6 0x007750b0
#define AI7 0x007750f4
#define AI8 0x00775138
#define AI9 0x0077517c
#define AI10 0x007751c0
#define AI11 0x00775204
#define AI12 0x00775248

#define Position 0x007BAADC
#define andagain 0x004DBCB5 //position again? what?

#define CarSelectA 0x0078A3E8
#define CarSelectB 0x0084CD58

#define Titlepos 0x0078A987
#define Car_Select 0x0078A864
#define IsTrackOpen 0x01539E0B

#define Test 0x004CCFCE
#define Candidate 0x004CCF2C // Unhook
#define Unknown1a 0x004CCF8a // X positive X right ?
#define Unknown2a 0x004CCF8e // Y postive Y down ?
#define Unknown3a 0x004CCF92 // Z positive Z forward ?
#define Unknown4a 0x004CCFDA // Cam Field Of View
#define Unknown5a 0x004CCFC2 // Pitch
#define Unknown6a 0x004CCFBE // Left Right
#define Unknown7a 0x004CCFC6 // ?
#define Unknown8a 0x004CCFB2
#define Unknown8b 0x004CCFB3
#define Unknown9a 0x004CCFB6
#define Unknown9b 0x004CCFB7
#define Unknown10a 0x004CCFAE
#define Unknown10b 0x004CCFAF
#define Unknown11a 0x004CCFB2
#define Unknown11b 0x004CCFB3
#define Unknown12a 0x004CCFB6
#define Unknown12b 0x004CCFB7
#define rr_TrackName 0x00774F44

//These are display names
#define rr_Carname1 0x00774F74
#define rr_Carname2 0x00774FB8
#define rr_Carname3 0x00774FFC
#define rr_Carname4 0x00775040
#define rr_Carname5 0x00775084
#define rr_Carname6 0x007750C8
#define rr_Carname7 0x0077510C
#define rr_Carname8 0x00775140

//These seem to be stable
#define rr_DriverName1 0x00774F88
#define rr_DriverName2 0x00774FCC
#define rr_DriverName3 0x00775010
#define rr_DriverName4 0x00775054
#define rr_DriverName5 0x00775098
#define rr_DriverName6 0x007750DC
#define rr_DriverName7 0x00775120
#define rr_DriverName8 0x00775164

#define rr_pos1getDriver 0x007b685c
#define rr_pos2getDriver 0x007b6864
#define rr_pos3getDriver 0x007b686c
#define rr_pos4getDriver 0x007b6874
#define rr_pos5getDriver 0x007b687c
#define rr_pos6getDriver 0x007b6884
#define rr_pos7getDriver 0x007b688c
#define rr_pos8getDriver 0x007b6894

//display names during race &#40;maybe change these as the race starts&#41;
#define Car1Name 0x007bab74
#define Car2Name 0x007bedc4
#define Car3Name 0x007c3014
#define Car4Name 0x007c7264
#define Car5Name 0x007cb4b4
#define Car6Name 0x007cf704
#define Car7Name 0x007d3954
#define Car8Name 0x007d7ba4


Posted: 20 Feb 2010, 02:42
jigebren
Well, Antimorph, I salute you. I take your presence here as a great honor. ;)

I going to take a look at your snippets, maybe your project could have been something like the ancestor of WolfR4...

Posted: 20 Feb 2010, 20:58
jigebren
Antimorph, looking at your method, there is one thing I'm wondering about: why did you choose the 60 value? Was it empirical? I thought the problematic limit was more something like 35...

Posted: 20 Feb 2010, 21:21
antimorph
No, not empirical, 60 was just the first shot in the dark that worked for me.

I think that I read in one of your other posts that the carbug is infact related to the numbers of each car type and not simply the total number (which is what I think I had assumed), that makes a lot of sense of the varying success that different people had with TMMCC.

What technique did you use to increase the limit to 128? I'm certainly interested.

/Steve

Posted: 21 Feb 2010, 01:17
jigebren
antimorph @ Feb 20 2010, 04:51 PM wrote:No, not empirical, 60 was just the first shot in the dark that worked for me.
Isn't it the definition of empirical, precisely? ;)

And I still don't understand why this value of 60 fixes the problem. But, it doesn't really matter, as my method is not the same, it's just that I'm curious to know the reason.

anitmorph wrote:What technique did you use to increase the limit to 128? I'm certainly interested.
A combination of disassembly and the studying of the available source code. I had no real knowledges in ASM or C++ before I started this project (well, it's unfortunately still quite the case, unlike what some can imagine), but it makes me discover a lot of new things...

Posted: 21 Feb 2010, 02:00
antimorph
Ha!, well it was really the first value I tried. I undertook no work to probe the boundaries of that value.

The default value of that variable at that memory location and at that point in the execution was consistently equal to the number of installed cars.

(There was some brute force work involved in scanning the entirety of the applications memory for consistent values/changes at various points in the runtimes execution)

I don't know why setting this value lower at this point in time avoids the crash. I supposed that it was a variable in some loop concerned with the crash but there is nothing but guesswork involved here. I feel that yours is certainly the more reasoned approach.

Posted: 21 Feb 2010, 03:20
jigebren
antimorph wrote:(There was some brute force work involved in scanning the entirety of the applications memory for consistent values/changes at various points in the runtimes execution)
Yes, I saw it on your second list above. I have also identified some values this way in the beginning. Now that I have a better overview of the whole exe file, with the help of the source code in can sometime make some interesting parallels.

I don't know why setting this value lower at this point in time avoids the crash. I supposed that it was a variable in some loop concerned with the crash but there is nothing but guesswork involved here.
You supposed well, I think, as the loop is on the number of cars. Since you have lowered this value, revolt will just loop on the fisrt cars and thus don't exceed the array size. But this way, some cars are never used by AI opponents. And I still think that 60 cars would crash revolt. Maybe it worked because, for most people, all cars would not be of the same category? (but I thought everyone was more inclined to use/create only Pro cars)

Posted: 21 Feb 2010, 03:28
antimorph
And I still think that 60 cars would crash revolt. Maybe it worked because, for most people, all cars would not be of the same category? (but I thought everyone was more inclined to use/create only Pro cars)
I know that I was running 155 cars during development of TMMCC, whilst I don't know the distribution by type it would seem that at least one category would always have exceeded 35.

However, within the first 60 cars (if going by the chronology of the directories in the revolt cars folder - which is what I think revolt retrieves) then the 35 limit may never have been broken, we know already that TMMCC prevents the later cars from being selected. Maybe this NumCars variable is the number of directories is some filesystem enumeration.

Posted: 21 Feb 2010, 03:32
antimorph
Which may mean that manipulating the folders that are apparent to revolt at the start of the race means that you can defeat the limit and ensure random selection of opponent vehicles. This may fit in with rst's way of thinking also as it would appear from the feature list of Phoenix R3 that he has already negotiated this. Yes, I suspect this has the ring of truth.

Posted: 21 Feb 2010, 03:55
jigebren
Well, I think I got it.

Revolt has 35 cars, including 5 'Pro' cars.
Imagine you add a lot of custom cars, so there will be a lot more than 35 Pro cars.
As with your patch revolt think it has only 60 cars, it will just look at the first 60 cars.
But I think revolt looks first for the stock cars, then for the custom cars, so we will have in the car list: 35 stock cars and 25 custom cars (a total of 60 cars).
Which means 5 stock Pro cars, and a maximum of 25 customs Pro cars (in case all added customs are Pro).
-> It gives a total of 30 Pro cars, less than the limit value of 35, so there is no bug :)


EDIT: hem, after a second read, it seems that what you said in a post above is quite similar.

Posted: 21 Feb 2010, 04:02
antimorph
I think that you will likely beat me to an implementation here. I would need to hack up TMMCC into some dll's that I could drive from a firefox addon using fantastic Mr. ECMAscript :)

Of course piping lap times into a distributed database using Firefox still carries some appeal :)

Posted: 21 Feb 2010, 04:16
jigebren
It's not heavily tested yet, but I think my patch (this one of which I talked about in a previous post - Posted: Feb 19 2010, 05:52) could be quite good: up to 128 cars in the same category, and no crash if this limit is reached.

And you were talking about the Phoenix R3 car limit fix fix implementation. Isn't it your patch implementation that is integrated?


And I don't really follow you about the firefox stuff... What does firefox has to do with revolt?

Posted: 21 Feb 2010, 04:32
antimorph
jigebren @ Feb 20 2010, 10:46 PM wrote: And you were talking about the Phoenix R3 car limit fix fix implementation. Isn't it your patch implementation that is integrated?

And I don't really follow you about the firefox stuff... What does firefox has to do with revolt?
I don't remember rst very well, I seem to recall a discussion once and could easily have shared code, but I'm not certain I recall well.

I already have skills with Firefox, and that technology stack is really where the really cool stuff is going on. The idea of poking and pulling on re-volt from "about:re-volt" amuses me. :P

Posted: 21 Feb 2010, 04:44
jigebren
antimorph @ Feb 21 2010, 12:02 AM wrote:I don't remember rst very well, I seem to recall a discussion once and could easily have shared code, but I'm not certain I recall well.
Even without code, it doesn't take a very long time to study your patch and imitate what it does, so it may be the same implementation.
The idea of poking and pulling on re-volt from "about:re-volt" amuses me.
Not very handy, but funny, yes it is. :D I couldn't even imagine things like that would be possible.

Posted: 21 Feb 2010, 04:47
antimorph
No doubt my going will be very slow (RL work is almost completely consuming) but I'll be happy to share the journey with you or anyone else that's interested. When I have a github project ready I'll share the url with you.

I would have thought launching revolt from a url would be super handy. :)

rv://BotanicalGardens?opponents=8&powerups=off&logging=on

Chop chop.

Posted: 21 Feb 2010, 05:11
jigebren
rv://BotanicalGardens?opponents=8&powerups=off&logging=on
:lol:

Speaking frankly, maybe I'm wrong, but I'm not sure there is a real interest except of course for someone like you who seems to be involved a lot in online/url/firefox stuffs. But I think you already know it ;) . Anyhow, I would be happy to help you if you need some revolt memory value offsets, or anything like that, don't hesitate to ask.

Posted: 28 Feb 2010, 16:33
miromiro
So, found anything that fixes the AI problem?

Posted: 28 Feb 2010, 16:36
antimorph
Yes, already WolfR4 offers an extremely good solution.

Posted: 28 Feb 2010, 18:15
miromiro
And it is... ?

Posted: 01 Mar 2010, 01:34
antimorph
WolfR4 is jigebrens' new patch suite, check earlier in the topic for details of the fix he has implemented.