Quantcast
Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
    1. Welcome to GTAForums!

    1. Red Dead Redemption 2

      1. PC
      2. Gameplay
      3. Missions
      4. Help & Support
    2. Red Dead Online

      1. Gameplay
      2. Find Lobbies & Outlaws
      3. Help & Support
      4. Frontier Pursuits
    1. Crews & Posses

      1. Recruitment
    2. Events

    1. GTA Online

      1. Diamond Casino & Resort
      2. DLC
      3. Find Lobbies & Players
      4. Guides & Strategies
      5. Vehicles
      6. Content Creator
      7. Help & Support
    2. Grand Theft Auto Series

    3. GTA 6

    4. GTA V

      1. PC
      2. Guides & Strategies
      3. Help & Support
    5. GTA IV

      1. Episodes from Liberty City
      2. Multiplayer
      3. Guides & Strategies
      4. Help & Support
      5. GTA IV Mods
    6. GTA Chinatown Wars

    7. GTA Vice City Stories

    8. GTA Liberty City Stories

    9. GTA San Andreas

      1. Guides & Strategies
      2. Help & Support
      3. GTA SA Mods
    10. GTA Vice City

      1. Guides & Strategies
      2. Help & Support
      3. GTA VC Mods
    11. GTA III

      1. Guides & Strategies
      2. Help & Support
      3. GTA III Mods
    12. Top Down Games

      1. GTA Advance
      2. GTA 2
      3. GTA
    13. Wiki

      1. Merchandising
    1. GTA Modding

      1. GTA V
      2. GTA IV
      3. GTA III, VC & SA
      4. Tutorials
    2. Mod Showroom

      1. Scripts & Plugins
      2. Maps
      3. Total Conversions
      4. Vehicles
      5. Textures
      6. Characters
      7. Tools
      8. Other
      9. Workshop
    3. Featured Mods

      1. DYOM
      2. OpenIV
      3. GTA: Underground
      4. GTA: Liberty City
      5. GTA: State of Liberty
    1. Red Dead Redemption

    2. Rockstar Games

    1. Off-Topic

      1. General Chat
      2. Gaming
      3. Technology
      4. Programming
      5. Movies & TV
      6. Music
      7. Sports
      8. Vehicles
    2. Expression

      1. Graphics / Visual Arts
      2. GFX Requests & Tutorials
      3. Writers' Discussion
      4. Debates & Discussion
    1. News

    2. Forum Support

    3. Site Suggestions

Seemann

SA Memory handling

Recommended Posts

Seemann

I've decided to create a new topic to collect all examples how to handle GTASA memory via SCM.

If you don't understand what is written there, maybe it's not yours. I'll try to explain more things later by editing this post.

All codes are written in Sanny Builder v2.99. To get it working, you should download the latest version of SB.
http://www.gtaforums.com/index.php?showtopic=211077

All codes are tested in San Andreas v1.0 US. Memory addresses could be different in other versions. If something is not working, be sure you use the version I said.

1.
Now, we have three ways to handle the game memory .

1. Initial memory handling way was published in this topic
Stat opcodes provide limited memory access to locations near the stat pools. It allows to make things like changing the player's money, for example.

Advantages:
- the only opcode is using

Disadvantages
- memory range is very limited, many useful addresses are inaccesible.


2. Second way: using the Xieon's patch, that changes three opcodes in gta-sa.exe and provides extremely wide possibilities for game memory handling.
Download

Advantages:
- all game addresses are accessible
- possibility to protect a memory region with VirtualProtect to rewrite it

Disadvantages
- requires exe patching; may not work with different versions (but in fact, I did not see any messages that the patch is working incorrectly).


3. Third way: using the SA arrays to get an access to any addresses in range of 0..FFFFFFFF. Initially was posted there.

Advantages:
- all game addresses are accessible
- easy to use
- nothing especial required; scm-based solution

Disadvantages
- some of addresses still coudn't be rewritable (because of AccessViolation Error).


2.
For the last way, there are three routines to read/write values to the specified address:
(briefly, so far).


Memory Handling Routines (san andreas)

1 MemoryWrite: write new value with specified length into the memory
Params: [email protected] = address; [email protected] = new value; [email protected] - value length (1, 2, 3, 4)

2 MemoryWrite_DWORD: write new DWord value into the memory
Params: [email protected] = address; [email protected] = new value;

3 MemoryRead: read DWord value from the memory
Params: [email protected] = address; [email protected] = returned value;

note that some address could be unreadable/unrewriteable!!!
to change such addresses try Xieon's MemPatch: ..\tools\Sa Memory Patch\

//--write specified number of bytes into memory:MemoryWrite  0085: [email protected] = [email protected]@ /= [email protected] *= 4           // memory address0062: [email protected] -= [email protected]    // offset (0, 1, 2, 3)  :_GetInitValue      // if you specify mem offset in [email protected], you're able to gosub heregosub @MemoryRead // get initial [email protected] *= 8 // bytes -> [email protected] *= 8dec([email protected])for [email protected] = 0 to [email protected]  if    08B6: test [email protected] bit [email protected]  then    08BF: set [email protected] bit [email protected]    // 1  else    08C5: clear [email protected] bit [email protected]  // 0  end  inc([email protected]) // next memory bitend    008A: &0([email protected],1i) = [email protected]  // write new valuereturn//--write 32-bit value into memory-----------:[email protected] -= [email protected] /= 4008A: &0([email protected],1i) = [email protected]  return//--read 32-bit value from memory-----------:[email protected] -= [email protected] /= 4008B: [email protected] = &0([email protected],1i)return



3.
I wrote some examples using these routines . Most of examples were published at gtaf, some of them was out of there.

Now, they are:


-------------------------------------------------

EXAMPLE 1.
Make extremely long trains, 15+ carriages!

Original (in Russian)
Screenshot
-------------------------------------------------

:LONGTRAINSthread 'TRAINS'  for [email protected] = -382229 to -382216    wait 0    &0([email protected],1i) = #STREAKC          end                                               // type0 changed!  // load models  #FREIGHT.Load  #FREIFLAT.Load  #STREAKC.Load  while true    if and      Model.Available(#FREIGHT)      Model.Available(#FREIFLAT)      Model.Available(#STREAKC)      then      Break    end    wait 0  end     // create train with new carriages  06D8: [email protected] = create_train_at 2278.1771 -1144.8823 27.5108 type 0 direction 1  #FREIGHT.Destroy  #FREIFLAT.Destroy  #STREAKC.Destroy end_thread




-------------------------------------------------

EXAMPLE 2.
New cheats in run-time

Original
-------------------------------------------------

