初级玩家

- 贡献度
- 8
- 金元
- 864
- 积分
- 58
- 精华
- 0
- 注册时间
- 2009-11-6
|
==== Singleplayer UI hacking wiki ====
=== WANNA JOIN US? ===
Before sending a PM to __usmc23__ who is taking care of this project, please try to play with __ALL__ the tricks listed here. __usmc23__ does not look at the comments on this page and will not provide any troubleshooting what so ever. If you have anything to contribute please pm __usmc23__ on IRC.
=== UPDATE 2 ===
Alright we have been looking at this all wrong, let me first start off by defining some functions, in SC2.exe this is the code for pushing a sc2layout file to the ui stack.
<code>
//
// sub_9AE2E0
//
// A1 is the Sc2Layout Name eg BattleUI/BattleUI
// A2 is the table of functions to use
int __fastcall UI_LoadSc2Layout(char *a1, void *a2)
{
int result; // eax@1
int v3; // esi@1
char v4; // [sp+4h] [bp-8h]@1
v3 = a2;
result = sub_AB6C20(&v4, 1);
if ( result )
result = Bnet_InitUnkown(v3);
return result;
}
.text:00AB6D40 UI_LoadSc2Layout proc near ; CODE XREF: sub_9AE2E0+34p
.text:00AB6D40 ; sub_9AE340+34p ...
.text:00AB6D40
.text:00AB6D40 var_8 = byte ptr -8
.text:00AB6D40
.text:00AB6D40 push ebp
.text:00AB6D41 mov ebp, esp
.text:00AB6D43 sub esp, 8
.text:00AB6D46 push esi
.text:00AB6D47 push 1
.text:00AB6D49 lea eax, [ebp+var_8]
.text:00AB6D4C mov esi, edx
.text:00AB6D4E push eax
.text:00AB6D4F xor edx, edx
.text:00AB6D51 call sub_AB6C20
.text:00AB6D56 test eax, eax
.text:00AB6D58 jnz short loc_AB6D5F
.text:00AB6D5A pop esi
.text:00AB6D5B mov esp, ebp
.text:00AB6D5D pop ebp
.text:00AB6D5E retn
.text:00AB6D5F ; ---------------------------------------------------------------------------
.text:00AB6D5F
.text:00AB6D5F loc_AB6D5F: ; CODE XREF: UI_LoadSc2Layout+18j
.text:00AB6D5F push esi
.text:00AB6D60 mov ecx, eax
.text:00AB6D62 call Bnet_InitUnkown
.text:00AB6D67 pop esi
.text:00AB6D68 mov esp, ebp
.text:00AB6D6A pop ebp
.text:00AB6D6B retn
.text:00AB6D6B UI_LoadSc2Layout endp
</code>
Now lets say we wanted to hide the entire spaceship planet background, what do we do? Open up ScreenBackground.sc2layout, and find <Frame type="Model" name="BackgroundModel">, add <Visible val="false"/> to it and you can hide the background stuff.
Now so were does this leave us? For a layout to work it has to be pushed onto the UI that becomes a child of ScreenBackground.sc2layout. Here is the menus it loads.
<code>
.rdata:01327879 aCreenmovieScree db 'creenMovie/ScreenMovie',0
.rdata:01327890 ScreenLoadingStr db 53h ; DATA XREF: UI_ParentBackground:loc_12CCD68r
.rdata:01327890 ; UI_ParentBackground+84o ...
.rdata:01327891 aCreenloadingScr db 'creenLoading/ScreenLoading',0
.rdata:013278AC ScreenCreditsStr db 53h ; DATA XREF: UI_ParentBackground:loc_12CCD48r
.rdata:013278AC ; UI_ParentBackground+64o ...
.rdata:013278AD aCreencreditsScr db 'creenCredits/ScreenCredits',0
.rdata:013278C8 ScreenReplayStr db 53h ; DATA XREF: UI_ParentBackground:loc_12CCD28r
.rdata:013278C8 ; UI_ParentBackground+44o ...
.rdata:013278C9 aCreenreplayScre db 'creenReplay/ScreenReplay',0
.rdata:013278E2 align 4
.rdata:013278E4 ScreenVersionStd db 53h ; DATA XREF: UI_ParentBackground:loc_12CCD08r
.rdata:013278E4 ; UI_ParentBackground+24o ...
.rdata:013278E5 aCreenversionScr db 'creenVersion/ScreenVersion',0
; UI_ParentBackground+7o ...
</code>
Now so that means ScreenMainMenu isn't loaded at all right? Wrong. Look at the DESC file it loads Sc2MainMenum, but doesn't ENABLE IT AND ATTACH IT TO THE ScreenMainMenu functions.
Lets look at the function that does just that,
<code>
UI_ParentBackground proc near ; DATA XREF: .rdata:013121D0o
.text:012CCCF0 cmp byte ptr ds:aScreenbackgrou, 0 ; "ScreenBackground/ScreenBackground"
.text:012CCCF7 mov eax, offset aScreenbackgrou ; "ScreenBackground/ScreenBackground"
.text:012CCCFC jz short loc_12CCD08
.text:012CCCFE mov edi, edi
.text:012CCD00
.text:012CCD00 loc_12CCD00: ; CODE XREF: UI_ParentBackground+16j
.text:012CCD00 add eax, 1
.text:012CCD03 cmp byte ptr [eax], 0
.text:012CCD06 jnz short loc_12CCD00
.text:012CCD08
.text:012CCD08 loc_12CCD08: ; CODE XREF: UI_ParentBackground+Cj
.text:012CCD08 cmp ds:ScreenVersionStd, 0
.text:012CCD0F mov dword_144B250, eax
.text:012CCD14 mov eax, offset ScreenVersionStd
.text:012CCD19 jz short loc_12CCD28
.text:012CCD1B jmp short loc_12CCD20
.text:012CCD1B ; ---------------------------------------------------------------------------
.text:012CCD1D align 10h
.text:012CCD20
.text:012CCD20 loc_12CCD20: ; CODE XREF: UI_ParentBackground+2Bj
.text:012CCD20 ; UI_ParentBackground+36j
.text:012CCD20 add eax, 1
.text:012CCD23 cmp byte ptr [eax], 0
.text:012CCD26 jnz short loc_12CCD20
.text:012CCD28
.text:012CCD28 loc_12CCD28: ; CODE XREF: UI_ParentBackground+29j
.text:012CCD28 cmp ds:ScreenReplayStr, 0
.text:012CCD2F mov dword_144B258, eax
.text:012CCD34 mov eax, offset ScreenReplayStr
.text:012CCD39 jz short loc_12CCD48
.text:012CCD3B jmp short loc_12CCD40
.text:012CCD3B ; ---------------------------------------------------------------------------
.text:012CCD3D align 10h
.text:012CCD40
.text:012CCD40 loc_12CCD40: ; CODE XREF: UI_ParentBackground+4Bj
.text:012CCD40 ; UI_ParentBackground+56j
.text:012CCD40 add eax, 1
.text:012CCD43 cmp byte ptr [eax], 0
.text:012CCD46 jnz short loc_12CCD40
.text:012CCD48
.text:012CCD48 loc_12CCD48: ; CODE XREF: UI_ParentBackground+49j
.text:012CCD48 cmp ds:ScreenCreditsStr, 0
.text:012CCD4F mov dword_144B260, eax
.text:012CCD54 mov eax, offset ScreenCreditsStr
.text:012CCD59 jz short loc_12CCD68
.text:012CCD5B jmp short loc_12CCD60
.text:012CCD5B ; ---------------------------------------------------------------------------
.text:012CCD5D align 10h
.text:012CCD60
.text:012CCD60 loc_12CCD60: ; CODE XREF: UI_ParentBackground+6Bj
.text:012CCD60 ; UI_ParentBackground+76j
.text:012CCD60 add eax, 1
.text:012CCD63 cmp byte ptr [eax], 0
.text:012CCD66 jnz short loc_12CCD60
.text:012CCD68
.text:012CCD68 loc_12CCD68: ; CODE XREF: UI_ParentBackground+69j
.text:012CCD68 cmp ds:ScreenLoadingStr, 0
.text:012CCD6F mov dword_144B268, eax
.text:012CCD74 mov eax, offset ScreenLoadingStr
.text:012CCD79 jz short loc_12CCD88
.text:012CCD7B jmp short loc_12CCD80
.text:012CCD7B ; ---------------------------------------------------------------------------
.text:012CCD7D align 10h
.text:012CCD80
.text:012CCD80 loc_12CCD80: ; CODE XREF: UI_ParentBackground+8Bj
.text:012CCD80 ; UI_ParentBackground+96j
.text:012CCD80 add eax, 1
.text:012CCD83 cmp byte ptr [eax], 0
.text:012CCD86 jnz short loc_12CCD80
.text:012CCD88
.text:012CCD88 loc_12CCD88: ; CODE XREF: UI_ParentBackground+89j
.text:012CCD88 cmp ds:ScreenMovieStr, 0
.text:012CCD8F mov dword_144B270, eax
.text:012CCD94 mov eax, offset ScreenMovieStr
.text:012CCD99 jz short loc_12CCDA8
.text:012CCD9B jmp short loc_12CCDA0
.text:012CCD9B ; ---------------------------------------------------------------------------
.text:012CCD9D align 10h
.text:012CCDA0
.text:012CCDA0 loc_12CCDA0: ; CODE XREF: UI_ParentBackground+ABj
.text:012CCDA0 ; UI_ParentBackground+B6j
.text:012CCDA0 add eax, 1
.text:012CCDA3 cmp byte ptr [eax], 0
.text:012CCDA6 jnz short loc_12CCDA0
.text:012CCDA8
.text:012CCDA8 loc_12CCDA8: ; CODE XREF: UI_ParentBackground+A9j
.text:012CCDA8 mov dword_144B278, eax
.text:012CCDAD retn
.text:012CCDAD UI_ParentBackground endp
</code>
So that means we stuck right? WRONG. BattleUI/BattleUi is attached seperate of this function, so my thinking is we can do the same thing our our loader. Here is the function that INIT BattleUI/BattleUI.
<code>
LoadBattleUi proc near ; CODE XREF: LoadBattleUi_0+5j
.text:00A68CB0
.text:00A68CB0 var_8 = dword ptr -8
.text:00A68CB0 var_4 = dword ptr -4
.text:00A68CB0
.text:00A68CB0 push ebp
.text:00A68CB1 mov ebp, esp
.text:00A68CB3 sub esp, 8
.text:00A68CB6 cmp dword_17334A0, 0
.text:00A68CBD jnz short loc_A68CEA
.text:00A68CBF mov eax, offset aBattleuiBattle ; "BattleUI/BattleUI"
.text:00A68CC4 mov [ebp+var_8], eax
.text:00A68CC7
.text:00A68CC7 loc_A68CC7: ; CODE XREF: LoadBattleUi+1Dj
.text:00A68CC7 add eax, 1
.text:00A68CCA cmp byte ptr [eax], 0
.text:00A68CCD jnz short loc_A68CC7
.text:00A68CCF mov [ebp+var_4], eax
.text:00A68CD2 mov eax, dword_1998EFC
.text:00A68CD7 mov edx, [eax+180h]
.text:00A68CDD lea ecx, [ebp+var_8]
.text:00A68CE0 call UI_LoadSc2Layout
.text:00A68CE5 mov dword_17334A0, eax
.text:00A68CEA
.text:00A68CEA loc_A68CEA: ; CODE XREF: LoadBattleUi+Dj
.text:00A68CEA mov esp, ebp
.text:00A68CEC pop ebp
.text:00A68CED retn
.text:00A68CED LoadBattleUi endp
</code>
So what we need to do is Init ScreenMainMenu and Init it to its function table which is in the exe. The function table for ScreenMainmenu is in the EXE just load it up and search from DebugMap,
=== UPDATE ===
We are looking for code in the SWF's to call the corrisponding sc2layouts, we can maybe fake this info the swf ill look at it tomarrow, here is the gfx file and swf put them in the proper places.
All the singleplayer GUIS can be DECOMPILED and viewed and editing in Flash. Remember to DECOMPILE the common/*.fla* to. The singleplayer guis use reusable code so you have to make sure if your looking for something to look in common/*.fla* as well.
__video__
http://www.youtube.com/watch?v=dvUZC-SxfCw
__files__
http://www.multiupload.com/PE5ERSZ5YN
The menu we have to load is S2MainMenu...NOT MainMenu.
=== HOW TO USE ACTIONSCRIPT TO EDIT GFX FILES ===
Method by GynDreams, Tutorial by usmc23.
First download all of this:
1. Reverse engineering and programming skills 
2. PHP (for the FLM decompiler)
3. MinGW GCC, especially CPP (the preprocessor for AS)
And than download your dev environment:
http://www.multiupload.com/UW0A2XX97V
Open your environment and for key path add: C:MinGwBin
Now...
We use PHP as a PREPROCESSOR to inject code into the flashscript assembly. Our high level actionscript code is in sc2.atl. Now here is a step by step tutorial on how to hook the singleplayer function into sc2.atl.
Open battle.net.flm, you will notice this code looks really messy and complicated so don't get scared. Find push r:1, 'GoToSinglePlayer', and under that isa function2, and under that is the code for it comment it out with a long comment /* and above end add */.
Now here is where our PHP injection comes to play. Add this line under function2, <?php GetFullFuncBody("sc2", "SinglePlayerMenu"); ?>. Sc2 is our class inside the sc2.atl, the next param is our function name we are going to use. So your new code looks like this:
<code>
push r:1, 'GoToSinglePlayer'
function2 () (r:1='this')
<?php GetFullFuncBody("sc2", "SinglePlayerMenu"); ?>
/*
push 'SC2'
getVariable
push 'Header'
getMember
push 'NavigationPanel'
getMember
push 'NavigationPanel'
getMember
push 'BUTTON_REPLAY'
getMember
push UNDEF, UNDEF, 'BATTLENET'
getVariable
push 'Invoke'
getMember
push 'FromUI'
getMember
push 'PAGE_SINGLE_PLAYER'
getMember
push 'Browser', 5, 'LIBRARY'
getVariable
push 'Browser'
getMember
push 'Browser'
getMember
push 'Show'
callMethod
pop
*/
end // of function
</code>
Open your ATL function and add this.
<code>
function SinglePlayerMenu()
{
_global.LIBRARY.Browser.Browser.Show("Browser", _global.BATTLENET.Invoke.FromUI.PAGE_SINGLE_PLAYER, undefined, undefined, _global.SC2.Header.NavigationPanel.NavigationPanel.BUTTON_REPLAY);
}
</code>
Open go.bat in a text editor and find:
set SC2_DIR=C:gamesstarcraft2Battle.net
Set that path accordinglly.
Finally run go.bat and when you open the singleplayer button it should do what it did before.
=== INTRO ===
The singleplayer UI art assets are in here: core.sc2mod/base.sc2data under the UI folder.
The singleplayer UI doesn't use actionscripts for native event calling but rather XML
scripts called .Sc2Layout. The SWF's in the are mostlly for eyecandy but may have some
other purpose as well. The button names in the XML determine what the button does, these
event are hard coded in the exe.
Singleplayer in the final game will only be able to be accessed through the battle.net user
interface. The battle.net.gfx has the singleplayer button seems to have the actionscript code
either missing or hidden.
When the beta first got leaked i first tried replacing the xml code from the ScreenMainMenu.Sc2Layout,
to BattleUI.sc2layout. The buttons show up but dont work because they dont have focus.
=== SO, WHAT DO WE KNOW? ===
== LOAD THE SINGLEPLAYER UI AND MOVE A BUTTON ==
<code>
eval LIBRARY.Browser.Browser.Load("Browser", "UI/Flash/Glue/S2MainMenu.swf", undefined, undefined, undefined, 0).
or
eval loadMovie("UI/Flash/Glue/S2MainMenu.swf", _root);
set _level0.DashBoard.m_browser.m_target2.m_loader.loader1.m_mainMenu.m_battleNetButton._x = 160
set _level0.DashBoard.m_browser.m_target2.m_loader.loader1.m_mainMenu.m_campaignButton._x = 160
set _level0.DashBoard.m_browser.m_target2.m_loader.loader1.m_mainMenu.m_exitGameButton._x = 160
set _level0.DashBoard.m_browser.m_target2.m_loader.loader1.m_mainMenu.m_optionsButton._x = 160
set _level0.DashBoard.m_browser.m_target2.m_loader.loader1.m_mainMenu.m_soloGameButton._x = 160
set _level0.DashBoard.m_browser.m_target2.m_loader.loader1.m_mainMenu.m_viewReplayButton._x = 160
</code>
== ENABLE SINGLEPLAYER BUTTON ==
To enable the singleplayer button you do open up the debug console and type this.
<code>
set _root.DashBoard.m_navigationPanel.m_singlePlayerButton._disabled=false
</code>
== DISPLAY A SWF MENU(NOT CORRECT BUT WORKS) ==
This has been common knownlege for awhile but we call up anyother menu we want by
doing this:
<code>
eval LIBRARY.Browser.Browser.Load("Browser", "UI/Flash/Glue/S2MainMenu.swf", undefined, undefined, undefined, 0).
</code>
The last integer paremetor when changed adds different backgrounds for the UI, but the problem is this function
creates a non fullscreen UI and doesnt call the actionscript inside of the SWF. But loads the SC2BetaLogo transition,
found in the swf.
We can compile ALL the singleplayer SWF's with the softhink decompiler and open them in flash.
We have also found out some buttons/UI's are just offscreen when there not in focus,
for example type this into console:
== LOAD A NEW SWF AND MOVE THE WINDOW POSITION) ==
<code>
eval LIBRARY.Browser.Browser.Load("Browser", "UI/Flash/Glue/S2SoloPlay.swf", undefined, undefined, undefined, 1, 1);
set _level0.DashBoard.m_browser.m_target2.m_loader.loader1.m_soloPlayMenu._y=0;
</code>
We shouldn't have to move the menu, we have to move it because its being displayed in a child window, the SWF should be loaded fullscreen, and the battle.net overlay removed.
=== WHAT WE NEED TO FIND ===
What we need to find is a function that loads a menu in fullscreen and hides the entire B.NET UI. |
|