Quantcast

Jump to content

» «
Photo

[SRC|REL] SCM Hook for Vice City

65 replies to this topic
random_download
  • random_download

    :o

  • Members
  • Joined: 07 Mar 2004

#31

Posted 12 July 2005 - 09:28 AM

CODE
int __declspec(naked) ExecuteScriptBuf()
{
__asm
{
 mov eax, OFFSET ScriptBuf // Move our script buffer base into eax.
 sub eax, SCRIPT_BASE  // Subtract usual script base from eax.

 mov ecx, gst    // Move GAME_SCRIPT_THREAD structure into ecx.
 mov [ecx+0x10], eax   // Move eax into the gst->dwScriptIP.

 call ProcessOneCommand  // Call the game's script opcode processor.
 xor eax, eax    // eax = 0.
 mov ecx, gst    // Move game script thread into ecx again.
 mov al, [ecx+0x79]   // Move the jumpflag into al (return value).
 ret       // return.
}
}


int Main()
{
ScriptBuf[1] = 0x01;
ScriptBuf[2] = 0x00;
ScriptBuf[3] = 0x04;
ScriptBuf[4] = 0x00;
int result = ExecuteScriptBuf(); // Execute script stub.
}

That code should call a "wait 0 ms" command. To call basic commands such as this that is really the only code you need (as well as declaring the vars and structures like gst). ScriptBuf contains the compiled scm code you want to execute. Format is:
Opcode(Word), ParamType(Byte), Parameter, ParamType(Byte), Parameter, etc.
Parameter types are:
01: 32bit int
02: Global var
03: Local var
04: 8bit int
05: 16bit int
06: float (4 byte)

For a string eg. in name_thread or gxt references miss out the parameter type.
01 00 04 00 = 0001: wait 0 ms, as "0" can be stored in an 8bit int and so parmeter type 04 is used.

ceedj
  • ceedj

    PEDS Creator

  • Members
  • Joined: 21 May 2005

#32

Posted 13 July 2005 - 12:16 AM

Ahhhh, things are getting clearer now, but I still don't get a couple of things:

A) Opcode(Word)

How does the program (or dll in this case) know what opcode is what? From what I can gather, you say

01 00 04 00 = 0001: wait 0 ms

So to me, it look like this:
CODE

ScriptBuf[1] = 0x01; - The "wait" opcode
ScriptBuf[2] = 0x00; - ? Or is this the first half of the opcode, and it's read in reverse?
ScriptBuf[3] = 0x04; - The parameter type, in this case 8bit
ScriptBuf[4] = 0x00; - The parameter for the previous type, in this case 00 ms


Does this mean I need to define the opcodes I will be using? For example, it seems that somewhere it needs to be defined that 0x01 becomes the opcode 0001. So that would mean that I would need to define somewhere that 0x02 = 0372 (actor wait state). Or does it work in reverse like I said, becoming this:
CODE

ScriptBuf[1] = 0x72; Second half of wait_state opcode
ScriptBuf[2] = 0x03; first half of wait_state opcode
ScriptBuf[3] = 0x02; Param type is a global
ScriptBuf[4] = 0x01; Not sure how I should get around this... should I rename my globals to numbers? If so, that would make my first ped = 1
ScriptBuf[5] = 0x04; Param type is 8bit
ScriptBuf[6] = 0x31; Wait state 31 (guestures 2, I think)
ScriptBuf[7] = 0x04; Param type is 8bit
ScriptBuf[8] = 0x20; 20ms, although how would I get higher numbers, like 2000 ms or more?

So that would give the game: 0372: 1 31 20ms

Is this close, or am I totally off the mark. If it's a byte conversion thing, I'll learn it, but I'm not sure where to start. Does it need to be converted to hex? That would make more sense to me, I think...

B) Obviously, I'd like a bunch of these sitting around. I noticed this:

int Main()

Is the Main() a label? For different opcodes, would I just change this to a different name? For example:

int WaitState1()
code follows

int WaitState2()
code follows

etc.

So when I call it from my WM_CHAR (the Windows I/O KeyPress), would I do this?
CODE

bool KeyPresses = false;
  for (;;)
    if (case WM_CHAR:
        switch(wParam)
           {
              case 'Q'   // Shift + q
int WaitState1()
code follows
int result = ExecuteScriptBuf(); // Execute script stub.
}
            {
              case 'W'   // Shift + w
int WaitState2()
code follows
int result = ExecuteScriptBuf(); // Execute script stub.
}

etc....

C) (as well as declaring the vars and structures like gst).

What does Canadian Tax have to do with it? wink.gif

I'll assume that was a typo and you meant gxt (text stuff). But I don't need text stuff. Does this relate to A) above when declaring what the opcode is, which ped is who, etc?

Thanks a bunch man, I think I'm getting closer...

