2 * Copyright (C) 2010 gonzoj
4 * Please check the CREDITS file for further information.
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "d2pointers.h"
38 #define PAGE_ALIGN(addr) (addr & ~0xfff)
40 char last_game_name
[512];
42 unit_any
*viewing_unit
;
44 #define i386_CALL 0xE8
45 #define i386_JUMP 0xE9
54 unsigned char *backup
;
63 #ifdef _VERSION_1_13 /* updated */
64 { i386_CALL
, "D2Client.dll", 0x626FE, 5, draw_automap
, NULL
}, /* updated 0x6FB126FE */
65 { i386_JUMP
, "D2Client.dll", 0xC3DB4, 6, draw_ingame_STUB
, NULL
}, /* updated 0x6FB73DB4 */
66 { i386_CALL
, "D2Client.dll", 0x92366, 6, item_name_patch_STUB
, NULL
}, /* updated 0x6FB42366 */
67 { i386_CALL
, "D2Multi.dll", 0x14D29, 5, next_game_name_patch
, NULL
}, /* updated 0x6F9E4D29 */
68 { i386_CALL
, "D2Multi.dll", 0x14A0B, 5, next_game_name_patch
, NULL
}, /* updated 0x6F9E4A0B */
69 { i386_CALL
, "D2Client.dll", 0x953E2, 6, view_inventory_patch_1
, NULL
}, /* updated 0x6FB453E2 */
70 { i386_CALL
, "D2Client.dll", 0x94AB4, 6, view_inventory_patch_2
, NULL
}, /* updated 0x6FB44AB4 */
71 { i386_CALL
, "D2Client.dll", 0x93A6F, 5, view_inventory_patch_3
, NULL
} /* updated 0x6FB43A6F */
73 #elif defined _VERSION_1_12 /* from McGod's mMap (modified) */
74 { i386_CALL
, "D2Client.dll", 0x4063E, 5, draw_automap
, NULL
},
75 { i386_JUMP
, "D2Client.dll", 0x90524, 6, draw_ingame_STUB
, NULL
},
76 { i386_CALL
, "D2Client.dll", 0xAF242, 6, view_inventory_patch_1
, NULL
},
77 { i386_CALL
, "D2Client.dll", 0xAE914, 6, view_inventory_patch_2
, NULL
},
78 { i386_CALL
, "D2Client.dll", 0xAD93F, 5, view_inventory_patch_3
, NULL
},
79 { i386_CALL
, "D2Client.dll", 0xAC236, 6, item_name_patch_STUB
, NULL
},
80 { i386_CALL
, "D2Multi.dll", 0x14959, 5, next_game_name_patch
, NULL
},
81 { i386_CALL
, "D2Multi.dll", 0x1463B, 5, next_game_name_patch
, NULL
}
85 #error NO VERSION SPECIFIED
97 if (strlen(D2CLIENT_get_game_info()->game_ip
) > 0)
99 draw_text(780, 122, D2FONT_GOLD
, 0, D2FONT_SPECIAL
, 0, "%s",
100 D2CLIENT_get_game_info()->game_ip
);
107 draw_text(400, 540, D2FONT_WHITE
, 0, D2FONT_STANDARD
, 1, "%s",
108 "snoogans.so v 0.4");
111 void __attribute__((fastcall
))
112 item_name_patch(unit_any
*item
, ms_wchar_t
*wname
)
119 ms_wchar_to_char(wname
, tmp
);
120 char line1
[512], *line2
;
121 strcpy(line1
, strtok(tmp
, "\n"));
122 line2
= strtok(NULL
, "\n");
123 int sockets
= D2COMMON_get_unit_stat(item
, 194, 0);
127 sprintf(c_sockets
, " (%i)", sockets
);
128 strcat(line1
, c_sockets
);
130 if (item
->item_data
->flags
& 0x400000)
132 char eth
[] = " (Eth)";
136 sprintf(name
, "(%i) ", item
->item_data
->level
);
143 char_to_ms_wchar(name
, wname
);
146 void __attribute__((fastcall
))
147 next_game_name_patch(vaddr box
, int __attribute__((stdcall))
148 (*call_back
)(vaddr
, DWORD
, DWORD
))
150 if (strlen(last_game_name
) == 0)
154 ms_wchar_t wname
[512];
155 char_to_ms_wchar(last_game_name
, wname
);
156 D2WIN_set_control_text(box
, wname
);
157 D2WIN_select_edit_box_text(box
, wname
);
158 D2WIN_set_edit_box_proc(box
, call_back
);
166 return D2CLIENT_get_player_unit();
172 view_inventory_patch()
174 unit_any
*unit
= get_view_unit();
175 unit_any
*me
= D2CLIENT_get_player_unit();
176 if (unit
->id
== me
->id
)
180 draw_text(560, 300, D2FONT_WHITE
, 0, D2FONT_SPECIAL
, 1, "%s",
181 unit
->player_data
->name
);
182 return get_view_unit();
186 install_hook(const char *module
, vaddr offset
, vaddr func
, size_t bytes
,
187 unsigned char inst
, unsigned char **backup
)
189 void *h
= LoadLibraryA(module
);
192 printf("err: could not get a handle for %s\n", module
);
195 vaddr addr
= (vaddr
) h
+ offset
;
196 unsigned char hook
[bytes
];
197 memset(hook
, 0x90, bytes
);
199 *(vaddr
*) &hook
[1] = func
- (addr
+ 5);
200 DEBUG_DO(printf("installing hook at 0x%08X to func (0x%08X)\n", addr
, func
)); DEBUG_DO(printf("ASM: ");)
201 DEBUG_DO(inst
== i386_CALL
? printf("call ") : printf("jmp ");)
202 DEBUG_DO(printf("0x%08X\n", func
- (addr
+ 5));)
203 DEBUG_DO(printf("enabling write access to page(s) starting from 0x%08X\n", PAGE_ALIGN(addr
));)
204 if (mprotect((void *) PAGE_ALIGN(addr
), bytes
, PROT_READ
| PROT_WRITE
207 printf("err: could not enable write access to page(s)\n");
210 *backup
= (unsigned char *) malloc(bytes
);
211 memcpy((void *) *backup
, (void *) addr
, bytes
);
212 DEBUG_DO(printf("saved original code\n");)
213 memcpy((void *) addr
, (void *) hook
, bytes
);
214 DEBUG_DO(printf("patched to:\n");
216 for (i
= 0; i
< bytes
; i
++)
218 printf("0x%02X\n", hook
[i
]);
220 DEBUG_DO(printf("disabling write access to page(s) starting from 0x%08X\n", PAGE_ALIGN(addr
));)
221 if (mprotect((void *) PAGE_ALIGN(addr
), bytes
, PROT_READ
| PROT_EXEC
))
223 printf("err: could not disable write access to page(s)\n");
226 DEBUG_DO(printf("done\n");)
234 for (i
= 0; i
< N_HOOKS
; i
++)
236 if (!install_hook(hooks
[i
].module
, hooks
[i
].offset
,
237 (vaddr
) hooks
[i
].func
, hooks
[i
].size
, hooks
[i
].type
, &hooks
[i
].backup
))
246 remove_hook(const char *module
, vaddr offset
, size_t bytes
,
247 unsigned char *backup
)
249 void *h
= LoadLibraryA(module
);
252 printf("err: could not get a handle for %s\n", module
);
255 vaddr addr
= (vaddr
) h
+ offset
;
256 DEBUG_DO(printf("enabling write access to page(s) starting from 0x%08X\n", PAGE_ALIGN(addr
));)
257 if (mprotect((void *) PAGE_ALIGN(addr
), bytes
, PROT_READ
| PROT_WRITE
260 printf("err: could not enable write access to page(s)\n");
263 memcpy((void *) addr
, (void *) backup
, bytes
);
264 DEBUG_DO(printf("restored original code:\n");
266 for (i
= 0; i
< bytes
; i
++)
268 printf("0x%02X\n", backup
[i
]);
271 DEBUG_DO(printf("disabling write access to page(s) starting from 0x%08X\n", PAGE_ALIGN(addr
));)
272 if (mprotect((void *) PAGE_ALIGN(addr
), bytes
, PROT_READ
| PROT_EXEC
))
274 printf("err: could not disable write access to page(s)\n");
277 DEBUG_DO(printf("done\n");)
285 for (i
= 0; i
< N_HOOKS
; i
++)
289 if (!remove_hook(hooks
[i
].module
, hooks
[i
].offset
, hooks
[i
].size
,