:NEWCHEATS// EXAMPLE 1: TEST 1 key press (space)thread 'CHEATS'[email protected] = -229908while true008B: [email protected] = &0([email protected],1i)      // get last keypresses0085: [email protected] = [email protected]        div([email protected], 0x 1 00)          // 1char: 0x100, 2chars: 0x10000: 3chars: 0x1000000mul([email protected], 0x 1 00)          // same0062: [email protected] -= [email protected]            // get needed number of chars (1)if  [email protected] == 0x20              // test if it's SPACEthen     03E5: text_box 'CHEAT1'// Cheat activated   Breakendwait 1000end// EXAMPLE 2: TEST 2 keys ('NO')[email protected] = -229908while true008B: [email protected] = &0([email protected],1i)       // get last keypresses0085: [email protected] = [email protected]        div([email protected], 0x 1 00 00)        // 1char: 0x100, 2chars: 0x10000: 3chars: 0x1000000mul([email protected], 0x 1 00 00)        // same0062: [email protected] -= [email protected]             // get needed number of chars (2)if  [email protected] == 0x4e4f             // test if player typed NOthen    03E5: text_box 'CHEAT1'  // Cheat activated  Breakendwait 1000end// EXAMPLE 3: TEST 3 keys ('WOW')[email protected] = -229908while true008B: [email protected] = &0([email protected],1i)       // get last keypresses0085: [email protected] = [email protected]        div([email protected], 0x 1 00 00 00)     // 1char: 0x100, 2chars: 0x10000: 3chars: 0x1000000mul([email protected], 0x 1 00 00 00)     // same0062: [email protected] -= [email protected]             // get needed number of chars  (3)if  [email protected] == 0x574f57           // test if player typed WOWthen    03E5: text_box 'CHEAT1'// Cheat activated  Breakendwait 1000end// EXAMPLE 4: TEST 4 keys ('HACK')[email protected] = -229908while trueif  &0([email protected],1i) == 0x4841434B  // test if player typed HACKthen  03E5: text_box 'CHEAT1'  // Cheat activated  Breakendwait 1000end// EXAMPLE 5: TEST 5 keys ('SANNY')// test 5th char 's' from address +4b, then test 'anny' from the beginning;//  addr      keys// -229908: X X X X    |  -229908: A N N Y// -229907: X X X O 



-------------------------------------------------

EXAMPLE 3.
Changing of the local variables of any thread

Original (in Russian)
-------------------------------------------------

// ---------------------------------------------//  This thread searches the one named TEST//  and changes its local variable [email protected]// ---------------------------------------------:CHANGELOCALVARthread 'CLV'{  [email protected]  =  thread address  [email protected]  =  temp}[email protected] = 0xA8B42C  // FIND_THREAD_LOOPwhile true  gosub @MemoryRead  // [email protected] = first active thread  if [email protected] == 0  then    Break // no threads, search failed  end  0085: [email protected] = [email protected]    // save the pointer  // get thread name magic address  div([email protected], 8)  dec([email protected], 1 348 395)  {   IMPORTANT NOTE:    thread names are stored in lowercase registry,    so we've to compare it in lowercase as well.    SB option 'Case Converting' has to be set to 'As is'!  }  if &0([email protected],1s) == 'test'  // check if this thread's name is "test"  then        // well, we've found it, can do everything with it    // [email protected] contains that thread address    // get address of [email protected]          inc([email protected], 0x3c)     // thread locals pool    inc([email protected], 40)       // local var name * 4; i.e. set to 36 to change [email protected]       // MEMORY WRITE DWORD    [email protected] = 3333 // new value of thread('test')[email protected]    gosub @MemoryWrite32bit    Break // end the LOOP  else    // no, that thread has another name    // check the next one    wait 0  end  // go to while_beginend// variable changed, end_thread  end_thread// ---------------------------------------------//  This thread shows a number after 1 sec//  after activated. The number is stored in [email protected]// ---------------------------------------------:TEST1thread 'TEST'[email protected] = 10000wait 3000054C: use_GXT_table 'POOL'01E3: text_1number_styled 'NUM' [email protected] 5000 ms 1  // ~1~end_threadoptimized version of CLV thread (see above):CODE:CLV03A4: name_thread 'CLV'0006: [email protected] = 67251:CLV_LOOP008B: [email protected] = &0([email protected],1i)00D6: if8039:   not  [email protected] == 0004D: jump_if_false @CLV_END0001: wait 0 ms0085: [email protected] = [email protected]: [email protected] /= 8000E: [email protected] -= 13483950016: [email protected] /= 4000E: [email protected] -= 269679200D6: if05AD:   &0([email protected],1s) == 'test'004D: jump_if_false @CLV_LOOP// 25 is the local number + 15// i.e. set to 24 to change [email protected]: [email protected] += 25// 3333 is a new value of the local0004: &0([email protected],1i) = 3333:CLV_END004E: end_thread




-------------------------------------------------

EXAMPLE 4.
Remove the message "To stop Carl..." when the player
first time stealing a car

Original
-------------------------------------------------

:MSGREMOVE thread 'NOMSG' [email protected] = 0xC0BC15 //  ADDRESS [email protected] = 1        //  VALUE [email protected] = 1        //  LENGTH (Byte) gosub @MemoryWriteend_thread

4.
You can grab a main.scm with all examples from here:
http://www.mysharefile.com/v/7409206/memhandling.rar.html

- Readme included
- source included


changes history:

08 Oct 2014:

- fixed CODE tags

06 Dec 2006:
- added link to the Xieon's patch
- added optimized version of CLV thread (example #3)

Edited by Seemann

Share this post


Link to post
Share on other sites
ceedj

Excellent post Seemann!

 

I have applied the #2 method (Xieon's Patch) and have gotten it working using the SA loader by op9080 (a C++ hook, and the foundation for SA Studios). Here's the opcode setups:

 

//Xieon's Memory PatchDEFINE_OPCODE(read_mem_addy, 0x00C3, "iii");DEFINE_OPCODE(write_mem_addy, 0x00C4, "iii");DEFINE_OPCODE(virtual_protect_change_at, 0x0181, "iii");

 

 

And here's his example from the Read Me that comes with the patch (moon gravity on jumps)

 

theScript << virtual_protect_change_at << 8796548 << 4 << 4;theScript << write_mem_addy << 8796548 << 2 << 0.002;theScript << virtual_protect_change_at << 8796548 << 4 << -1;

 

 

Two things:

 

1) On 0181, the last parameter is a float in the example. Though it works now, suppose I use an address that needs an integer? How would I solve this?

 

2) Maybe add a link to the patch in your first post.

 

My only gripe with the patch method is that you'd have to include it in any mods that use it (is he allowing this? It's not really clear in the Read Me file), and get your end user to patch it. Although nifty that an auto-find and backup were included in the patch. smile.gif

Edited by ceedj

Share this post


Link to post
Share on other sites
Seemann

 

