Jump to content

[SA] Memory access via stat opcodes


Recommended Posts

Stat 64412 PROCEDURAL OBJECT GENERATION TABLE DEFINITION 64422:18x4b per cell

 

example breakdown (full) of object 000 (sjmcacti2 by the means of original game):

 

Stat 64422 PROCEDURAL_OBJECT -000 SURFACE TYPE

Stat 64423 PROCEDURAL_OBJECT -000 OBJECT NAME

Stat 64424 PROCEDURAL_OBJECT -000 AVERAGE SPACING

Stat 64425 PROCEDURAL_OBJECT -000 DENSITY [x/sqm]

Stat 64426 PROCEDURAL_OBJECT -000 MINIMUM DISTANCE [x^2]

Stat 64427 PROCEDURAL_OBJECT -000 MINIMUM ROTATION [RAD]

Stat 64428 PROCEDURAL_OBJECT -000 MAXIMUM ROTATION [RAD]

Stat 64429 PROCEDURAL_OBJECT -000 MINIMUM SCALE XY

Stat 64430 PROCEDURAL_OBJECT -000 MAXIMUM SCALE XY

Stat 64431 PROCEDURAL_OBJECT -000 MINIMUM SCALE Z

Stat 64432 PROCEDURAL_OBJECT -000 MAXIMUM SCALE Z

Stat 64433 PROCEDURAL_OBJECT -000 MINIMUM Z OFFSET

Stat 64434 PROCEDURAL_OBJECT -000 MAXIMUM Z OFFSET

Stat 64435 PROCEDURAL_OBJECT -000 b1=ALIGN

Stat 64436 PROCEDURAL_OBJECT -000 USE GRID [sq base in m]

Stat 64437 PROCEDURAL_OBJECT -000 UNUSED

Stat 64438 PROCEDURAL_OBJECT -000 UNUSED

Stat 64439 PROCEDURAL_OBJECT -000 UNUSED

end

 

here is last object for our stat range:

 

Stat 65520 PROCEDURAL_OBJECT -060 SURFACE TYPE

 

and under that virtual stat is last object used in game and there is a memory space for few more:

Stat 66144 PROCEDURAL_OBJECT -093 SURFACE TYPE

Edited by PLPynton
  • 3 weeks later...

As the way of using stats to gain memory access is seriously limited, I'd like to suggest alternate way.

That's pretty clear and simple method which is based on SA arrays.

 

The original idea was told by Y_Less there, so all credits goes to him.

The main thing is that the array indexes can contain 32-bit integer values that gives us an access to ANY in-game address in ranges 0x00000000..0xFFFFFFFF.

 

There is an example how to increment player's money by $150 via arrays (bit useless because of 0109, but very easy to see that it works)

 

(SB example):

 

...0@ = 0xB7CE50 // memory address to readgosub @MemoryRead // get current money to 1@1@ += 1500@ = 0xB7CE50gosub @MemoryWrite // set new money value from 1@...// --------------------:MemoryWrite 0@ -= 0xA49960 0@ /= 4 // now 0@ contains the value which after array's parsing will point to the memory address that we specified 008A: &0(0@,1i) = 1@return:MemoryRead 0@ -= 0xA49960 0@ /= 4 008B: 1@ = &0(0@,1i)return

 

 

in SAMB this method will work too but small changes are necessary.

 

P.S. However, there are still one limit. Not every memory address could be re-written by this, because of Access Violation Error. So, the using of Xieon's patch remains the best solution so far.

 

 

 

Whoops, just realized I posted this in the worng topic. Sorry guys; I'm referring to Xieon's patch. Thanks.

 

No problem, it isn't really off-topic here. And maybe it's better than bumping that topic for that.

 

 

Does anyone have a working copy of this .rar they can send me? The one from the top post comes up as corrupted.

 

Actually, it works for me. When you click that link, you need to click on "/mempatch.rar". Actually, right-click and choose "Save Target As" etc (using Firefox, when I initially just clicked the link it opened the rar in FF showing the text biggrin.gif).

 

Also, Xieon's patch and INI code converter are included in the latest SB download. turn.gif

 

Does anyone have a working copy of this .rar they can send me? The one from the top post comes up as corrupted.

 

That's the link

I realized that the way of changing memory I described above (through the arrays) is working only when you change memory value with 32-bit value (dword). But if you need change the only byte (or word) and use this way it also rewrites the neighbour bytes.

 

Though, to change the byte in game memory you need

 

1. Read memory address (you get DWORD value)

2. Change ITS byte(-s) using set_bit, clear_bit opcodes; so you will change only specified bytes

3. Rewrite the whole address with the new value

 

The main thing is that we do not change any bytes except those needed to be changed.

 

 

// 0@ -address// 2@ -new value// 3@ -length (in bytes)//--write specified number of bytes into memory:MemoryWrite    0085: 5@ = 0@ 0@ /= 4 0@ *= 4           // memory address 0062: 5@ -= 0@    // offset (0, 1, 2, 3)  :_GetInitValue      // if you specify mem offset in 5@, you're able to gosub here gosub @MemoryRead // get initial value 3@ *= 8 // bytes -> bits 5@ *= 8 dec(3@) for 6@ = 0 to 3@   if     08B6: test 2@ bit 6@    then     08BF: set 1@ bit 5@    // 1   else     08C5: clear 1@ bit 5@  // 0   end    inc(5@) // next memory bit end     008A: &0(0@,1i) = 1@  // write new value return//--write 32-bit value into memory-----------:MemoryWrite32bit 0@ -= 0xA49960 0@ /= 4 008A: &0(0@,1i) = 1@   return//--read 32-bit value from memory-----------:MemoryRead 0@ -= 0xA49960 0@ /= 4 008B: 1@ = &0(0@,1i)return//-------------------------------------------

 

 

So, example of using that. It shows how to remove annoying text box saying "To stop Carl..." when the player first time stealing a car:

 

 

...0@ = 0xC0BC15 //  ADDRESS2@ = 1        //  VALUE3@ = 1        //  LENGTH (Byte)gosub @MemoryWrite....

 

 

random_download
I tried doing that in VC once. Even though I was only changing the one byte, I was crashing the game. I'm assuming that's because I was also trying to write to read-only bytes? Not sure, but not once was I able to get it to work confused.gif

I think writing to read-only values would just mean that they don't get written to (ie. nothing happens). The game would crash however if you write to an address that doesn't exist.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • 0 User Currently Viewing
    0 members, 0 Anonymous, 0 Guests

×
×
  • Create New...

Important Information

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