Y_Less
  • Y_Less

    629

  • Members
  • Joined: 14 Mar 2004

#33

Posted 13 July 2005 - 01:08 AM

Alot of this I don't know, but some I can answer from the earlier days of mission coding.

Yes, the OpCodes are defined backwards - 0001 is 01 00 in the SCM or in this case in your code. Yes your numbers need to be in hex so a wait 20 ms command would be 01 00 04 14 (14 being 20 in HEX). For larger numbers, you would need a bigger space to store the number in (e.g. 16 bits - 05), so wait 2000 ms would be 01 00 05 07 D0 (7D0 is 2000 in HEX and the numbers are not reversed, but they require a preceding 0 to pad it out).

Finally, referencing your actors. When you define an actor as $myactor1, that variable is only used as a marker in your builder. As you may know, these are only references to the actor, but the game does not read them as this, it reads them as memory offsets from the start of the SCM memory block, $myactor1 is not an offset, but 352?? or any other multiple of 4 (or possibly 8) is (when you decompile an SCM, you will see al the default variables as $1 $2 $3 etc, these are the offset divided multiple (4 or 8). Unfortunately, you cannot use Direct Memory Access in the latest builders, even though it was useful, you will need an old builder such as 0.22, which I still use a bit. To get the offset of you actor, you will need to compile then in a hex editor, track down the create_actor you used, and look at the 2 bytes after the 02 variable type, this is the actors ACTUAL variable, and is what you would need to use to reference it.

I know this is a fairly basic explanation of what goes on, but its the best I can do at the moment, I'm a bit rusty on DMA.

ceedj
  • ceedj

    PEDS Creator

  • Members
  • Joined: 21 May 2005

#34

Posted 13 July 2005 - 01:31 AM Edited by ceedj, 13 July 2005 - 06:55 AM.

You sir, are WONDERFUL!

That really helps alot!
EDIT: I got the old MB; I just slugged this into the original MAIN.SCM
CODE

009A:  $Grp1Ped1?? = create_actor  4? #PGA at  10@  11@  12@
009A:  $Grp2Ped1?? = create_actor  4? #PGA at  10@  11@  12@
009A:  $Grp2Ped2?? = create_actor  4? #PGA at  10@  11@  12@
009A:  $Grp3Ped1?? = create_actor  4? #PGA at  10@  11@  12@
009A:  $Grp3Ped2?? = create_actor  4? #PGA at  10@  11@  12@
009A:  $Grp3Ped3?? = create_actor  4? #PGA at  10@  11@  12@
009A:  $Grp4Ped1?? = create_actor  4? #PGA at  10@  11@  12@
009A:  $Grp4Ped2?? = create_actor  4? #PGA at  10@  11@  12@
009A:  $Grp4Ped3?? = create_actor  4? #PGA at  10@  11@  12@
009A:  $Grp4Ped4?? = create_actor  4? #PGA at  10@  11@  12@

Except I'm not entirely sure WHERE to look in the hex editor for what I'm looking for. Again, the code above doesn't need to "work" per say; it's just so I can find the offsets you are talking about. So where WOULD I find this?

Would this be the same for my car creation routine, since I'll need to put a ped in a car on occasion (see Just A Short - Getaway for that usage)?

EDIT 2: And just so I'm clear, the actor_wait_state code from my above post would now be:
CODE

int WaitState1()
{
ScriptBuf[1] = 0x72; //Second half of wait_state opcode
ScriptBuf[2] = 0x03; //first half of wait_state opcode
ScriptBuf[3] = 0x02; //Param type is a global
ScriptBuf[4] = 0x??; //Need to find actor offset
ScriptBuf[5] = 0x04; //Param type is 8 bit
ScriptBuf[6] = 0x1F; //Wait state 31 (guestures 2)
ScriptBuf[7] = 0x05; //Param type is 16 bit
ScriptBuf[8] = 0x07; //First half of 2000 ms
ScriptBuf[9] = 0xD0; //Second half of 2000 ms
int result = ExecuteScriptBuf(); // Execute script stub.
}
int ClearObj1()
{
ScriptBuf[1] = 0x1C; //Second half of clear_objective opcode
ScriptBuf[2] = 0x01; //first half of clear_objective opcode
ScriptBuf[3] = 0x02; //Param type is a global
ScriptBuf[4] = 0x??; //Need to find actor offset
int result = ExecuteScriptBuf(); // Execute script stub.
}


Which SHOULD give me

0372: ?? 31 2000m
011C: ??

Correct?

Again, many thanks! Getting closer still... rah.gif

EDIT 3: I was playing around with Delfi's Devloper Console, and found the pointers for my created peds. They remain the same, no matter how many times I change them, so this must reference my peds creation routine (I used the No Peds/Vehicles option to eliminate other peds so I could get the right numbers). Here's what I got:

CODE

1 ped
Pointer - 29875600
Type - 6888364

2 peds
ped1
Pointer - 29854400
Type - 6888364

ped2
Pointer - 29861408
Type - 6888364

4 peds
ped1
Pointer - 29857904
Type - 6888364

ped2
Pointer - 29863160
Type - 6888364

ped3
Pointer - 29870168
Type - 6888364

ped4
Pointer - 29878928
Type - 6888364


Converting the first number to hex gives me 1C7DD90. Since to make this a mutiple of 4 or 8, I'd have to add a leading 0 to pad it out, giving me this:

01C7DD90

So, in int WaitState1(), my ScriptBuf becomes:
CODE

int WaitState1()
{
ScriptBuf[1] = 0x72; //Second half of wait_state opcode
ScriptBuf[2] = 0x03; //first half of wait_state opcode
ScriptBuf[3] = 0x01; //Param type is 32 bit then add
ScriptBuf[4] = 0x01; //Ped ID part 1
ScriptBuf[5] = 0xC7; //Ped ID part 2
ScriptBuf[6] = 0xDD; //Ped ID part 3
ScriptBuf[7] = 0x90; //Ped ID part 4
ScriptBuf[8] = 0x04; //Param type is 8 bit
ScriptBuf[9] = 0x1F; //Wait state 31 (guestures 2)
ScriptBuf[10] = 0x05; //Param type is 16 bit
ScriptBuf[11] = 0x07; //First half of 2000 ms
ScriptBuf[12] = 0xD0; //Second half of 2000 ms
int result = ExecuteScriptBuf(); // Execute script stub.
}


OR do I just do this:
CODE

int WaitState1()
{
ScriptBuf[1] = 0x72; //Second half of wait_state opcode
ScriptBuf[2] = 0x03; //first half of wait_state opcode
ScriptBuf[3] = 0x01; //Param type is 32 bit
ScriptBuf[4] = 0x1C7DD90; //Actor ID
ScriptBuf[5] = 0x04; //Param type is 8 bit
ScriptBuf[6] = 0x1F; //Wait state 31 (guestures 2)
ScriptBuf[7] = 0x05; //Param type is 16 bit
ScriptBuf[8] = 0x07; //First half of 2000 ms
ScriptBuf[9] = 0xD0; //Second half of 2000 ms
int result = ExecuteScriptBuf(); // Execute script stub.
}


and forget about adding the leading 0?

Will this help me at all? Or am I completely wrong?

random_download
  • random_download

    :o

  • Members
  • Joined: 07 Mar 2004

#35

Posted 13 July 2005 - 10:38 AM

To find the actor in a hex editor search for:
CODE
9A 00 04 04 05 95 00 03 0A 00 03 0B 00 03 0C 00 02 <here is the global var>

You should find a chunk like that, just like in your code.
int Main() is not a label. It is how a function is declared in C++, so to call it you would do:
CODE
int Result = Main();

The function Main() is executed once the program starts however, so you should not need to call it.
Sorry, I forgot to mention, global and local vars are Words, ie. 2 bytes long. Whenever you read a word, dword etc. it is read in "reverse". So 0x20000000 would be 00 00 00 20, and 03A7 would be A7 03
so:
CODE

int WaitState1()
{
ScriptBuf[1] = 0x72; //Second half of wait_state opcode
ScriptBuf[2] = 0x03; //first half of wait_state opcode
ScriptBuf[3] = 0x02; //Param type is a global
ScriptBuf[4] = 0x??; //Need to find actor offset
ScriptBuf[5] = 0x??; //Need to find actor offset
ScriptBuf[6] = 0x04; //Param type is 8 bit
ScriptBuf[7] = 0x1F; //Wait state 31 (guestures 2)
ScriptBuf[8] = 0x05; //Param type is 16 bit
ScriptBuf[9] = 0xD0; //First half of 2000 ms
ScriptBuf[10] = 0x07; //Second half of 2000 ms
int result = ExecuteScriptBuf(); // Execute script stub.
}
int ClearObj1()
{
ScriptBuf[1] = 0x1C; //Second half of clear_objective opcode
ScriptBuf[2] = 0x01; //first half of clear_objective opcode
ScriptBuf[3] = 0x02; //Param type is a global
ScriptBuf[4] = 0x??; //Need to find actor offset
ScriptBuf[5] = 0x??; //Need to find actor offset
int result = ExecuteScriptBuf(); // Execute script stub.
}

You could also have more developed function eg.:
CODE

int Wait(int Time)
{
ScriptBuf[1] = 0x01;
ScriptBuf[2] = 0x00;
 if (Time >= -128) and (Time <= 127) {
ScriptBuf[3] = 0x04;
memcpy(&ScriptBuf[4], &Time, 1);
        }
 else if (Time >= -32768) and (Time <= 32767) {
ScriptBuf[3] = 0x05;
memcpy(&ScriptBuf[4], &Time, 2);
        }
 else {
ScriptBuf[3] = 0x01;
memcpy(&ScriptBuf[4], &Time, 4);
        }
int result = ExecuteScriptBuf(); // Execute script stub.
}

Then you would just go:
Wait(1000); // 0001: wait 1000 ms

ScriptBuf is an array of BYTE, each part of it is 1 byte long so
ScriptBuf[4] = 0x1C7DD90; //Actor ID
won't work as you are trying to put 4 bytes into a memory of 1 byte.

@Y_Less:
QUOTE
so wait 2000 ms would be 01 00 05 07 D0 (7D0 is 2000 in HEX and the numbers are not reversed, but they require a preceding 0 to pad it out).

Are you sure? I thought that parameters were written the normal way if they are > 1 byte ie. "reversed".

ceedj
  • ceedj

    PEDS Creator

  • Members
  • Joined: 21 May 2005

#36

Posted 13 July 2005 - 10:48 AM Edited by ceedj, 13 July 2005 - 11:13 AM.

Very good, this is starting to actually make SENSE.

Awesome with the help. Thanks!

I have much to play with now...

EDIT: This is what HexWorkshopFree spits out for me:
CODE

/*00D459:*/ 0x9A, 0x00, 0x04, 0x04, 0x04, 0x5F, 0x03, 0x0A, 0x00, 0x03, 0x0B, 0x00, 0x03, 0x0C, 0x00, 0x02, 0x64,
/*00D46A:*/ 0x03, 0x9A, 0x00, 0x04, 0x04, 0x04, 0x5F, 0x03, 0x0A, 0x00, 0x03, 0x0B, 0x00, 0x03, 0x0C, 0x00, 0x02, 0xF0,
/*00D47C:*/ 0x03, 0x9A, 0x00, 0x04, 0x04, 0x04, 0x5F, 0x03, 0x0A, 0x00, 0x03, 0x0B, 0x00, 0x03, 0x0C, 0x00, 0x02, 0x18,
/*00D48E:*/ 0x0D, 0x9A, 0x00, 0x04, 0x04, 0x04, 0x5F, 0x03, 0x0A, 0x00, 0x03, 0x0B, 0x00, 0x03, 0x0C, 0x00, 0x02, 0x1C,
/*00D4A0:*/ 0x0D, 0x9A, 0x00, 0x04, 0x04, 0x04, 0x5F, 0x03, 0x0A, 0x00, 0x03, 0x0B, 0x00, 0x03, 0x0C, 0x00, 0x02, 0x20,
/*00D4B2:*/ 0x0D, 0x9A, 0x00, 0x04, 0x04, 0x04, 0x5F, 0x03, 0x0A, 0x00, 0x03, 0x0B, 0x00, 0x03, 0x0C, 0x00, 0x02, 0xD0,
/*00D4C4:*/ 0x0D, 0x9A, 0x00, 0x04, 0x04, 0x04, 0x5F, 0x03, 0x0A, 0x00, 0x03, 0x0B, 0x00, 0x03, 0x0C, 0x00, 0x02, 0x98,
/*00D4D6:*/ 0x0F, 0x9A, 0x00, 0x04, 0x04, 0x04, 0x5F, 0x03, 0x0A, 0x00, 0x03, 0x0B, 0x00, 0x03, 0x0C, 0x00, 0x02, 0xBC,
/*00D4E8:*/ 0x10, 0x9A, 0x00, 0x04, 0x04, 0x04, 0x5F, 0x03, 0x0A, 0x00, 0x03, 0x0B, 0x00, 0x03, 0x0C, 0x00, 0x02, 0x48,
/*00D4FA:*/ 0x11, 0x9A, 0x00, 0x04, 0x04, 0x04, 0x5F, 0x03, 0x0A, 0x00, 0x03, 0x0B, 0x00, 0x03, 0x0C, 0x00, 0x02, 0xE4,
/*00D50C:*/ 0x13,

9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 64
03 9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 F0
03 9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 18
0D 9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 1C
0D 9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 20
0D 9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 D0
0D 9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 98
0F 9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 BC
10 9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 48
11 9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 E4
13


The top section is C++ formated (very handy, yes?), the bottom is regular hex. So that I am clear, I am looking for the number immediately following the 02. In the first case it's 64, followed by 03. Now in my code (and the code random posted after) I have two spaces for the actor; do I need to use both the 64 and the 03, or is it just one or the other? Either way, I will play with both and see what happens...

I had a feeling about the int Main() thing; as I was looking over some sample code, I noticed that I can build all of the opcodes in Main() and call them with my OnKeyDown from another file. Silly of me perhaps, but I'm battling not only learning the syntax of C++, but also how to integrate that with all of the MB coding that I use now. I greatly appreciate the help in figuring this out though.

This is starting to remind me of the minor GameShark hacking I used to do with WWF No Mercy.

cool.gif

Y_Less
  • Y_Less

    629

  • Members
  • Joined: 14 Mar 2004

#37

Posted 13 July 2005 - 11:32 AM

9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 64 03
9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 F0 03
9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 18 0D
9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 1C 0D
9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 20 0D
9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 D0 0D
9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 98 0F
9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 BC 10
9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 48 11
9A 00 04 04 04 5F 03 0A 00 03 0B 00 03 0C 00 02 E4 13

Using this formatting, it is alot clearer to see what is going on, after all the 0C 00 02 are the ped references (64 03, F0 03, 18 0D ect), by the looks of things, they are backwards, so large waits probably are too.

Also, you variables: $Grp1Ped1?? are not valid $ indicates MB variable ?? indicates memory reference, for the first pe you could EITHER use $Grp1Ped1 or 0364??, but not both in the same SCM. If you use 0364?? the ped will definately be stored at 0364 (02 64 03), if you use $Grp1Ped1 it will be stored at the next availabe address assigned by MB, if you are going to be modifying your SCM alot and integrating it with C, I would suggest using the ?? variables so for every compile they are the same (as MTA do), just be careful you don't use an address used elsewhere, this is why we often advise against using numbered variables.

random_download
  • random_download

    :o

  • Members
  • Joined: 07 Mar 2004

#38

Posted 14 July 2005 - 11:00 AM Edited by random_download, 14 July 2005 - 10:09 PM.

QUOTE (ceedj @ Jul 13 2005, 10:48)
I have two spaces for the actor; do I need to use both the 64 and the 03, or is it just one or the other? Either way, I will play with both and see what happens...

You use both. The actor is defined by the number "364", so in your code you will use this to reference the actor:
ScriptBuf[4] = 0x64;
ScriptBuf[5] = 0x03;

Or you could do:
int Actor = 0x0364;
memcpy(&ScriptBuf[4], &Actor, 2);

Which will do the same thing.

ceedj
  • ceedj

    PEDS Creator

  • Members
  • Joined: 21 May 2005

#39

Posted 14 July 2005 - 06:01 PM

I REALLY appreciate the help guys, and I don't want to piss anyone off...

But...

I'm recoding my scm into C++, using spooky's structures. Trying to do this memory crap and all that is more of a pain than I need to deal with right now. I got about half of it done (just finishing up the system-wide keyhook); just need to setup a few more structures and opcodes.

Thanks very much though; everything is VERY informative. colgate.gif

albuemil
  • albuemil

    Player Hater

  • Members
  • Joined: 15 Oct 2002

#40

Posted 21 July 2005 - 12:46 PM

Hy.

Sorry to bother you again, but isn't there still a version for San Andreas ? i would like to add some things to SA, but without modifying the MAIN.SCM.

Question, if i save a game witha "SCM Hooking MOD", can it be loaded with "normal" GTA ? or it's the same as if you would have modified the MAIN.SCM file ?

Statico
  • Statico

    Programmer

  • Members
  • Joined: 19 Mar 2005

#41

Posted 24 August 2005 - 02:46 PM

Spookie has made a San Andreas version, but from what I know the source hasn't been released

ceedj
  • ceedj

    PEDS Creator

  • Members
  • Joined: 21 May 2005

#42

Posted 25 August 2005 - 03:31 AM

QUOTE (Statico @ Aug 24 2005, 10:46)
Spookie has made a San Andreas version, but from what I know the source hasn't been released

Like, OMG!

I hope he's not mad at me for using the Vice version. cryani.gif

I'd love to see that source though. Mostly so the 8 billion people can stop pestering me for San An Studios! blink.gif

random_download
  • random_download

    :o

  • Members
  • Joined: 07 Mar 2004

#43

Posted 01 September 2005 - 10:49 PM

QUOTE (albuemil @ Jul 21 2005, 12:46)
Question, if i save a game witha "SCM Hooking MOD", can it be loaded with "normal" GTA ? or it's the same as if you would have modified the MAIN.SCM file ?

As long as the scm hook doesn't call a create_thread command then you should be able to save and then load from an original scm file. If however any threads are created or destroyed, then you will not be able to load a game you make after doing this with an original scm.

Y_Less
  • Y_Less

    629

  • Members
  • Joined: 14 Mar 2004

#44

Posted 02 September 2005 - 05:42 PM

QUOTE (ceedj @ Aug 25 2005, 03:31)
QUOTE (Statico @ Aug 24 2005, 10:46)
Spookie has made a San Andreas version, but from what I know the source hasn't been released

Like, OMG!

I hope he's not mad at me for using the Vice version. cryani.gif

I'd love to see that source though. Mostly so the 8 billion people can stop pestering me for San An Studios! blink.gif

I don't think he will be mad at you for it, as he released it to be used, and you have made some very good missions with it.

Bench
  • Bench

    Player Hater

  • Members
  • Joined: 01 Oct 2005

#45

Posted 01 October 2005 - 03:04 AM

Excellent work, Spooky!

I've just gotten started with this GTA:SA modding malarky. all those funny cryptic numbers and the evil dreaded goto-style "jump" thingies in the script files were making my head ache! nervous.gif

Great to see there's a way to mod GTA in a language which I can actually understand and make sense of tounge.gif smile.gif

Great job, thanks for the contribution biggrin.gif

Nipa
  • Nipa

    Hi.

  • Members
  • Joined: 24 Apr 2005

#46

Posted 01 October 2005 - 03:15 AM

Um, you do know that this was meant for Vice City.. It'll not work with San Andreas, unless you can get Spookie to give you the SA version (rumor)

-Nipa

Bench
  • Bench

    Player Hater

  • Members
  • Joined: 01 Oct 2005

#47

Posted 01 October 2005 - 11:34 PM

Hummm, whoops... I didn't read the entire thread. confused.gif

op9080
  • op9080

    Player Hater

  • Members
  • Joined: 19 Sep 2005

#48

Posted 17 October 2005 - 11:03 AM Edited by op9080, 24 October 2005 - 11:01 AM.

Here's an updated GAME_SCRIPT_THREAD for GTA:SA

CODE
struct GTASA_SCRIPT_THREAD // 0xE0 bytes total.
{       //
void* pNext;   // 0x00
void* pPrev;   // 0x04
char strName[8];  // 0x08
DWORD dwBaseIP;   // 0x10
DWORD dwScriptIP;  // 0x14
DWORD dwReturnStack[8]; // 0x18
WORD dwStackPointer; // 0x38
DWORD dwLocalVar[34]; // 0x3C
BYTE bStartNewScript; // 0xC4
BYTE bJumpFlag;   // 0xC5
BYTE bIsMissionThread;// 0xC6
BYTE bIsExternalScript;// 0xC7
BYTE bInMenu   // 0xC8
BYTE bUnknown; // 0xC9
DWORD dwWakeTime;  // 0xCC
WORD wIfParam;   // 0xD0
BYTE bNotFlag;   // 0xD2
BYTE bWastedBustedCheck;// 0xD3
BYTE bWastedBustedFlag; // 0xD4
DWORD dwSceneSkipIP;  // 0xD8
BYTE bMissionThread; // 0xDC
};


Comments:
  • dwScriptIP contains an absolute address, not relative to script base.
  • For mission and external script threads, dwBaseIP contains the base address of the buffer at which the code is stored, since the code is not stored at the usual script base buffer. Jump targets with a negative value are relative to this address (the negative value is subtracted from dwBaseIP.) The buffer for mission threads is at address 0xA7A6A0. Buffers for external scripts are allocated dynmically since there can be many of them.
  • For non-mission threads (bMissionThread == 0), the thread's local vars are stored at offset 0x3C as above. For mission threads (bMissionThread != 0), the thread's local vars are stored in a buffer of length 4096 bytes at address 0xA48960 (right below the script base). There can only be 1 mission thread running, so there is no sharing problem for this buffer.
  • Local vars @32 and @33 are up-counting millisec timers. This holds true regardless of where the local vars are stored.
  • The flag bIsMissionThread appears to always have an identical value to bMissionThread, although it's tested for different purposes.
  • bWastedBustedCheck is set to 1 for all new threads. However an actual check is only performed if both bIsMissionThread and bWastedBustedCheck are non-zero.
  • dwSceneSkipIP is an IP to jump to if a cutscene is terminated by a keypress.
  • bInMenu indicates if the thread is in a game menu (the type used for buying food, clothes, ammunation, etc., not the main menu.)
  • bUnknown is initialized to 0xFF when a thread is created. It is used by external script threads where is can have a value of either 0xFF or 0-5.

dustcrazy
  • dustcrazy

    Just simply, the crazy one.

  • BUSTED!
  • Joined: 11 Apr 2004

#49

Posted 05 January 2006 - 12:36 AM Edited by dustcrazy, 05 January 2006 - 02:10 PM.

I am a cheap basterd and am currently learning C++. I have "Microsoft Visual C++ 2005 Express Edition", since its the only on I can get directly from Microsoft. I also have DevC++ and Microsoft C++ 6. But when I load it up with 2005 Expr. Edit. I get this after its converts it to the new.

QUOTE
Project: SCMMod
Filename Status Errors Warnings
SCMMod.vcproj Converted 0 2
Conversion Issues - SCMMod.vcproj:
Visual C++ now supports a secure version of the C Runtime Library. Use of this library is turned on by default. You may see some warnings about deprecated functions when you build your project. It is advised that you correct these warnings, in order to make your code more secure.
The C/C++ compiler default settings have been modified to be more compliant with ISO Standard C++. Included in those changes are enforcing Standard C++ for loop scoping and supporting wchar_t as a native type. These changes may cause existing code to no longer compile without changes to the code or the compiler options with which it is built.
Project file successfully backed up as 'C:\Documents and Settings\Dustin\Desktop\SCMMod\src\SCMMod.vcproj.7.10.old'.
Project upgraded successfully.
Due to the requirement that Visual C++ projects produce an embedded (by default) Windows SxS manifest, manifest files in the project are automatically excluded from building with the Manifest Tool. It is recommended that the dependency information contained in any manifest files be converted to "#pragma comment(linker,"<insert dependency here>")" in a header file that is included from your source code. If your project already embeds a manifest in the RT_MANIFEST resource section through a resource (.rc) file, the line will need to be commented out before the project will build correctly.
Due to a conformance change in the C++ compiler, code change may be required before your project will build without errors. Previous versions of the C++ compiler allowed specification of member function pointers by member function name (e.g. MemberFunctionName). The C++ standard requires a fully qualified name with the use of the address-of operator (e.g. &ClassName::MemberFunctionName). If your project contains forms or controls used in the Windows Forms Designer, you may have to change code in InitializeComponent because the designer generated code used the non-conformant syntax in delegate construction (used in event handlers).

1 file  Converted: 1
Not converted 0
Is this some thing I should worry about and if so what should I do?

Also I don't know how to load it with VC6++, as it doesn't have a workstation.

Btw THIS MOD KICKS A$$

Edit:
I complied it in Express Edition and got this long list of errors, Log

Edit: Compiling in VC++6
QUOTE
--------------------Configuration: SCMMod - Win32 Debug--------------------
Compiling...
ScriptClasses.cpp
GameScripting.cpp
GxtHook.cpp
MissionHook.cpp
c:\documents and settings\dustin\desktop\scmmod\src\missionhook.cpp(234) : warning C4018: '==' : signed/unsigned mismatch
MissionThreads.cpp
c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(433) : error C2362: initialization of 'bBringMsg' is skipped by 'goto MissionFailed'
        c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(393) : see declaration of 'bBringMsg'
c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(433) : error C2362: initialization of 'bBringMsg' is skipped by 'goto MissionFailed'
        c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(393) : see declaration of 'bBringMsg'
c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(433) : error C2362: initialization of 'bBringMsg' is skipped by 'goto MissionFailed'
        c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(393) : see declaration of 'bBringMsg'
c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(433) : error C2362: initialization of 'bBringMsg' is skipped by 'goto MissionFailed'
        c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(393) : see declaration of 'bBringMsg'
SCMMod.cpp
Error executing cl.exe.

SCMMod.dll - 4 error(s), 1 warning(s)

grovespaz
  • grovespaz

    Group: Morons

  • Members
  • Joined: 22 Feb 2004

#50

Posted 26 April 2006 - 12:01 PM Edited by grovespaz, 26 April 2006 - 12:31 PM.

QUOTE (dustcrazy @ Jan 5 2006, 00:36)
Edit: Compiling in VC++6
QUOTE
--------------------Configuration: SCMMod - Win32 Debug--------------------
Compiling...
ScriptClasses.cpp
GameScripting.cpp
GxtHook.cpp
MissionHook.cpp
c:\documents and settings\dustin\desktop\scmmod\src\missionhook.cpp(234) : warning C4018: '==' : signed/unsigned mismatch
MissionThreads.cpp
c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(433) : error C2362: initialization of 'bBringMsg' is skipped by 'goto MissionFailed'
        c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(393) : see declaration of 'bBringMsg'
c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(433) : error C2362: initialization of 'bBringMsg' is skipped by 'goto MissionFailed'
        c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(393) : see declaration of 'bBringMsg'
c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(433) : error C2362: initialization of 'bBringMsg' is skipped by 'goto MissionFailed'
        c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(393) : see declaration of 'bBringMsg'
c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(433) : error C2362: initialization of 'bBringMsg' is skipped by 'goto MissionFailed'
        c:\documents and settings\dustin\desktop\scmmod\src\missionthreads.cpp(393) : see declaration of 'bBringMsg'
SCMMod.cpp
Error executing cl.exe.

SCMMod.dll - 4 error(s), 1 warning(s)

Final edit(I hope):
Sorry for the bump, i had the same problem, and asked for help, but i figured it out:

I fixed the bBringMsg warning by moving
CODE
bool bBringMsg = false;
directly beneath
CODE
float fX, fY, fZ;


The
CODE
c:\documents and settings\dustin\desktop\scmmod\src\missionhook.cpp(234) : warning C4018: '==' : signed/unsigned mismatch

warning is fixed by removing one = in the line.

But now, the mission wont start if i stand in the marker, the marker does disappear, but nothing happens..

Cowpat
  • Cowpat

    web schmeb

  • Members
  • Joined: 12 Feb 2004

#51

Posted 26 April 2006 - 01:12 PM

QUOTE (grovespaz @ Apr 26 2006, 12:01)
The
CODE
c:\documents and settings\dustin\desktop\scmmod\src\missionhook.cpp(234) : warning C4018: '==' : signed/unsigned mismatch

warning is fixed by removing one = in the line.

But now, the mission wont start if i stand in the marker, the marker does disappear, but nothing happens..

Put the '=' sign back. You're changing a test for equality into an assignation. If you you want to remove the warning either change one of the data types or perform a cast.

ceedj
  • ceedj

    PEDS Creator

  • Members
  • Joined: 21 May 2005

#52

Posted 26 April 2006 - 03:33 PM

CODE
c:\documents and settings\dustin\desktop\scmmod\src\missionhook.cpp(234) : warning C4018: '==' : signed/unsigned mismatch


This warning has ALWAYS shown up from day one. I think it's because it was written in 7.1, and we compile with 6.0. I've always ignored it, and never had any issues. But like Cowpat said, put the other = back in; that statement checks if a mission is running.

I also had an issue with bBringMsg at the very beginning, but it's been almost a year since I've done it that I can't quite remember what I did. If you're still having problems, post back and I'll compare my code with the original and we'll see what I can find.

smile.gif

Herne
  • Herne

    Coffee Fiend

  • Members
  • Joined: 19 Jul 2005

#53

Posted 04 May 2006 - 08:01 PM

Ceedj, is there any chance you could give a c++ noob using dev-c++ 'a few tips' on how to compile this in dev-c++. I like the idea of coding missions with c++ syntax, but my knowledge of the language... and compilers in general, is somewhat limited.

ceedj
  • ceedj

    PEDS Creator

  • Members
  • Joined: 21 May 2005

#54

Posted 04 May 2006 - 08:05 PM

I don't think it will compile in dev c++, but I could be wrong. I've got MSVC++, so I never had a problem...

Anyone else have thoughts on this?

Y_Less
  • Y_Less

    629

  • Members
  • Joined: 14 Mar 2004

#55

Posted 04 May 2006 - 10:35 PM

I don't think it will compile as some of the libaries will be different. If you want to write missions in C syntax, have a look at POINT, a mission compiler with C syntax.

Cowpat
  • Cowpat

    web schmeb

  • Members
  • Joined: 12 Feb 2004

#56

Posted 06 May 2006 - 10:07 AM

QUOTE (Herne @ May 4 2006, 20:01)
Ceedj, is there any chance you could give a c++ noob using dev-c++ 'a few tips' on how to compile this in dev-c++. I like the idea of coding missions with c++ syntax, but my knowledge of the language... and compilers in general, is somewhat limited.

It seems that dev-cpp and directx will work together, but a little work is required to set it up. From what I've read Dev-cpp won't read .lib files unless they are converted to it's own .a (or .as ?) format. A utilty which comes with the MinGW compiler called reimp does that job, though you might like to write a little Batch file to do it.

This link appears useful, also this link and this link

Herne
  • Herne

    Coffee Fiend

  • Members
  • Joined: 19 Jul 2005

#57

Posted 09 May 2006 - 03:14 PM

thanks for the help but i'm afraid all that direct-x stuff is way over my head.
If anyone can give me a link for POINT i would be most grateful.

Y_Less
  • Y_Less

    629

  • Members
  • Joined: 14 Mar 2004

#58

Posted 09 May 2006 - 05:05 PM

http://www.joncaruan...projects/point/

Herne
  • Herne

    Coffee Fiend

  • Members
  • Joined: 19 Jul 2005

#59

Posted 10 May 2006 - 05:24 PM

Y_Less to my rescue! Again. Thanks!

ceedj
  • ceedj

    PEDS Creator

  • Members
  • Joined: 21 May 2005

#60

Posted 23 May 2007 - 09:21 PM Edited by ceedj, 23 May 2007 - 09:27 PM.

HUGE BUMP. YEAH!

Anyway, I'm having a problem, similar to the text issue I had using the SA hook (which CyQ was awesome enough to help fix). Same issue here; there are two animation headers in the game that I can't load because the strings are too long: playidles and sunbathe. Anyone wanna take a stab at how I can resolve this?

Thanks muchly! smile.gif

EDIT: This is related to this post if anyone wonders why I want to fix this. Thanks again.




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users