1) On 0181, the last parameter is a float in the example. Though it

works now, suppose I use an address that needs an integer? How would I solve this?

 

sorry, but why do you speak about 0181? This one has all the parameters integer. Do you mean 00C3/00C4?

 

 

My only gripe with the patch method is that you'd have to include it in any mods that use it (is he allowing this? It's not really clear in the Read Me file), and get your end user to patch it.

 

yes, it's free to distribute, the only you'd have to do is to include Readme.txt with the patch.

 

Share this post


Link to post
Share on other sites
Bigun

Splendid post Seemann!

That's nice, modifying thread locals...we can pretty much kiss globals away. O_o Also good for savegame compabillity.

Share this post


Link to post
Share on other sites
ceedj

I was in fact refering to 00C4. Whoops. smile.gif Anyway, sorry for the confusion. I edited my post with the correct data type for 0181.

 

This is what I get for replying to topics with little sleep. lol.gif

Share this post


Link to post
Share on other sites
Seemann

Main.scm Got Cracked!

 

Finally, I figured out a way to run an assembler code from a main.scm without any patches or whatever.

From now, we have no limits for the coding ever.

 

It's similar to the CyQ's method of an injection of the asm code to change opcode handlers.

I found two opcodes in SA that could make the same function.

 

They are: 0572 and 0A3D.

 

So, how it works.

 

1. In San Andreas we have 92 cheats. Some of them are null, some are well-known and often used.

