Mac Gold Limit Editing
Moderator: Contrail
-
- Posts: 15
- Joined: Tue Jun 18, 2002 7:43 pm
Mac Gold Limit Editing
I've been tinkering around with the Mac D2 Carbon Application to modify the gold limit, trying to bring it inline with Windows Eastern Sun.
I've successfully quadrupled the stash limit. Ten million at clvl 100. It's done in a round about way though. 50k/clvl +5 million base. The reason for this is that I only edited the programmed calculation from (clvl/2 +1)*50k to (clvl/1 +100)*50k. I don't know enough about the structure of the code to make the equation into clvl*2*50k.
The offset for the code that controls the stash gold limit is 1942400 or so. If you take a look with a hex editor around that offset, you will see two "c350" which is hex for 50k. There are two because there are two equations for gold stash limits. One is for level 30 and under, and the other for 31+. Unfortunately, this value can't simply be changed to 200k as it is a 2-byte value.
Changing offset 1942401 from 04 to 06 changed the equation from clvl/2 to clvl/1. Offset 1942411 is the byte controlling the +X in the equation.
I only figured this out by changing different bytes to different values, loading D2(if the change doesn't make it crash) and checking how it affected the stash size. I would imagine that the change at 1942401 is a code change and not a data change (as opposed to say, the 1942411 change). Theoretically, one could make the right change to give the linear limit of clvl*4*50k. Again, I don't know enough about the structure to do that. Any Ideas?
I've also doubled the inventory gold limit. It is controlled at offset 1944958. Unfortunately, this is a signed value, or it would be very easy to quadruple the original 10k value to bring it in line with Windows ES. I think quadrupling would require a code change that I don't know how to do yet.
I've successfully quadrupled the stash limit. Ten million at clvl 100. It's done in a round about way though. 50k/clvl +5 million base. The reason for this is that I only edited the programmed calculation from (clvl/2 +1)*50k to (clvl/1 +100)*50k. I don't know enough about the structure of the code to make the equation into clvl*2*50k.
The offset for the code that controls the stash gold limit is 1942400 or so. If you take a look with a hex editor around that offset, you will see two "c350" which is hex for 50k. There are two because there are two equations for gold stash limits. One is for level 30 and under, and the other for 31+. Unfortunately, this value can't simply be changed to 200k as it is a 2-byte value.
Changing offset 1942401 from 04 to 06 changed the equation from clvl/2 to clvl/1. Offset 1942411 is the byte controlling the +X in the equation.
I only figured this out by changing different bytes to different values, loading D2(if the change doesn't make it crash) and checking how it affected the stash size. I would imagine that the change at 1942401 is a code change and not a data change (as opposed to say, the 1942411 change). Theoretically, one could make the right change to give the linear limit of clvl*4*50k. Again, I don't know enough about the structure to do that. Any Ideas?
I've also doubled the inventory gold limit. It is controlled at offset 1944958. Unfortunately, this is a signed value, or it would be very easy to quadruple the original 10k value to bring it in line with Windows ES. I think quadrupling would require a code change that I don't know how to do yet.
-
- Paladin
- Posts: 169
- Joined: Sun Jul 13, 2003 1:37 am
- Location: Austin, TX
Re: Mac Gold Limit Editing
I'll take a look at those areas when I get home tonight, I'll most likely be able to figure out how to change the calculation for the stash gold limit at least. The inventory gold limit may be more difficult to deal with, depending on how the code that deals with it works.
ETA:
Okay, I've sucessfully made the stash gold limit quadruple what it was while going up at the same rate as the original version, although after level 30 it goes up by 100,000 each level instead of 200,000 every two levels.
First, the original code that gets the stash gold limit, with a few annotations. This is taken from the 1.10b version of Diablo II (Carbon).
Now, my revised version, which I had to add an extra instruction to that multiplies the value by 4 for the calculation for levels 30 and below:
Also, I checked the Eastern Sun database site, and it actually says that the inventory gold stash is only doubled for that mod, so just changing 10,000 to 20,000 should work.
The necessary change, for completeness' sake:
Careyagimon, thank you for making the original post with the offsets, they were very helpful in allowing me to find and change this code. The function that is used by the stash gold limit function to get the level looks to be one of the functions that gets stats in general, which will be a very useful function to know the location of.
If anyone wants a more detailed explanation of what the code is doing, I'll do my best to provide one, although I'm not an expert on PowerPC assembler by any means.
- Contrail
ETA:
Okay, I've sucessfully made the stash gold limit quadruple what it was while going up at the same rate as the original version, although after level 30 it goes up by 100,000 each level instead of 200,000 every two levels.
First, the original code that gets the stash gold limit, with a few annotations. This is taken from the 1.10b version of Diablo II (Carbon).
Code: Select all
001da350: 7c0802a6 mflr r0
001da354: 3880000c li r4,12 - Passes 12 as an argument to the next function
001da358: 90010008 stw r0,8(SP)
001da35c: 38a00000 li r5,0 - Passes 0 as an argument to the next function
001da360: 9421ffc0 stwu SP,-64(SP)
001da364: 4800fe6d bl 0x1ea1d0 - Function call that return the player's level in r3
001da368: 60000000 nop
001da36c: 2c03001e cmpwi r3,30 - compares the player's level to 30
001da370: 40810024 ble- 0x1da394 - If level <= 30 we skip down to 0x1da394
001da374: 54600ffe rlwinm r0,r3,1,31,31
001da378: 3c800001 lis r4,1
001da37c: 7c001a14 add r0,r0,r3
001da380: 7c030e70 srawi r3,r0,1
001da384: 3804c350 subi r0,r4,15536 - mullw treats this as an unsigned value
001da388: 38630001 addi r3,r3,1
001da38c: 7c6301d6 mullw r3,r3,r0
001da390: 4800002c b 0x1da3bc - Skips the branch for level <= 30
001da394: 3ca06666 lis r5,26214
001da398: 3c800001 lis r4,1
001da39c: 38056667 addi r0,r5,26215
001da3a0: 7c601896 mulhw r3,r0,r3
001da3a4: 3804c350 subi r0,r4,15536
001da3a8: 7c631670 srawi r3,r3,2
001da3ac: 54640ffe rlwinm r4,r3,1,31,31
001da3b0: 7c632214 add r3,r3,r4
001da3b4: 38630001 addi r3,r3,1
001da3b8: 7c6301d6 mullw r3,r3,r0
001da3bc: 80010048 lwz r0,72(SP)
001da3c0: 38210040 addi SP,SP,64
001da3c4: 7c0803a6 mtlr r0
001da3c8: 4e800020 blr
001da3cc: 00000000 .word 0x00000000
Code: Select all
001da350: 7c0802a6 mflr r0
001da354: 3880000c li r4,12
001da358: 90010008 stw r0,8(SP)
001da35c: 38a00000 li r5,0
001da360: 9421ffc0 stwu SP,-64(SP)
001da364: 4800fe6d bl 0x1ea1d0
001da368: 60000000 nop
001da36c: 2c03001e cmpwi r3,30
001da370: 40810024 ble- 0x1da394
001da374: 54600ffe rlwinm r0,r3,1,31,31
001da378: 3c800001 lis r4,1
001da37c: 7c001a14 add r0,r0,r3
001da380: 5403083c rlwinm r3,r3,1,0,30 - Shifts left once instead of right once
001da384: 3804c350 subi r0,r4,15536
001da388: 38630001 addi r3,r3,1
001da38c: 7c6301d6 mullw r3,r3,r0
001da390: 4800002c b 0x1da3c0
001da394: 3ca06666 lis r5,26214
001da398: 3c800001 lis r4,1
001da39c: 38056667 addi r0,r5,26215
001da3a0: 7c601896 mulhw r3,r0,r3
001da3a4: 3804c350 subi r0,r4,15536
001da3a8: 7c631670 srawi r3,r3,2
001da3ac: 54640ffe rlwinm r4,r3,1,31,31
001da3b0: 7c632214 add r3,r3,r4
001da3b4: 38630001 addi r3,r3,1
001da3b8: 5463103a rlwinm r3,r3,1,0,30 - Added line - left shift by 2 = multiplying by 4
001da3bc: 7c6301d6 mullw r3,r3,r0
001da3c0: 80010048 lwz r0,72(SP)
001da3c4: 38210040 addi SP,SP,64
001da3c8: 7c0803a6 mtlr r0
001da3cc: 4e800020 blr
The necessary change, for completeness' sake:
Code: Select all
Original:
001dad7c: 1c632710 mulli r3,r3,10000
Changed:
001dad7c: 1c634e20 mulli r3,r3,20000
If anyone wants a more detailed explanation of what the code is doing, I'll do my best to provide one, although I'm not an expert on PowerPC assembler by any means.
- Contrail
Last edited by Contrail on Sat Oct 06, 2007 4:03 am, edited 1 time in total.
-
- Posts: 15
- Joined: Tue Jun 18, 2002 7:43 pm
Re: Mac Gold Limit Editing
I would guess this is because of your change to shift left once at 001da380. The calculation is normally something like "(Integer (clvl/2)) x 50000" hence a change only every other level. The shift left once makes it "(Integer (clvl*2))*50000." Since clvl*2 is always an integer, the change happens every level. Sorry for the psuedo-code. I don't actually know any assembly, I am just guessing at the structure of the equation.although after level 30 it goes up by 100,000 each level instead of 200,000 every two levels.
How is it that you add a line to the code? The app stops working when I tried doing that.
http://miyoshino.la.coocan.jp/eswiki/?FAQ#sdd9e562 says ES has an octupled stash and quadrupled inventory. Maybe that is an old section of the wiki.
-
- Paladin
- Posts: 169
- Joined: Sun Jul 13, 2003 1:37 am
- Location: Austin, TX
Re: Mac Gold Limit Editing
You're correct about why it's happening, I was mostly just making a note of the difference.Careyagimon";p="358300" wrote:I would guess this is because of your change to shift left once at 001da380. The calculation is normally something like "(Integer (clvl/2)) x 50000" hence a change only every other level. The shift left once makes it "(Integer (clvl*2))*50000." Since clvl*2 is always an integer, the change happens every level. Sorry for the psuedo-code. I don't actually know any assembly, I am just guessing at the structure of the equation.although after level 30 it goes up by 100,000 each level instead of 200,000 every two levels.
Short answer: very carefully. Long answer: you need to have at least one line free at the end of the function or a no op instruction you can replace, because you don't want to increase the total number of lines in the file. Then you carefully move lines up or down in the file until you can clear out the space where you actually want your new instruction to go. The next step is to figure out the correct hex value for the instruction you want to add and place it in the correct place in the file. Finally, you correct any branch calls internal to the function that no longer point to the same line they did previously.How is it that you add a line to the code? The app stops working when I tried doing that.
Hmm, I was going by the ES database website, I'm not sure which is likely to be more accurate....ES has an octupled stash and quadrupled inventory. Maybe that is an old section of the wiki.
- Contrail
-
- Dominion
- Posts: 6438
- Joined: Sat Oct 02, 2004 5:14 pm
- Location: Toronto, Ontario, Canada
The wiki is most likely up to date.
"Hi. My name is Hans, and I am addicted to a game that is not yet been made" - Card carrying member of D3 Addictions Anonymous, since June 2008.
Card carrying member of Mentaldom, since May 2006 - Zy-El Hardcore.
"German pornstar/Bee Gee lookalike" & "The Blacksmith"
Trying to picture Hans as a Dominion...nah it isn't working sorry. It's the mustache that gets me every time - Al-T.
"All men play on 127" - Hans
"Okay, time out. This is Zy-El. The mod of total excess. Since when would any Zy-El lover do only what's necessary?" - Metropolis Man
Zy-El Wiki|New Zy-El Website
Card carrying member of Mentaldom, since May 2006 - Zy-El Hardcore.
"German pornstar/Bee Gee lookalike" & "The Blacksmith"
Trying to picture Hans as a Dominion...nah it isn't working sorry. It's the mustache that gets me every time - Al-T.
"All men play on 127" - Hans
"Okay, time out. This is Zy-El. The mod of total excess. Since when would any Zy-El lover do only what's necessary?" - Metropolis Man
Zy-El Wiki|New Zy-El Website
-
- Paladin
- Posts: 169
- Joined: Sun Jul 13, 2003 1:37 am
- Location: Austin, TX
Re: Mac Gold Limit Editing
Okay, well, to get 8 times the inventory gold capacity, you can make the following change instead of the previous change I listed for increasing the inventory gold limit.
That shifts the level value left three places, which is the same as multiplying by 8, before multiplying it by the original 10,000 gold value.
- Contrail
Code: Select all
Original:
001dad78: 60000000 nop
New:
001dad78: 54631838 rlwinm r3,r3,3,0,28
- Contrail
Re: Mac Gold Limit Editing
I am totally ignorant of Mac executable structure, but perhaps a trick from the Windows DLL world can help. DLLs have discrete sections for code, read-only data (mostly intermodular communication) and read/write data. Since these sections are sized in pages, there is usually some slack space at the end of each section. You can replace static code at any location with a jump to slack space, put the overwritten instructions there and then your new code, and jump back to the next original line. Calls to new procedures work too.Contrail";p="358301" wrote:Short answer: very carefully. Long answer: you need to have at least one line free at the end of the function or a no op instruction you can replace, because you don't want to increase the total number of lines in the file. Then you carefully move lines up or down in the file until you can clear out the space where you actually want your new instruction to go. The next step is to figure out the correct hex value for the instruction you want to add and place it in the correct place in the file. Finally, you correct any branch calls internal to the function that no longer point to the same line they did previously.
One of the best examples of this is the skill points per level fix documented here. My post on 12 Jul, 2003 shows the basic technique. In a pinch, if you have discrete sections and run out of space code space, you should be able to put code in a read-only data section and execute it through jumps and calls. Read-write data is more risky, as the program may overwrite your new code in memory if the data location you use is actually referenced.
You need a tool that shows the executable file structure (what we call a PE viewer in the Windows world). Then look for dead bytes, probably all 00, between the last recognizable code and the section boundary.
Do the right thing. It will gratify some people and astonish the rest.
~ Mark Twain
Run Diablo II in any version for mods: tutorial
The Terms of Service!! Know them, abide by them, and enjoy the forums at peace.
The Beginner's Guide v1.4: (MS Word | PDF) || Mod Running Scripts || TFW: Awakening
~ Mark Twain
Run Diablo II in any version for mods: tutorial
The Terms of Service!! Know them, abide by them, and enjoy the forums at peace.
The Beginner's Guide v1.4: (MS Word | PDF) || Mod Running Scripts || TFW: Awakening
-
- Paladin
- Posts: 169
- Joined: Sun Jul 13, 2003 1:37 am
- Location: Austin, TX
Re: Mac Gold Limit Editing
I do have a tool named PEFViewer that I downloaded from Apple's developer site that seperates out the different PEF containers and sections in a file. Unfortunately, the type of executable file being used for the Diablo II (Carbon) application doesn't have the same sort of page size requirement that a Windows DLL does, so there isn't as much dead space. Code sections are required to be 16 byte aligned, but otherwise the size of a section is fairly flexible. Some documentation on the PEF file structure that Diablo II uses on the Mac can be found on Apple's website here.Myhrginoc";p="359648" wrote:I am totally ignorant of Mac executable structure, but perhaps a trick from the Windows DLL world can help. DLLs have discrete sections for code, read-only data (mostly intermodular communication) and read/write data. Since these sections are sized in pages, there is usually some slack space at the end of each section. You can replace static code at any location with a jump to slack space, put the overwritten instructions there and then your new code, and jump back to the next original line. Calls to new procedures work too.
One of the best examples of this is the skill points per level fix documented here. My post on 12 Jul, 2003 shows the basic technique. In a pinch, if you have discrete sections and run out of space code space, you should be able to put code in a read-only data section and execute it through jumps and calls. Read-write data is more risky, as the program may overwrite your new code in memory if the data location you use is actually referenced.
You need a tool that shows the executable file structure (what we call a PE viewer in the Windows world). Then look for dead bytes, probably all 00, between the last recognizable code and the section boundary.
The code section for Diablo II has the actual functions, some glue code for making calls to external functions, and then some read-only data in it. There are some stretches of empty space in among the read-only data that's there that may be able to be used as you've suggested. They're not terribly large, though, so I may need to look into if it'd even be possible to add new external libraries and functions to the loader section without disturbing everything else too much. On the other hand, if that does turn out to be possible, it'd open things up quite a bit.
- Contrail
Re: Mac Gold Limit Editing
If you can make an auxiliary library, then you could write your own "importer" function. The importer would have one parameter, the offset to the first instruction of a function in your module. The function itself should get the library's load address and save it in a read/write space if not already defined, then add the offset to the load address to get the true address of the function...and then call it. This is definitely a kludge but it works if you can't edit import/export lists. You only need one function, in the Diablo code you only need to "relocate" the bytes needed for the parameter and call for the importer. If you were calling a custom function used in several places, then you would have a number of "header" functions with the relocated code and a call to the custom function so the latter doesn't need to be burdened with relocated code.
There are other methods available that are more elegant, if you know how to patch code in memory. Then you just need to tag onto a function that executes very early (such as mpq load time) for the patcher.
There are other methods available that are more elegant, if you know how to patch code in memory. Then you just need to tag onto a function that executes very early (such as mpq load time) for the patcher.
Do the right thing. It will gratify some people and astonish the rest.
~ Mark Twain
Run Diablo II in any version for mods: tutorial
The Terms of Service!! Know them, abide by them, and enjoy the forums at peace.
The Beginner's Guide v1.4: (MS Word | PDF) || Mod Running Scripts || TFW: Awakening
~ Mark Twain
Run Diablo II in any version for mods: tutorial
The Terms of Service!! Know them, abide by them, and enjoy the forums at peace.
The Beginner's Guide v1.4: (MS Word | PDF) || Mod Running Scripts || TFW: Awakening
-
- Posts: 15
- Joined: Tue Jun 18, 2002 7:43 pm
-
- Paladin
- Posts: 169
- Joined: Sun Jul 13, 2003 1:37 am
- Location: Austin, TX
Are you having trouble with the one to increase the stash gold limit by four, or with one of the inventory gold limit increase code edits I posted (one is for 2x the limit, and the other is for 8x the limit)?Careyagimon";p="360362" wrote:Contrail, could you reiterate the edit to quadruple the inventory stash? I can't get it to work as it is. Thanks
- Contrail
-
- Posts: 15
- Joined: Tue Jun 18, 2002 7:43 pm
-
- Paladin
- Posts: 169
- Joined: Sun Jul 13, 2003 1:37 am
- Location: Austin, TX
Okay, the specific changes that need to be made are as follows:Careyagimon";p="360378" wrote:Whoa, I just reread my last post... Sorry about that.
The stash gold limit. The code listed above isn't working for me.
With a hex editor, at offset 001da380 change 7c030e70 to 5403083c.
Then you insert 5463103a between the instruction at offset 001da3b4 and the instruction currently at offset 001da3b8.
Finally, at offset 001da3d0 (was originally 001da3cc), remove 00000000, to make up for the insertion at offset 001da3b8.
- Contrail
-
- Paladin
- Posts: 169
- Joined: Sun Jul 13, 2003 1:37 am
- Location: Austin, TX
Re: Mac Gold Limit Editing
Turns out I forgot one more thing that needs to be changed.
At offset 001da390 you need to change 4800002c to 48000030, otherwise it ends up multiplying the stash gold limit by 50,000 twice instead of once if the character's level is over 30.
- Contrail
At offset 001da390 you need to change 4800002c to 48000030, otherwise it ends up multiplying the stash gold limit by 50,000 twice instead of once if the character's level is over 30.
- Contrail
-
- Posts: 15
- Joined: Tue Jun 18, 2002 7:43 pm