Drakan patch 445++, solving Alwarren and cutscene
Hi everyone.
English is not my native language so it will be a real challenge for you to understand me but I'll do my best to make this obstacle not so hard.
Shelim, I'm glad that you continue making attempts to fix Drakan crashes. Unfortunately the goal is still too far
Thank you for publishing bytes your patch changes.
Could you give a little explanation of your patches? If you don't mind to reveal your secrets, of course.
Patch 445+ bypasses 2 identical blocks of code. Why?
Patch 445++ bypasses another one block. For what purpose?
Why does a downloadable version of your patch http://dl.getdropbox.com/u/82366/drakan ... %2B%2B.exe include only "DRAKAN PATCH 445+" staff? Is "DRAKAN PATCH 445++ (second version)" still in alpha state and that's why you decided not to include it into your official patch release?
English is not my native language so it will be a real challenge for you to understand me but I'll do my best to make this obstacle not so hard.
Shelim, I'm glad that you continue making attempts to fix Drakan crashes. Unfortunately the goal is still too far
Thank you for publishing bytes your patch changes.
Could you give a little explanation of your patches? If you don't mind to reveal your secrets, of course.
Patch 445+ bypasses 2 identical blocks of code. Why?
Patch 445++ bypasses another one block. For what purpose?
Why does a downloadable version of your patch http://dl.getdropbox.com/u/82366/drakan ... %2B%2B.exe include only "DRAKAN PATCH 445+" staff? Is "DRAKAN PATCH 445++ (second version)" still in alpha state and that's why you decided not to include it into your official patch release?
I do not remember the exact code, but I found something like this in Drakan code (related to 445+):
This "DoSomething" was done two times in code. I did not investigate what this do specifically, but it seems to be non essential for game to run. Guess drawing routines, or something...
As for 445++ I don't remember it even a bit, and I do not have access to my notes at this moment.
And as for next patches, things seemed to slowed for a bit, as I have major personal problems to be handled for now. So, any futher Drakan patches are postponed until I get free time again (which may not happen soon, I am afraid )
Code: Select all
// C++ style code, mostly based on guessing
Frame * frame = CopyBackgroundBuffer(); // Noticed that on modern hardware
// we don't have background in menus? :-)
frame->DoSomething(); // Ops, no one check the return value of above
// we have dereferenced null pointer over there!
As for 445++ I don't remember it even a bit, and I do not have access to my notes at this moment.
And as for next patches, things seemed to slowed for a bit, as I have major personal problems to be handled for now. So, any futher Drakan patches are postponed until I get free time again (which may not happen soon, I am afraid )
-
- Dragon
- Posts: 402
- Joined: Fri Oct 10, 2003 4:20 pm
- Location: USA
- Contact:
Shelim wrote:
"And as for next patches, things seemed to slowed for a bit, as I have major personal problems to be handled for now. So, any futher Drakan patches are postponed until I get free time again (which may not happen soon, I am afraid )"
Best of luck with all your current challenges.
I trust balance will be restored to your life soon, and with less effort than you anticipate.
Drakan (and it's community) will be here when you're ready 8^)
"And as for next patches, things seemed to slowed for a bit, as I have major personal problems to be handled for now. So, any futher Drakan patches are postponed until I get free time again (which may not happen soon, I am afraid )"
Best of luck with all your current challenges.
I trust balance will be restored to your life soon, and with less effort than you anticipate.
Drakan (and it's community) will be here when you're ready 8^)
Okay, seems I had more luck than brains [:D]
My problems have solved themselves amazingly easy despite looking terrible at first. So, I am once again actively working at my Drakan project.
What is this about? Well, as I mention earlier, I am writing DX 6.1 hooks that will intercept all calls to graphics card, translate them to DX 9.0c, then inject some cool special effects and send them back. This would drastically increase hardware requirements, but not necessary lower the fps count (especially if wisely used). I know for sure that the drakan does internal L&T (yeah, I reach the point when I can confirm Drakon Rider info), so I cannot intercept light source positions (this is required to write some special effects like normal maps or advance shadow techniques), but still I can add things like full scene motion blur, depth-of-field, post-processing effects, pixel- and vertex shaders, stereoscopic 3D rendering and many others. Everything will be packed as single addon, to be installed upon vanilia Drakan 445 and will be fully configurable with graphical launcher.
As for currently progress, I have completed about 40% of 1st stage of code where entire addon require three stages of work. 1st stage is about implementing all DX 6.1 interfaces and this is mostly copy&paste work, a bit annoying and time consuming. 2nd stage will consist of implementing DX 9.0c driver and this will be the hardest one. 3rd one will be equal to beta status and will consist of injecting everything I want to add to Drakan code.
@Drakon Rider:
What 445SP1 patch changes? I diffed files and found few parts of file has been no-op'ed, some flags were changed and some function rewritten... I wonder how this work internally and prefer not to do additional reverse engineering Do you have some documentation, notes, or anything? I wish to merge this with addon but I would feel better if I know something about those fixes first
My problems have solved themselves amazingly easy despite looking terrible at first. So, I am once again actively working at my Drakan project.
What is this about? Well, as I mention earlier, I am writing DX 6.1 hooks that will intercept all calls to graphics card, translate them to DX 9.0c, then inject some cool special effects and send them back. This would drastically increase hardware requirements, but not necessary lower the fps count (especially if wisely used). I know for sure that the drakan does internal L&T (yeah, I reach the point when I can confirm Drakon Rider info), so I cannot intercept light source positions (this is required to write some special effects like normal maps or advance shadow techniques), but still I can add things like full scene motion blur, depth-of-field, post-processing effects, pixel- and vertex shaders, stereoscopic 3D rendering and many others. Everything will be packed as single addon, to be installed upon vanilia Drakan 445 and will be fully configurable with graphical launcher.
As for currently progress, I have completed about 40% of 1st stage of code where entire addon require three stages of work. 1st stage is about implementing all DX 6.1 interfaces and this is mostly copy&paste work, a bit annoying and time consuming. 2nd stage will consist of implementing DX 9.0c driver and this will be the hardest one. 3rd one will be equal to beta status and will consist of injecting everything I want to add to Drakan code.
@Drakon Rider:
What 445SP1 patch changes? I diffed files and found few parts of file has been no-op'ed, some flags were changed and some function rewritten... I wonder how this work internally and prefer not to do additional reverse engineering Do you have some documentation, notes, or anything? I wish to merge this with addon but I would feel better if I know something about those fixes first
-
- Dragon
- Posts: 87
- Joined: Sun Jul 29, 2001 2:35 am
- Location: Russia
- Contact:
445SP1 was designed mostly for NoWhere level and 2 additional special attack animations.
What it changes:
1. Removed special camera rotation mode from 'left' special combo (left-forward-attack) and from 'back' special combo (forward-backward-attack).
2. For 'left' special attack added 2 active 'hitting intervals' (as the new animation has 2 visual 'physical' slashes). Engine do not only calculates objects (bounding spheres for weapon) intersection to detect attack hit but also makes it only at the special 'hittable intervals', that are unic for every attack (in retail Drakan:OOTF).
3. Removed 'stuck in block' bug.
Unfortunately no notes from may years ago. I have IDA disassembler database with some my notes inside, though a few.
What it changes:
1. Removed special camera rotation mode from 'left' special combo (left-forward-attack) and from 'back' special combo (forward-backward-attack).
2. For 'left' special attack added 2 active 'hitting intervals' (as the new animation has 2 visual 'physical' slashes). Engine do not only calculates objects (bounding spheres for weapon) intersection to detect attack hit but also makes it only at the special 'hittable intervals', that are unic for every attack (in retail Drakan:OOTF).
3. Removed 'stuck in block' bug.
Unfortunately no notes from may years ago. I have IDA disassembler database with some my notes inside, though a few.
I would never dream that I could say so so early, but...
The first stage is done
Complete implementation of all DX 6.1 graphical interfaces hooked to Drakan is ready and as far as I know it's fully working. I am running beta tests with my collegues here in Poland, and I am scheduled for begin second stage (DX 9.0c implementation) next week or the week after.
The addon will be completely independent of game executable, so it will work with either 445, 445++, or 445SP1.
As for help, thanks for proposition, but presently I do not need C/C++ programmer. But I may need shader artist in future (programmer who knows HLSL and will be willing to implement some cool special effects for DirectX 9.0c and Shader Model 3.0 [;)] )
The first stage is done
Complete implementation of all DX 6.1 graphical interfaces hooked to Drakan is ready and as far as I know it's fully working. I am running beta tests with my collegues here in Poland, and I am scheduled for begin second stage (DX 9.0c implementation) next week or the week after.
The addon will be completely independent of game executable, so it will work with either 445, 445++, or 445SP1.
As for help, thanks for proposition, but presently I do not need C/C++ programmer. But I may need shader artist in future (programmer who knows HLSL and will be willing to implement some cool special effects for DirectX 9.0c and Shader Model 3.0 [;)] )
Wait, so from what I understand from skimming through this thread, you can somehow access Drakan's source code?
If you do somehow have access to the source code, or have any other means of editing the software, please tell me more about it. I'm an experienced(though sadly not professional) programmer looking to serve the Drakan community somehow. If you could help me on my way as to how you have devised these patches, I would be much obliged. I already know you don't need a programmer, so I won't bother you about that. Still, I'd like to be able to devise my own contributions to Drakan. I'm not familiar with HLSL, unfortunately, so I won't be able to help you out with that either. Sorry.
I would also like to report a side effect the patch has; unfortunately the multiplayer component will upon initiating the hosting of a game report that the network settings are incorrect. This does not occur in an unpatched version of Drakan. I have yet to confirm whether it does this in 445, or 445+, but I will do so.
It seems LogMeIn's Hamachi LAN emulation software provides a workaround to this problem, as the message doesn't show up whenever this software is active and connected to a network.
Thanks for the patch, and have a good one!
If you do somehow have access to the source code, or have any other means of editing the software, please tell me more about it. I'm an experienced(though sadly not professional) programmer looking to serve the Drakan community somehow. If you could help me on my way as to how you have devised these patches, I would be much obliged. I already know you don't need a programmer, so I won't bother you about that. Still, I'd like to be able to devise my own contributions to Drakan. I'm not familiar with HLSL, unfortunately, so I won't be able to help you out with that either. Sorry.
I would also like to report a side effect the patch has; unfortunately the multiplayer component will upon initiating the hosting of a game report that the network settings are incorrect. This does not occur in an unpatched version of Drakan. I have yet to confirm whether it does this in 445, or 445+, but I will do so.
It seems LogMeIn's Hamachi LAN emulation software provides a workaround to this problem, as the message doesn't show up whenever this software is active and connected to a network.
Thanks for the patch, and have a good one!
No, I do not have access to Drakan source code, although I tried to contact Surreal few times
Original patch is basically disassembly work, when I took the compiled code and analyzed it in IDA (it's very efficient for debugging crash points)
The new one is based on mechanism called Windows hook. Basically the hook is function that replace other function from dynamic linked library (DLL). IE. when game calls WinAPI function SetWindowTextA( ), you can intercept this call and inject there your own function with same argument set. You can do something like this:
BOOL WINAPI SetWindowTextA(HWND hWnd, LPCTSTR lpString)
{
return origFuncTable->pSetWindowTextA(hWnd, _T("Drakan: 10th Anniversy")); // caption changed
}
The same goes for every DX function. You can intercept all methods the game send to DX and inject any code there
There is MSDN article about this technique over here: http://msdn.microsoft.com/en-us/library ... 85%29.aspx
Original patch is basically disassembly work, when I took the compiled code and analyzed it in IDA (it's very efficient for debugging crash points)
The new one is based on mechanism called Windows hook. Basically the hook is function that replace other function from dynamic linked library (DLL). IE. when game calls WinAPI function SetWindowTextA( ), you can intercept this call and inject there your own function with same argument set. You can do something like this:
BOOL WINAPI SetWindowTextA(HWND hWnd, LPCTSTR lpString)
{
return origFuncTable->pSetWindowTextA(hWnd, _T("Drakan: 10th Anniversy")); // caption changed
}
The same goes for every DX function. You can intercept all methods the game send to DX and inject any code there
There is MSDN article about this technique over here: http://msdn.microsoft.com/en-us/library ... 85%29.aspx
News from battle front [:D]
Major part of DX 9.0c renderer for Drakan is now ready, and the only things left are missing textures plus some minor enhancement and overall optimization. When I finish this part, I'll begin adding post effects. Currently I know for sure that I'll be able to add full scene motion blur and/or depth of field, fake normal maps (light position will depend on camera movement, so they won't look THAT good) and perhaps other crazy stuff I am considering right now
First screen from DX 9.0c renderer (as I said, no textures are in place yet, I just put some placeholder): http://img713.imageshack.us/img713/2336/tekstura.png
(the artifact on the grounds is in fact shadow, and that curtain in the background is outer layer of fog - don't worry about 11 FPS, that's because engine saves 4-5 debug .png files per frame, which won't happen in final)
Major part of DX 9.0c renderer for Drakan is now ready, and the only things left are missing textures plus some minor enhancement and overall optimization. When I finish this part, I'll begin adding post effects. Currently I know for sure that I'll be able to add full scene motion blur and/or depth of field, fake normal maps (light position will depend on camera movement, so they won't look THAT good) and perhaps other crazy stuff I am considering right now
First screen from DX 9.0c renderer (as I said, no textures are in place yet, I just put some placeholder): http://img713.imageshack.us/img713/2336/tekstura.png
(the artifact on the grounds is in fact shadow, and that curtain in the background is outer layer of fog - don't worry about 11 FPS, that's because engine saves 4-5 debug .png files per frame, which won't happen in final)
-
- Dragon
- Posts: 87
- Joined: Sun Jul 29, 2001 2:35 am
- Location: Russia
- Contact:
About stuck in block bug -
// Human specific flags
#define HF_BLOCKING 0x00000080
#define HF_ATTBUFFERED 0x00000200
#define HF_HOLDBLOCK 0x00004000
#define HF_ALTATTBUFFERED 0x00010000
#define HF_GRUNTED 0x00020000
There is a function of the HumanContol class:
void HumanControl::EndAttack()
{
int idRootAnim;
int idCurAnim;
int iUpperBody;
REVAL rRootTimer;
REVAL rTransTime;
at the very end of this function a lot of human state flags got cleared in 1 line/operation:
dwFlags &= ~(HF_GRUNTED | HF_ATTBUFFERED | HF_ALTATTBUFFERED | HF_BLOCKING);
Most probably I simply add clearing HF_HOLDBLOCK flag at this point too. So it is mostly 1 bit change in the argument of some AND operation. The exact bit corresponding to position of 1 in 0x00004000 number.
// Human specific flags
#define HF_BLOCKING 0x00000080
#define HF_ATTBUFFERED 0x00000200
#define HF_HOLDBLOCK 0x00004000
#define HF_ALTATTBUFFERED 0x00010000
#define HF_GRUNTED 0x00020000
There is a function of the HumanContol class:
void HumanControl::EndAttack()
{
int idRootAnim;
int idCurAnim;
int iUpperBody;
REVAL rRootTimer;
REVAL rTransTime;
at the very end of this function a lot of human state flags got cleared in 1 line/operation:
dwFlags &= ~(HF_GRUNTED | HF_ATTBUFFERED | HF_ALTATTBUFFERED | HF_BLOCKING);
Most probably I simply add clearing HF_HOLDBLOCK flag at this point too. So it is mostly 1 bit change in the argument of some AND operation. The exact bit corresponding to position of 1 in 0x00004000 number.
-
- Dragon
- Posts: 87
- Joined: Sun Jul 29, 2001 2:35 am
- Location: Russia
- Contact:
Also found my old note that describes how 'engine performance patch' acts:
>The memory handling does sound very stupid, though - when Drakan came out, 128MB was a pretty normal spec for most machines.
as you know Drakan's minimum hardware is 16 Mb RAM ... ask Surreal or Psygnosis why it is so...
look at this subroutine - it is a part of render code that manage memory :
i.e. you can patch byte 09H at offset 3C8CEH in Drakan.exe to 0FH to get about +40% performance at Paradise level and about +190% performance at Atlantis level ... but it would make almost zero difference at retail low-enough-poly levels ... the more POP/POR you have in a frame the more advantage you will get ...
also recommended to patch memory allocation routine at 3C7ECH - we have not place there but we can replace it with a jump to free place at the end of .text section - i make it to 78500H
so changes in the tweaked version:
You can add it in your patch too.
I think it is part of 'dynamic arrays' which Riot Engine uses to fits in very small RAM machines, but for some design reason it can not reallocates the exact new amount of memory in 1 OS call and makes a number of sequential calls that takes much more time. The point of that patch was to increase the memory allocation step - so reduce a number of calls to reallocating OS subroutine. Yes - it will ends in not optimal memory usage but now we usually have significally more memory in user's PCs.
Also I found some backup of my IDA database with my comments from that years when I searching via Drakan:OOTF binaries:
ftp://fauser:365445@files.drakan.ru/pub ... n_idbs.zip
May it would be useful too. Do not remember what IDA version I use though.
>The memory handling does sound very stupid, though - when Drakan came out, 128MB was a pretty normal spec for most machines.
as you know Drakan's minimum hardware is 16 Mb RAM ... ask Surreal or Psygnosis why it is so...
look at this subroutine - it is a part of render code that manage memory :
Code: Select all
...
.text:0043C7D0 ; --------------- S U B R O U T I N E ---------------------------------------
.text:0043C7D0
.text:0043C7D0
.text:0043C7D0 sub_43C7D0 proc near ; CODE XREF: sub_446A30+258p
.text:0043C7D0 ; sub_446E70+6B0p
.text:0043C7D0
.text:0043C7D0 arg_0 = dword ptr 10h
.text:0043C7D0 arg_4 = dword ptr 14h
.text:0043C7D0 arg_8 = dword ptr 18h
.text:0043C7D0
.text:0043C7D0 push ebx
.text:0043C7D1 push ebp
.text:0043C7D2 push esi
.text:0043C7D3 mov esi, ecx
.text:0043C7D5 push edi
.text:0043C7D6 mov eax, [esi+1B8h]
.text:0043C7DC mov ecx, [esi+1BCh]
.text:0043C7E2 cmp ecx, eax ; test if allocated memory still enough
.text:0043C7E4 jl short loc_43C848 ; jump if everything still OK for render
.text:0043C7E6 mov ecx, [esi+1B4h]
.text:0043C7EC add eax, 100h ; prepare to allocate more memory
.text:0043C7F1 test ecx, ecx ; test if ReAllocating required
.text:0043C7F3 mov [esi+1B8h], eax
.text:0043C7F9 jz short loc_43C82C ; jump to Allocating
.text:0043C7FB mov edi, ds:GlobalHandle
.text:0043C801 push ecx ; pMem
.text:0043C802 call edi ; GlobalHandle
.text:0043C804 push eax ; hMem
.text:0043C805 call ds:GlobalUnlock
.text:0043C80B mov eax, [esi+1B8h]
.text:0043C811 mov ecx, [esi+1B4h]
.text:0043C817 push 2 ; uFlags
.text:0043C819 lea eax, [eax+eax*4]
.text:0043C81C shl eax, 2
.text:0043C81F push eax ; dwBytes
.text:0043C820 push ecx ; pMem
.text:0043C821 call edi ; GlobalHandle
.text:0043C823 push eax ; hMem
.text:0043C824 call ds:GlobalReAlloc ; DAMN SLOW function :(
.text:0043C82A jmp short loc_43C83B
.text:0043C82C ; ---------------------------------------------------------------------------
.text:0043C82C
.text:0043C82C loc_43C82C: ; CODE XREF: sub_43C7D0+29j
.text:0043C82C lea edx, [eax+eax*4]
.text:0043C82F shl edx, 2
.text:0043C832 push edx ; dwBytes
.text:0043C833 push 0 ; uFlags
.text:0043C835 call ds:GlobalAlloc
.text:0043C83B
.text:0043C83B loc_43C83B: ; CODE XREF: sub_43C7D0+5Aj
.text:0043C83B push eax ; hMem
.text:0043C83C call ds:GlobalLock
.text:0043C842 mov [esi+1B4h], eax
.text:0043C848
.text:0043C848 loc_43C848: ; CODE XREF: sub_43C7D0+14j
.text:0043C848 mov eax, [esi+1BCh]
.text:0043C84E xor ecx, ecx
.text:0043C850 mov edi, [esp+4+arg_4]
.text:0043C854 lea edx, [eax+eax*4]
.text:0043C857 mov eax, [esi+1B4h]
.text:0043C85D lea edx, [eax+edx*4]
.text:0043C860 mov [edx], ecx
.text:0043C862 mov [edx+4], ecx
.text:0043C865 mov [edx+8], ecx
.text:0043C868 mov [edx+0Ch], ecx
.text:0043C86B mov [edx+10h], ecx
.text:0043C86E mov eax, [esi+1BCh]
.text:0043C874 mov edx, [esp+4+arg_8]
.text:0043C878 inc eax
.text:0043C879 mov [esi+1BCh], eax
.text:0043C87F mov ecx, [esi+1B4h]
.text:0043C885 lea eax, [eax+eax*4]
.text:0043C888 lea ebp, [ecx+eax*4-14h]
.text:0043C88C mov [ebp+0], edx
.text:0043C88F mov [ebp+8], edi
.text:0043C892 mov eax, [esi+1C8h]
.text:0043C898 mov [ebp+0Ch], eax
.text:0043C89B mov ecx, [esi+164h]
.text:0043C8A1 mov [ebp+4], ecx
.text:0043C8A4 mov ebx, [esi+1C8h]
.text:0043C8AA mov ecx, [esi+1C4h]
.text:0043C8B0 mov eax, ebx
.text:0043C8B2 lea edx, [eax+edi]
.text:0043C8B5 cmp edx, ecx ; <== test if enough memory
.text:0043C8B7 jle short loc_43C92A ; <== jump if everything still OK for render
.text:0043C8B9 sub eax, ecx
.text:0043C8BB lea eax, [eax+edi-1]
.text:0043C8BF cdq
.text:0043C8C0 and edx, 1FFh ; >
.text:0043C8C6 add eax, edx ; >
.text:0043C8C8 sar eax, 9 ; > < == prepare to allocate more memory
.text:0043C8CB inc eax ; >
.text:0043C8CC shl eax, 9 ; >
.text:0043C8CF add eax, ecx
.text:0043C8D1 mov ecx, [esi+1C0h]
.text:0043C8D7 test ecx, ecx ; < == test if ReAllocating required
.text:0043C8D9 mov [esi+1C4h], eax
.text:0043C8DF jz short loc_43C911 ; < == jump for Allocating
.text:0043C8E1 push ecx ; pMem
.text:0043C8E2 call ds:GlobalHandle
.text:0043C8E8 push eax ; hMem
.text:0043C8E9 call ds:GlobalUnlock
.text:0043C8EF mov eax, [esi+1C4h]
.text:0043C8F5 mov ecx, [esi+1C0h]
.text:0043C8FB shl eax, 5
.text:0043C8FE push 2 ; uFlags
.text:0043C900 push eax ; dwBytes
.text:0043C901 push ecx ; pMem
.text:0043C902 call ds:GlobalHandle
.text:0043C908 push eax ; hMem
.text:0043C909 call ds:GlobalReAlloc ; DAMN SLOW function :(
.text:0043C90F jmp short loc_43C91D
...
also recommended to patch memory allocation routine at 3C7ECH - we have not place there but we can replace it with a jump to free place at the end of .text section - i make it to 78500H
so changes in the tweaked version:
Code: Select all
.text:0043C7EC jmp 478500
.text:0043C8CC shl eax, 0FH
.text:00478500 or eax,100H
.text:00478505 shl eax,05H
.text:00478508 jmp 43C7F1H
I think it is part of 'dynamic arrays' which Riot Engine uses to fits in very small RAM machines, but for some design reason it can not reallocates the exact new amount of memory in 1 OS call and makes a number of sequential calls that takes much more time. The point of that patch was to increase the memory allocation step - so reduce a number of calls to reallocating OS subroutine. Yes - it will ends in not optimal memory usage but now we usually have significally more memory in user's PCs.
Also I found some backup of my IDA database with my comments from that years when I searching via Drakan:OOTF binaries:
ftp://fauser:365445@files.drakan.ru/pub ... n_idbs.zip
May it would be useful too. Do not remember what IDA version I use though.