2. These opcodes are well known too. 0572 gives to all taxis the nitro, 0A3D makes the prostitutes pay you (it doen't matter, I use 0572).

But not anybody knows that this opcodes works as the cheats like. They enables one of the 92 flags and game begins to think that you use a cheat (but without affecting cheats history, only implying what the cheat does).

3. 0A3D referring to the cheat #90, 0572 - cheat #91

4. All the cheats routines addresses are stored as simple Dword values and COULD be changed in run-time via array's method.

5. So, what this code does: it changes 91st cheat routine address with a value INSIDE main.scm (all adresses are well-known). Then we run this cheat and game goes to the address we set, in other words it goes inside main.scm and begins work with the code as with an assembler.

 

Using hex..end struct in Sanny Builder it's possible to execute ANY code you want.

 

Personally I'm not good ASM'er, so my example is a kind of useless (I just give 1000 buxes to the player), but it's only the beginning.

Somebody who knows asm well could implement VirtualProtect routine and then we even do not need to patch the game with the Xieon's patch to work with the addresses that have to be protected (a gravity one, for example).

 

The code:

 

// ----------------------------------//      Asm code injector// ----------------------------------// set new handler [email protected] = -429863&0([email protected],1i) = 0xA49960&0([email protected],1i) += @__AsmInjection// Run Asm Injection0572: 1// restore handler&0([email protected],1i) = 0return:__AsmInjectionhex// here goes ASM code!//My example: Add $1000 to the player moneyB8 E8030000     // mov eax, 100001 05 50CEB700  // add [0xB7CE50], eaxC3              // returnend

 

 

This code adds 1000 to the value stored at 0xB7CE50 (player.money). Bit useless, but works!

 

 

Pay attention: that was tested in San Andreas v1.0 US. If you have v1.01 please test if it works.

 

 

well, well... There's another example:

http://sannybuilder.com/files/cheater.rar

 

This mod allows to enable all cheats by pressing Action Key.

 

Edited by Seemann

Share this post


Link to post
Share on other sites
Seemann

I could run the VirtualProtect procedure from the main.scm, and now there's no need for the Xieon's patch: we can do the same through the SCM. Worked on US, EUR, GER 1.0

 

That's the full code how to write the value with the specified length (1,2,4 bytes) to the specified address protected with VP.

 

 

:[email protected] == 1jf @[email protected] = -429863&0([email protected],1i) =  0xA49960&0([email protected],1i) += @_____vpsv0052: gap 0 virtual_protect_at_address [email protected] size [email protected] newprotect 4 gap 0 00572: 1gosub @MemoryWrite0052: gap 0 virtual_protect_at_address [email protected] size [email protected] newprotect -1 gap 0 00572: 1&0([email protected],1i) = 0end_thread:_____novpgosub @MemoryWriteend_thread:[email protected] = -429864&0([email protected],1i) =  0xA49960&0([email protected],1i) += @_____mwss0052: gap 0 target_address [email protected] size [email protected] value [email protected] gap 0 00A3D: 1&0([email protected],1i) = 0return:_____vpsvhex68 F4 3C A4 00 83 3D 84 3C A4 00 FF75 08 FF 35 F4 3C A4 00 EB 06 FF 35 84 3C A4 00 FF 35 80 3C A4 00 FF 35 7C 3C A4 00 FF 15 2C 80 85 00 C3end:_____mwsshex8B 15 7C 3C A4 00 8B 05 84 3C A4 00 83 3D 80 3C A4 00 01 75 03 88 02 C3 83 3D 80 3C A4 00 02 75 04 66 89 02 C3 89 02 C3end

 

 

It is a thread that executed once and stopped. Place it to your scripts as you did with other threads.

When you create it with 004F, pass four parameters to it:

 

 

create_thread @MemoryProofWrite address (DWORD) size (Byte: 1,2,4) value (DWORD) VirtualProtect (BOOL)

 

 

then the local variables of the thread will be initialized with these values. The variables as parameters are allowed.

 

 

If you only need to write values (without the VirtualProtect) use

 

create_thread @MemoryProofWrite address XXXX size XXXX value XXXX VirtualProtect 0

 

or without VirtualProtect parameter ever

 

 

 

 

 

Hello, world!

 

Example1. Changing the gravity (the patch example) /with VirtualProtect

 

 

create_thread @MemoryProofWrite address 0x00863984 size 4 value 0.002 VirtualProtect 1

 

 

Compiled SCM and source

 

 

Example2. Remove annoying message about entering car (from the first post) /without VirtualProtect

 

 

create_thread @MemoryProofWrite address 0xC0BC15 size 1 value 1

 

Edited by Seemann

Share this post


Link to post
Share on other sites
DexX

Seemann, i just want to be sure i understand you correctly, since i'm not a mission coder;

Are you saying we can write anywhere in the game's memory, and write any size data?

 

i've been using a modified vorbis dll (by delfi) to load .asi files, which alter the game's memory as i wish @ runtime. could we use this code you posted, along with the "mission pack" method of installing scm mods? if so that would really be sweet..

Share this post


Link to post
Share on other sites
Seemann

 

Are you saying we can write anywhere in the game's memory, and write any size data?

The memory address could be any, but the value size could only be 1, 2 or 4 bytes.

 

The asm code there contains something like:

 

 

cmp size, 1ja @2mov byte ptr [address], valueret:2cmp size, 2ja @4mov word ptr [address], valueret:4mov dword ptr [address], valueret

 

 

 

I could implement the BlockWrite routine for writing the data with any size, need that?

 

Share this post


Link to post
Share on other sites
PLPynton

that is just great. what is missing is a possibility to decompile a game script whenever hex data input is there. or in fact make a way so code written in such a form will could be decompiled and compiled without loosing its functionality.

as most of the coders will like to use your work here it will be a big minus if their MOD can not be decompiled back.

Edited by PLPynton

Share this post


Link to post
Share on other sites
Seemann

 

what is missing is a possibility to decompile a game script whenever hex data input is there.

No, such possibility is there since v2.98, IIRC.

The Sanny Builder console could receive the commands from the input line and you can turn on the option IGNORE_UNKNOWN which allows to decompile almost any protected/broken scm. Read the help files and the console texts

 

 

Share this post


Link to post
Share on other sites
PLPynton

i mean that in other way:

it is great what you just did!

 

and the SB returns me

"Thread not found. Base: 194426. Probably Script.img is broken"

 

edit: i inserted the thread just before mission 0 (added if line that was missing at the beginning), i issued with

create_thread @MemoryProofWrite address 0x00863984 size 4 value 0.002 VirtualProtect 1

from mission 0 code

is there anything i could forget to switch?

Edited by PLPynton

Share this post


Link to post
Share on other sites
Seemann

 

and the SB returns me

"Thread not found. Base: 194426. Probably Script.img is broken"

 

I'm successed to decompile the files with the hex insertions.

BTW, there's no way for exact decompiling. The labels (_____vpsv, _____mwss) will disappear as well when you decompile . So, the way for other people is that the author has to include his source with the mod.

 

 

i issued with create_thread @MemoryProofWrite address 0x00863984 size 4 value 0.002 VirtualProtect 1

 

cant understand the kind of issue: code doesnt compile or the game crashes? I just do the same and all works fine to me (heh, it's too funny play with gravity=2.0)

 

Share this post


Link to post
Share on other sites
PLPynton

well, i still can not decompile it but as you say we have to include source ok, not a problem i guess.

 

i do not want to mess up too much: there is a way to place any kind of informations within script after jump command and that information is ignored by the game, while that kind of information can be interpreted by decompiler after it was created by compiler. additional marking of START, END and TXTCODE (3 nops) will be also required for code that is extraordinary when compiling. nop1 for start of code, nop2 for end code and nop3 somewhere in script after jump (to avoid main part consumption). well but that is just an idea and i understand how unnecesary it might be. ignore that please.

 

ignore that, i have had an issue because my game crashed after i quit and dis not want to start again. did because i messed to much in memory.

 

edit: he i can imagine what happens with 2.0, deadly gravity hehe

 

EDIT2: listen, do not ignore that idea with txt code included in main.scm. what if you do that: i can write a mod then mark my code as "SPECIAL" and it decompiles it after all EXACTLY AS SOURCE- with custom labels, globals, and descriptions. you just place text code after jump when our special nop is there (within main.scm code). then decompile using this text and putting it between our 2 special nops. (even using one nop with several parameters). i think people can like have SOURCE after decompiling right? if the game accepts it of course.

Edited by PLPynton

Share this post


Link to post
Share on other sites
Seemann

 

i think people can like have SOURCE after decompiling right?

The decompiler don't even need for the special marks (nops or whatever) in the code to detect if there's an in-built source code. The compiler just adds the source and the offsets where the text has to be insterted and its length at very end of the file. That also save the space.

So, the decompiler checks that and inserts this plain text instead of the byte code (it wont even decompile it as there's a source ready-to-go, yes, just skip?).

Very easy.

 

But lets imagine: for example, I have two custom threads. I decide to include one of them as source in main.scm. But it uses custom variables and labels from another one. What happen: when the decompiler put the source, it still use such names, but those thread will have another names after the decompiling. So, that source will be uncompilable.

And to avoid that is too hard, I think. Ideas?

 

I think the using of such sources for now only necessary for the hex..end construct. I could make the compiler store all the hex insertions offsets and its length to allow then the decompiler parse them and it should solve the problem with the undecompilable sources.

 

 

 

added if line that was missing at the beginning

For the single ifs there's no need for 00D6. I just save some space in the main.scm

 

Is the compiled scm from the gravity.rar working for you?

Edited by Seemann

Share this post


Link to post
Share on other sites
SteaVor

Excellent work, Seemann, this is really useful and does work flawlessly for me - it even works with my German v1.0 exe! That's so great!

What's the best way to read a value from memory now?

Share this post


Link to post
Share on other sites
PLPynton

yes it can be decompiled but that does not proof why it can not on full game script. i see that it does not lead in any good direction, our further discussion about built in source. just forget it.

 

besides from me too: great work, EU 1.0 NoCD works

Edited by PLPynton

Share this post


Link to post
Share on other sites
Seemann

 

What's the best way to read a value from memory now?

I will write similar code for reading the data, but still don't know the best way how to pass the variable pointer where the read value will be stored

 

In theory it should be something like:

 

create_thread @MemoryProofRead address XXX size XXX variable_offset 20

 

And the code stores the value to variable $5.

 

But most likely I will use another way.

 

 

 

i see that it does not lead in any good direction, our further discussion about built in source. just forget it.

No, that’s good idea. I will implement it for the hex firstly, and when we'll see how that works - for the text sources.

 

 

Thanks for your feedbacks, guys.

 

Share this post


Link to post
Share on other sites
Seemann

Well, that's it:

 { -----------------------------------------------------------------  Memory Access Thread  to write a value with the specified length to the memory address  use  create_thread @MemoryProofWrite address X:DWord size X:BYTE value X:DWORD VirtualProtect X:BOOL   to read a value with the specified length by the memory address  use  create_thread @MemoryProofRead address X:DWord size X:BYTE VirtualProtect X:BOOL  The read value will be stored to the variable $MEMORY_PROOF_READ  The possible Size values: 1 (byte), 2 (word), 4 (dword)  The VirtualProtect parameter is optional----------------------------------------------------------------- }:[email protected] = @[email protected] == 1jf @_____novp:[email protected] = -429863&0([email protected],1i) =  0xA49960&0([email protected],1i) += @_____vpsv0052: gap 0 virtual_protect_at_address [email protected] size [email protected] newprotect 4 gap 0 00572: run_VPSV 1gosub [email protected]: gap 0 virtual_protect_at_address [email protected] size [email protected] newprotect -1 gap 0 00572: run_VPSV 1&0([email protected],1i) = 0end_thread:[email protected] = @[email protected] == 0jf @_____mpvp:_____novpgosub [email protected]_thread:[email protected] = -429864&0([email protected],1i) =  0xA49960&0([email protected],1i) += @_____mwss0052: gap 0 target_address [email protected] size [email protected] value [email protected] gap 0 00A3D: run_MWSS 1&0([email protected],1i) = 0return:[email protected] = -429864&0([email protected],1i) =  0xA49960&0([email protected],1i) += @_____mrmm02EC: run_MRMM 1 read_address [email protected] size [email protected] {store_to} 02 $MEMORY_PROOF_READend&0([email protected],1i) = 0return:_____vpsvhex68 F4 3C A4 00 83 3D 84 3C A4 00 FF75 08 FF 35 F4 3C A4 00 EB 06 FF 3584 3C A4 00 FF 35 80 3C A4 00 FF 357C 3C A4 00 FF 15 2C 80 85 00 C3end:_____mwsshex8B 15 7C 3C A4 00 8B 05 84 3C A4 008B 0D 80 3C A4 00 83 F9 01 75 03 8802 C3 83 F9 02 75 04 66 89 02 C3 8902 C3end:_____mrmmhex31 C0 BA 78 3C A4 00 89 02 8B 0D 803C A4 00 8B 05 7C 3C A4 00 83 F9 0175 05 8A 00 88 02 C3 83 F9 02 75 0766 8B 00 66 89 02 C3 8B 00 89 02 C3              end{ ---------end of memory access thread----------------------------- }

That thread is the more complex way of getting memory access. For some cases you may need for something shorter. Feel free to modify it.



Example: decrease a gravity for 5 sec, then restore to normal

create_thread @MemoryProofRead  address 0x863984 size 4 VirtualProtect 1wait 0create_thread @MemoryProofWrite address 0x863984 size 4 value 0.002 VirtualProtect 1wait 5000create_thread @MemoryProofWrite address 0x863984 size 4 value $MEMORY_PROOF_READ VirtualProtect 1


edit: optimized mrmm

edit2: fixed CODE tags

Edited by Seemann

Share this post


Link to post
Share on other sites
Seemann

That's the multiversion of the memory access thread.

You could pass two addresses: one for v1, second for v1.01. The code detects what version is running now and works with that correctly.

Parameters:

   create_thread @MemoryProofMultiWrite/Read address for v1.0 (X:DWord) address for v1.01 (X:DWord) size (X:BYTE) value (X:DWORD) VirtualProtect (X:BOOL)



 { -----------------------------------------------------------------  Memory Access Thread  MultiVersion :: supports GTA SA v1 and v1.01  to write a value with the specified length to the memory address  use  create_thread @MemoryProofMultiWrite address for version1 X:DWord address for version1.01 X:DWord size X:BYTE value X:DWORD VirtualProtect X:BOOL  Example:  create_thread @MemoryProofMultiWrite address_V1 0xC0BC15 address_V2 0xC0E295 size 1 value 1   to read a value with the specified length by the memory address  use  create_thread @MemoryProofMultiRead address for version1 X:DWord address for version1.01 X:DWord size X:BYTE VirtualProtect X:BOOL   The read value will be stored to the variable $MEMORY_PROOF_READ   Example:  create_thread @MemoryProofMultiRead address_V1 0x863984 address_V2 0 size 4 VirtualProtect 1  The possible Size values: 1 (byte), 2 (word), 4 (dword)  The VirtualProtect parameter is optional----------------------------------------------------------------- }:MemoryProofMultiWritegosub @[email protected] = @[email protected] == 1jf @_____novp:_____mpvp0085: [email protected] = [email protected]([email protected],2i)008A: &0([email protected],1i) = [email protected]([email protected],2i)005E: &0([email protected],1i) += [email protected]([email protected],2i)0052: gap 0 virtual_protect_at_address [email protected]([email protected],2i) size [email protected] newprotect 4 gap 0 00572: run_VPSV 1gosub [email protected]: gap 0 virtual_protect_at_address [email protected]([email protected],2i) size [email protected] newprotect -1 gap 0 00572: run_VPSV 1&0([email protected],1i) = 0end_thread:MemoryProofMultiReadgosub @[email protected] = @[email protected] == 0jf @_____mpvp:_____novpgosub [email protected]_thread:MemoryWrite0085: [email protected] = [email protected]([email protected],2i)008A: &0([email protected],1i) = [email protected]([email protected],2i)005E: &0([email protected],1i) += [email protected]([email protected],2i)0052: gap 0 target_address [email protected]([email protected],2i) size [email protected] value [email protected] gap 0 00A3D: run_MWSS 1&0([email protected],1i) = 0return:MemoryRead0085: [email protected] = [email protected]([email protected],2i)008A: &0([email protected],1i) = [email protected]([email protected],2i)005E: &0([email protected],1i) += [email protected]([email protected],2i)02EC: run_MRMM 1 read_address [email protected]([email protected],2i) size [email protected] {store_to} 02 $MEMORY_PROOF_READend&0([email protected],1i) = 0return:[email protected] = -429566&0([email protected],1i) == 4611680jf @_____gsvo012 // 1.0//    [email protected]  = 0   [email protected] = -429863   [email protected] = -429864   [email protected] = 0xA49960   [email protected] = @_____vpsv   [email protected] = @_____mwss   [email protected] = @_____mrmmreturn:_____gsvo012    // 1.01   [email protected]  = 1   [email protected] = -431117   [email protected] = -431118   [email protected] = 0xA4BFE0   [email protected] = @_____vpsv2   [email protected] = @_____mwss2   [email protected] = @_____mrmm2    return:_____vpsv2hex68 74 63 A4 00 83 3D 04 63 A4 00 FF75 08 FF 35 74 63 A4 00 EB 06 FF 3504 63 A4 00 FF 35 FC 62 A4 00 FF 35F8 62 A4 00 FF 15 2C 90 85 00 C3end:_____vpsvhex68 F4 3C A4 00 83 3D 84 3C A4 00 FF75 08 FF 35 F4 3C A4 00 EB 06 FF 3584 3C A4 00 FF 35 80 3C A4 00 FF 357C 3C A4 00 FF 15 2C 80 85 00 C3end:_____mwss2hex8B 15 FC 62 A4 00 8B 05 04 63 A4 008B 0D 63 00 A4 00 EB 12end:_____mwsshex8B 15 7C 3C A4 00 8B 05 84 3C A4 008B 0D 80 3C A4 00 83 F9 01 75 03 8802 C3 83 F9 02 75 04 66 89 02 C3 8902 C3end:_____mrmm2hex31 C0 BA F8 62 A4 00 89 02 8B 0D 0063 A4 00 8B 05 FC 62 A4 00 EB 15end:_____mrmmhex31 C0 BA 78 3C A4 00 89 02 8B 0D 803C A4 00 8B 05 7C 3C A4 00 83 F9 0175 05 8A 00 88 02 C3 83 F9 02 75 0766 8B 00 66 89 02 C3 8B 00 89 02 C3              end{ ---------end of memory access thread----------------------------- }





Example: how to remove the message showed when Carl first time stealing a car in the both versions

 create_thread @MemoryProofMultiWrite address_V1 0xC0BC15 address_V2 0xC0E295 size 1 value 1
Edited by Seemann

Share this post


Link to post
Share on other sites
Y_Less

I did post a thing a long time ago on hacking based almost entirely on CyQ's method before the stats method was discovered (using the set_player_handling hack), I even found an unused OpCode on an accessible boundary for the write and another unused OpCode nearby for the read, unfortunately I never got it working, although I never tried amazingly hard, but yeah, I posted what I had in Demarest's mem hacking revisited topic, but well done for getting this working.

 

Also, ceedj, no offence but what's the point of doing that from C++ when you already have a perfectly good handle into memory?

 

Edit, link to my original SA mem hacking stuff: http://www.gtaforums.com/index.php?showtop...dpost&p=3863930

 

Also, it's great to see people still continuing all the work like this.

Edited by Y_Less

Share this post


Link to post
Share on other sites
ceedj

None taken buddy. As some people know, I am teh suk on memory stuff, so the patch method was a nice, easy way to get what I want. Just recently however, I think I figured out how the function works that op9080 set up for the gravity controls and the various speed/height patches. There was also the issue of controlling it, as with over 100+ keychecks, finding a spot for another one was tricky.

 

Also bear in mind when I started working with these "hooks" I had NO idea how to program with C++. Some would say I still don't; have a look at Spookie's SCM mod thread here somewhere and watch random_download try to explain asm stuff to me. I, of course, failed spectacularly, but that's another story. wink.gif

 

@Seemann: at the risk of exposing myself further as the true GTAF-Idiot, I have to ask: is the asm code for that (in SB) a "standard" piece of code? In other words, will I just be able to copy that part and just use the "create_thread" command to do my memory stuff? Although I DO use a hook for most of my SA stuff, I can think of a number of situations where I could have more than one running thread (can't do that with the hooks) and I've even tinkered around with a hybrid setup; using the hook for the keys/selection process and using MB/SB for everything else. Just curious. And BTW, AWESOME JOB coming up with this. You people are friggin genuises. smile.gif

Share this post


Link to post
Share on other sites
Seemann

 

is the asm code for that (in SB) a "standard" piece of code?

Yes, but using only the hex insertions is not enough to handle the memory. The whole thread deals with that: one part loads the parameters to the memory, another one runs the asm code. You should copy one of those threads (for v1 only or multiversion thread, as you wish) anywhere to the MAIN and begin to use it with 004F.

 

 

Btw, I know the way how to check via the scripts if ANY keyboard key is pressed (I mean ANY key except ESC and PrintScreen ones). Other keys could be checked very easy and it removes the 00E1 opcode limit which allows to check only about 20 pre-defined keys.

 

Interested?

Edited by Seemann

Share this post


Link to post
Share on other sites
ceedj

RE: Thread - yeah, that's what I was wondering about. In my case, using the multiversion thread you posted would be better yes. This is probably a few months away (I'm neck-deep in wrapping the second season), but I LOVE getting answers to possible questions early. Makes my life a whole lot nicer in the end. wink.gif

 

RE: Keypresses - Hmmm. Let's say yes, and we'll see if I can implement it.

 

Is this related to what Y_Less discussed sometime ago about making your own cheats, or something totally different?

 

Thanks for the heads up buddy! smile.gif

Share this post


Link to post
Share on other sites
Y_Less

If you can hook the keypress reader then you can see if a certain sequence of keys is pressed and then act upon it. That action may be something to improve the players stats/situation at that time and it may also display a text box. So yes, creating your own cheats is very possible. You can also do things like text entry and faking GXTs, although I was looking into faking GXTs in SA the other day for unrelated reasons but I'm not sure how to do it atm, it was easy in VC to track down, SA isn't so easy sad.gif.

 

Anyway, yes, it is possible.

Share this post


Link to post
Share on other sites
Y_Less

SA cheat processor. To prove the point I've written said cheat processor and designed it to be as easy to use as possible. It uses a very slightly modified version of the mem hacking code to allow it to be called directly or through a create_thread, but this is entirely backwards compatible (basically, if you call it via create_thread just do as you normally would, if you create it directly first set [email protected] and [email protected] to 1 ([email protected] is the internal marker to return instead of end_thread but [email protected] passes that fact in MemoryProofRead as there's one less parameter)).

 

I don't know what Seemann's method of getting the keys is but this just reads a pool of last pressed letters at 0x969110, this means we don't need to save the code as they enter it but does mean it's limited a bit.

 

To create a new cheat simply do:

 

 

create_thread @CHEAT_PROCESSOR @CHEAT_CODE_LABEL

 

 

Then create your cheat code at :CHEAT_CODE_LABEL

 

 

:CHEAT_CODE_LABEL0661: set_cheat_text "ACTIVATE"03E5: show_text_box 'HELP101'return

 

 

The 0661 OpCode sets the text required to be typed to activate the cheat (the processor reads this itself and acts accordingly). The rest of the section is the code run when the cheat is entered and the return is required instead of an end_thread or other thing.

 

Also note that in your cheat code [email protected] [email protected] and [email protected] are strictly forbidden, using them will break the cheat!

 

The full cheat processor code (including modified SINGLE version memory access code):

 

 

{ ----------------------------------------------------------------- Cheat Processor Thread To create your own thread simply call this, passing the cheat's processing label as a parameter. Then set the first command in the cheat to:  0661: set_cheat_text "<string to trigger the cheat>"  (much like a name_thread but for a cheat)  This string can be up to 255 characters but must be entirely capital letters, no other characters at all (spaces, numbers etc)  Also, your cheat thread must be ended with a return, not an end thread (unless you want it to be fire once only)----------------------------------------------------------------- }:CHEAT_PROCESSOR0085: [email protected] = [email protected]@ += 0xA49963 // SCM offset + [email protected] = 1 // [email protected] = 0 // virtual [email protected] = 1 // return, don't endgosub @MemoryProofRead008B: [email protected] = [email protected] += 4005A: [email protected] += [email protected]@ = 0{   [email protected] should now hold the length of the string and nothing more   I REALLY wish we could do && and >> in SCM   maybe this could be converted to ASM for uber ease...      Important variables at this point:   [email protected]@ - reserverd for processing    [email protected] - real cheat label   [email protected] - string length   [email protected] - old first DWORD of character table      Other notes:   9867536 - decimal offset of some character table}:CP_MAIN_LOOPwait [email protected] = [email protected] = [email protected] = [email protected] = 1gosub @MemoryProofRead803C: $MEMORY_PROOF_READ != [email protected] @CP_MAIN_LOOP  008B: [email protected] = $MEMORY_PROOF_READ [email protected] = [email protected] = 0:CP_STRCMP802D: [email protected] < [email protected] // (!>=)jf @[email protected] = 0x969110005A: [email protected] += [email protected] @MemoryProofRead008B: [email protected] = $MEMORY_PROOF_READ0085: [email protected] = [email protected]@ += 0xA4995F // SCM offset - 10062: [email protected] -= [email protected] @MemoryProofRead003C: $MEMORY_PROOF_READ == [email protected] jf @[email protected] += 1jump @CP_STRCMP:CP_SUCCESSgosub [email protected]// Display cheat message03E5: text box "CHEAT1"[email protected] = [email protected] = [email protected] = [email protected] = [email protected] = 1// Mark as having cheatedgosub @[email protected] = 0xBAA472gosub @MemoryProofWrite// Increase cheat [email protected] = [email protected] = [email protected] = 1gosub @MemoryProofRead008B: [email protected] = [email protected] += [email protected] = 0gosub @MemoryProofWrite:CP_FAILUREjump @CP_MAIN_LOOP { ----------------------------------------------------------------- Memory Access Thread to write a value with the specified length to the memory address  use create_thread @MemoryProofWrite address X:DWord size X:BYTE value X:DWORD VirtualProtect X:BOOL to read a value with the specified length by the memory address  use create_thread @MemoryProofRead address X:DWord size X:BYTE VirtualProtect X:BOOL The read value will be stored to the variable $MEMORY_PROOF_READ The possible Size values: 1 (byte), 2 (word), 4 (dword) The VirtualProtect parameter is optional----------------------------------------------------------------- }:[email protected] = @[email protected] == 1jf @_____novp:[email protected] = -429863&0([email protected],1i) =  0xA49960&0([email protected],1i) += @_____vpsv0052: gap 0 virtual_protect_at_address [email protected] size [email protected] newprotect 4 gap 0 00572: run_VPSV 1gosub [email protected]: gap 0 virtual_protect_at_address [email protected] size [email protected] newprotect -1 gap 0 00572: run_VPSV 1&0([email protected],1i) = [email protected] == 0jf @MemoryReturnend_thread:[email protected] = @MemoryRead0085: [email protected] = [email protected]@ == 0jf @_____mpvp:_____novpgosub [email protected]@ == 0jf @MemoryReturnend_thread:[email protected] = -429864&0([email protected],1i) =  0xA49960&0([email protected],1i) += @_____mwss0052: gap 0 target_address [email protected] size [email protected] value [email protected] gap 0 00A3D: run_MWSS 1&0([email protected],1i) = 0return:[email protected] = -429864&0([email protected],1i) =  0xA49960&0([email protected],1i) += @_____mrmm02EC: run_MRMM 1 read_address [email protected] size [email protected] {store_to} 02 $MEMORY_PROOF_READend&0([email protected],1i) = 0return:MemoryReturn0051: return:_____vpsvhex68 F4 3C A4 00 83 3D 84 3C A4 00 FF75 08 FF 35 F4 3C A4 00 EB 06 FF 3584 3C A4 00 FF 35 80 3C A4 00 FF 357C 3C A4 00 FF 15 2C 80 85 00 C3end:_____mwsshex8B 15 7C 3C A4 00 8B 05 84 3C A4 008B 0D 80 3C A4 00 83 F9 01 75 03 8802 C3 83 F9 02 75 04 66 89 02 C3 8902 C3end:_____mrmmhex31 C0 BA 78 3C A4 00 89 02 8B 0D 803C A4 00 8B 05 7C 3C A4 00 83 F9 0175 05 8A 00 88 02 C3 83 F9 02 75 0766 8B 00 66 89 02 C3 8B 00 89 02 C3              end{ ---------end of memory access thread----------------------------- }

 

 

And a few pointless little 'cheats':

 

 

create_thread @CHEAT_PROCESSOR @HEALTH_CHEATcreate_thread @CHEAT_PROCESSOR @CAR_CHEAT

 

 

 

:HEALTH_CHEAT0661: set_cheat_text "HELLO"0256:   player $PLAYER_CHAR definedjf @HEALTH_CHEAT_END03E5: show_text_box 'HELP101'  // Respect can be earned be passing certain missions, killing rival gangs members, gaining territory and tagging.08AF: set_actor $PLAYER_ACTOR max_health_to 2550223: set_actor $PLAYER_ACTOR health_to 255 00A0: store_actor $PLAYER_ACTOR position_to [email protected] [email protected] [email protected]@ += 100.000A1: put_actor $PLAYER_ACTOR at [email protected] [email protected] [email protected]:HEALTH_CHEAT_ENDreturn// Spawns a car:CAR_CHEAT0661: sat_cheat_text "BURN"0256:   player $PLAYER_CHAR definedjf @CAR_CHEAT_END 0247: load_model #INFERNUS038B: load_requested_models:CAR_CHEAT_LOADwait 00248:   model #INFERNUS availablejf @CAR_CHEAT_LOAD 00A0: store_actor $PLAYER_ACTOR position_to [email protected] [email protected] [email protected]@ += 5.000A5: [email protected] = create_car #INFERNUS [email protected] [email protected] [email protected]: release_model #INFERNUS:CAR_CHEAT_ENDreturn; 

 

 

IMPORTANT (AGAIN):

 

DO NOT USE [email protected], [email protected] OR [email protected] IN YOUR CODE!

 

PS: Seemann, after reading your code I learnt about the missing if statement trick for 1 big statements, cheers.

 

Edit: added a bit to the success label, they now behave exactly like real cheats, including displaying the text box and making the game complain when you try save smile.gif.

 

Edit 2: do you think you could modify these so the initial writing installs the ASM over existing unused OpCodes, instead of reusing existing one. Obviously use that initially but then have that write other OpCode pointers to point at the data so writing memory becomes as easy as:

 

0D1E: write_memory 0x01234567 size 1 data [email protected] protect 1

01DF: [email protected] = read_memory $SOME_LABEL size 4 protect 0

 

(0D1E is my example unknown OpCode for obvious reasons smile.gif)

 

Shouldn't be too hard to fake the correct OpCode code syntax (that's what I was trying to do originally). Plus it shouldn't be too hard to adjust based on the EXE if you know a constant address in both to use and an address different on both to tell which they're using.

Edited by Y_Less

Share this post


Link to post
Share on other sites
Seemann

 

Is this related to what Y_Less discussed sometime ago about making your own cheats, or something totally different?

No, it's nothing about cheats (essentially, I posted my way of the cheats creating on the first post). It's a checking of the keypresses via the memory addresses. I will post this later.

 

Edit: custom keypresses

 

 

you can also do things like text entry and faking GXTs, although I was looking into faking GXTs in SA the other day for unrelated reasons but I'm not sure how to do it atm, it was easy in VC to track down, SA isn't so easy

Well, I did that. I have a subroutine to change the existing GXT entries in run-time on my own text.

I could post that later too.

 

 

do you think you could modify these so the initial writing installs the ASM over existing unused OpCodes, instead of reusing existing one

If you mean to do that via the mission scripts (like all in this topic), I should say: there IS a possible way to create a fake opcodes handler and add a hundred of the fake opcodes in range of [0A8C .. 0AEF] doing whatever we want (i like the idea with OD1E but sadly thats impossible). Other opcodes could only be changed with the EXE editing, not in run-time.

 

But please say, what actually we get from this? We will force then to reuse the fake opcode handler activation in order the added opcodes to work every time the game loads. Why not use the Xieons patch which added such opcodes then?

 

Btw, I did not change any opcodes in MemoryProof, those 0052 and 02EC are NOPs and I used them only as a good way to load the parameters into the memory (the hex reads the OpcodeParameters[32] array which address is well-known).

 

 

 

Also, in addition of using the MemoryProof: the size parameter is not necessary when it is equals to 4. In other words, DWORD size is default. If you get an access without VirtualProtect you may not specify the size parameter as well:

 

 

create_thread @MemoryProofRead address 100

 

this will read 4 bytes from the mem addy 100.

 

 

And dont forget to add a wait command after using 004F in order a new thread to be created immediately.

Edited by Seemann

Share this post


Link to post
Share on other sites
Y_Less

I'm not sure if that whole post was directed at me but anyway.

 

 

Is this related to what Y_Less discussed sometime ago about making your own cheats, or something totally different?

No, it's nothing about cheats (essentially, I posted my way of the cheats creating on the first post). It's a checking of the keypresses via the memory addresses. I will post this later.

 

Edit: custom keypresses

 

You do know that was the point of my whole last post? tounge.gif

 

 

you can also do things like text entry and faking GXTs, although I was looking into faking GXTs in SA the other day for unrelated reasons but I'm not sure how to do it atm, it was easy in VC to track down, SA isn't so easy

Well, I did that. I have a subroutine to change the existing GXT entries in run-time on my own text.

I could post that later too.

 

Interesting, I've been doing unrelated work on GXT memory recently and although I've been unable to create my own (for some reason changing the pointer to your own block of CRC names and pointers doesn't seem to work, but changing individual string pointers does, though is obviously less flexible.

 

 

do you think you could modify these so the initial writing installs the ASM over existing unused OpCodes, instead of reusing existing one

If you mean to do that via the mission scripts (like all in this topic), I should say: there IS a possible way to create a fake opcodes handler and add a hundred of the fake opcodes in range of [0A8C .. 0AEF] doing whatever we want (i like the idea with OD1E but sadly thats impossible). Other opcodes could only be changed with the EXE editing, not in run-time.

 

But please say, what actually we get from this? We will force then to reuse the fake opcode handler activation in order the added opcodes to work every time the game loads. Why not use the Xieons patch which added such opcodes then?

 

CyQs original VC hack thing changed the pointers for two OpCodes, one for read mem, the other for write mem to make them easier to use, plus it's all SCM based, but it's not essential.

 

 

Btw, I did not change any opcodes in MemoryProof, those 0052 and 02EC are NOPs and I used them only as a good way to load the parameters into the memory (the hex reads the OpcodeParameters[32] array which address is well-known).

 

 

 

Also, in addition of using the MemoryProof: the size parameter is not necessary when it is equals to 4. In other words, DWORD size is default. If you get an access without VirtualProtect you may not specify the size parameter as well:

 

 

create_thread @MemoryProofRead address 100

 

this will read 4 bytes from the mem addy 100.

 

 

And dont forget to add a wait command after using 004F in order a new thread to be created immediately.

 

I didn't use create_thread to access memory, I called your functions directly setting the correct locals first (and it does work).

Share this post


Link to post
Share on other sites
Seemann

 

You do know that was the point of my whole last post?

Well, I think yes smile.gif You made the SCM-based cheat processor using modified MemProof. But to be fair that differs from the thing I posted there, isn't it? wink.gif

 

 

CyQs original VC hack thing changed the pointers for two OpCodes, one for read mem, the other for write mem to make them easier to use, plus it's all SCM based, but it's not essential.

That was possible in VS as the opcodes pointers were stored as simple changeable DATA. In SA these pointers are the CODE thing (the part of the exe functions), and they can NOT be changed in run-time, as it is the part of executed code.

 

 

I didn't use create_thread to access memory, I called your functions directly setting the correct locals first (and it does work).

Sure, that’s what I mean when said: you could modify the code to make it simpier and easier in use for your purpose.

 

 

 

Share this post


Link to post
Share on other sites
Bigun

Hey (bump!).

I've tried to modify the CLV thread to take parameters, so you can easily modify any thread's any local var. Not very surprisingly, it crashes (I'm pretty clueless about anything memory-related confused.gif ). So I need help with this, and any related info I should know, please.

I've narrowed the crash down to the first 008B opcode; I guess it may have to do with that ADMA (&) thing, which I've no idea what I should do with. Took a shot in changing &0 to &3 like the local var, but that wasn't it.

 

Heres the code, including the test thread:

:CLV //[email protected] == thread_name, [email protected] == local var num to modify, [email protected] value to set to var03A4: name_thread 'CLV' 0006: [email protected] = 67251 :CLV_LOOP 008B: [email protected] = &0([email protected],1i)00D6: if8039:   not  [email protected] == 0004D: jump_if_false @CLV_END0001: wait 0 ms0085: [email protected] = [email protected]: [email protected] /= 8000E: [email protected] -= 13483950016: [email protected] /= 4000E: [email protected] -= 269679200D6: if05AD:   &0([email protected],1s) == [email protected]: jump_if_false @CLV_LOOP//add to [email protected] (local var num + 15)000A: [email protected] += 15 005A: [email protected] += [email protected] // integer values // 3333 is a new value of the local//0004: &0([email protected],1i) = 3333 //global=int008A: &0([email protected],1i) = [email protected] // integer values and handles :CLV_END004E: end_thread// -------------------------------------------:debug_var_testthread 'VCHNG'[email protected] = 2create_thread @CLV thread_name 'vchng' local_num 2 set_value 10wait 2000054C: use_GXT_table 'POOL'01E3: text_1number_styled 'NUM' [email protected] 5000 ms 1  // ~1~end_thread

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


  • 1 User Currently Viewing
    0 members, 0 Anonymous, 1 Guest

×
×
  • Create New...

Important Information

By using GTAForums.com, you agree to our Terms of Use and Privacy Policy.