November 07, 2024, 08:43:10 AM
Homepage
Home
Help
Search
Login
Register
Wiki
Imprint
Warhammer Dark Omen Forum
|
Modifications
|
Campaigns
(Moderator:
Malus
)
Cut-Scene Modding
Username
1 Hour
1 Day
1 Week
1 Month
Forever
Password
Pages: [
1
]
2
Go Down
Print
Author
Topic: Cut-Scene Modding (Read 32933 times)
0 Members and 1 Guest are viewing this topic.
aqrit
Developer
Offline
Posts: 85
Cut-Scene Modding
«
on:
November 29, 2013, 08:41:02 AM »
What is the current state of cut-scene modding?
Is the wiki up to date?
http://wiki.dark-omen.org/do/DO/WHMTG
Has anyone given thought to externalizing the .MTG file?
Logged
Ghabry
Developer
Offline
Posts: 1020
Re: Cut-Scene Modding
«
Reply #1 on:
November 29, 2013, 01:58:02 PM »
I had some thoughts about this. But havnt started working on this yet
My idea was to read some script.whmtg file using Mod Selector.
The file structure should look like this
http://pastebin.com/9mf0NfwD
without the line count at the beginning.
That file is assembled on mod loading and then written in WHMTG-binary format to memory (the memory location must be the same everytime because savegames reference it, e.g. using VirtualAllocEx). And then the hardcoded stuff pointing to WHMTG (e.g. New Campaign, Tutorial, Jump to Chapter x cheat) should be repointed to the new one.
Logged
aqrit
Developer
Offline
Posts: 85
Re: Cut-Scene Modding
«
Reply #2 on:
December 01, 2013, 08:51:54 AM »
Looks pretty much all figured out.
I doubt that the save file would have an absolute address store in it.
my guess is that "current position" in the script would be relative to "script start"
so I think it will not be necessary to load at the same memory address every time.
since pastebin has apparently banned my IP address from posting...
here is what things look like to me at this point in time.
//xrefs
004C3C48 // start of script ( 4C3C20 thru 4C3C244 == dead code? )
004CCD28 // end of script
004C3D48 // tutorial
004C3D68 // new campaign
004C3DA8 // Start game at chapter 2
004C3E40 // Start game at chapter 3
004C3F28 // Start game at chapter 4
004C4060 // Start game at chapter 5
//VA func, name, argc, args w/fixups
/////////////////////////////////////////////////////////////////////////
0x0041DB60, "WH_GOTO", 1, { 1 } // label
0x0041DB80, "WH_IF", 2, { }
0x0041DC30, "WH_ENDIF", 0, { }
0x0041DC60, "WH_ELSE", 0, { }
0x0041DC80, "WH_GOSUB", 1, { 1 } // label
0x0041DCD0, "WH_RETURN", 0, { }
0x0041DDF0, "WH_PUSHLV", 0, { }
0x0041DE10, "WH_POPLV", 0, { }
0x0041DD00, "WH_REPEAT", 0, { }
0x0041DD20, "WH_UNTIL", 2, { }
0x0041DED0, "WH_END", 0, { }
0x0041C920, "WH_PlayMovie", 1, { 1 } // ".tgq"
0x0041C970, "WH_MeetingPoint", 2, { 1, 2 } // ".bmp", label
0x0041CA00, "WH_TravelMap", 10, { 1, 2, 3 } // ".bmp", ".spr", ".dot"
0x0041CB10, "WH_Deploy", 0, { }
0x0041CB20, "WH_Battle", 2, { 1 } // "B1_01"
0x0041CDC0, "WH_GetUnitStatus", 1, { }
0x0041CE20, "WH_GetUnitHireStatus", 1, { }
0x0041CE80, "WH_AddUnit", 1, { }
0x0041CED0, "WH_RemoveUnit", 1, { }
0x0041DEE0, "WH_SetVariable", 2, { 1 } // var
0x0041DF00, "WH_ReadVariable", 1, { 1 } // var
0x0041D620, "WH_AddCash", 1, { }
0x0041D970, "WH_GameOver", 0, { }
0x0041DF20, "WH_ClearVariables", 2, { 1 } // var
0x0041CFB0, "WH_ForceUnit", 1, { }
0x0041CFF0, "WH_UnForceUnit", 1, { }
0x0041D040, "WH_ExcludeUnit", 1, { }
0x0041D080, "WH_IncludeUnit", 1, { }
0x0041D0D0, "WH_TemporyUnitSet", 1, { }
0x0041D120, "WH_TemporyUnitClear", 1, { }
0x0041D170, "WH_UnitIsGoingSet", 1, { }
0x0041D1C0, "WH_UnitIsGoingClear", 1, { }
0x0041CAB0, "WH_Book", 0, { }
0x0041C9D0, "WH_MeetingWait", 0, { }
0x0041CB40, "WH_InitDebrief", 2, { }
0x0041CB70, "WH_Debrief", 0, { }
0x0041CAE0, "WH_SaveGame", 0, { }
0x0041CC00, "WH_Delay", 1, { }
0x0041CCE0, "WH_Pause", 1, { }
0x0041CBE0, "WH_SetDeafultSaveName", 1, { 1 } // "text"
0x0041D640, "WH_AddMagic", 1, { }
0x0041D870, "WHMTG_DisplayBitmap", 3, { 1 } // ".bmp"
0x0041D8A0, "WHMTG_RemoveBitmap", 0, { }
0x0041D210, "WH_CheckObjective", 1, { }
0x0041D550, "WHMTG_Voice", 2, { 1 } // "VC001"
0x0041D8B0, "WHMTG_SpotAnim", 4, { }
0x0041D950, "WHMTG_ChooseInit", 0, { }
0x0041D740, "WHMTG_PlaySFX", 6, { 1, 2, 5 } // "stay", "continue", "H_KZ001"
0x0041D720, "WHMTG_StopSFX", 1, { }
0x0041D980, "WHMTG_StopAllSFX", 2, { }
0x0041D9A0, "WHMTG_PlayMusic", 1, { }
0x0041D9C0, "WHMTG_SetMusic", 1, { 1 } // ".fsm"
0x0041D9E0, "WHMTG_SetBackground", 0, { }
0x0041D2A0, "WHMTG_Speak", * // var arg???
0x0041D360, "WHMTG_SpeakNoWait", 1, { }
0x0041D420, "WHMTG_Narrate", 5, { 3 } // ".mad"
0x0041D410, "WHMTG_Wait", 1, { }
// not used ( guessed at args # )
0x0041DE30, "WH_DO", 1, { unknown }
0x0041DE20, "WH_SETLV", 1, { unknown }
0x0041DE60, "WH_LOOP", 0, {}
0x0041DEC0, "WH_BREAK", 0, {}
0x0041C910, "WH_Test", 1, { unknown }
0x0041D9B0, "WHMTG_StopMusic", 0, {}
0x0041D280, "WHMTG_AddBitmap", 1, { unknown }
0x0041D250, "WH_SetObjective", 2, { unknown }
0x0041D690, "WH_RemoveMagic", 1, { unknown }
0x0041CDA0, "WH_ShowMouse", 1, { unknown }
0x0041CD90, "WH_HideMouse", 0, {}
0x0041CBA0, "WH_Picture", 1, { unknown }
// not implemented
0x0041DA00, "WH_Narration"
0x0041DA10, "WH_WriteTextToFile"
0x0041DA20, "WH_SetUnitVar"
0x0041DA30, "WH_ReadUnitVar"
0x0041DA40, "WH_DisableAutosave"
0x0041DA50, "WHMTG_StartAnimAsync"
0x0041DA60, "WHMTG_StopAnim"
0x0041DA70, "WHMTG_PlayAnim"
0x0041DA80, "WHMTG_LoadHeads"
0x0041DA90, "WHMTG_ShowHead"
0x0041DAA0, "WHMTG_AddOption"
0x0041DAB0, "WHMTG_ChooseOption"
0x0041DAC0, "WHMTG_HideHead"
0x0041D9F0, "WHMTG_PlaySample"
0x0041DAD0, "WHMTG_PlaySampleNoWait"
0x0041DAE0, "WHMTG_LoadDots"
0x0041DB10, "WHMTG_PlayDots"
0x0041DB20, "WHMTG_WaitForDots"
0x0041DB30, "WHMTG_FinishDots"
0x0041DB40, "WHMTG_ContinuePrompt"
0x0041DAF0, "WHMTG_SetResult"
0x0041DB00, "WHMTG_RemoveBitmap"
0x0041DB50, "WHMTG_ResetDotList"
/////
int WHMTG_Narrate(
DWORD head_id
DWORD head_animiation_id
CHAR* psz_mad_name
DWORD unused // always 0 in script and ignored in func
DWORD keep_highlight
);
Logged
Ghabry
Developer
Offline
Posts: 1020
Re: Cut-Scene Modding
«
Reply #3 on:
December 01, 2013, 01:36:57 PM »
Most of them is already at
http://wiki.dark-omen.org/do/DO/WHMTG/OpCodes
The WHMTG struct starts in the savegame header at 0xBC and has a size of 0xDC
Some parts of the struct can be easily figured out by looking at a debug print function at 0x40ED80. Any idea what LV means?
The program counter is at 0x00 of the struct, the script entry point at 0x08. (my data could be wrong)
For my first savegame (saved before border counties mission) the entry point is
0x4C3D90 and PC 0x3A. But by looking at other savegames that data is always the same so I lack some information there :/
But you are right, it can't be hardcoded, you can e.g. load English savegames in a German Dark Omen version.
Logged
aqrit
Developer
Offline
Posts: 85
Re: Cut-Scene Modding
«
Reply #4 on:
December 01, 2013, 06:48:57 PM »
I saw that wiki page, I posted this here to show the arg count and arg types for the functions
the LV is "the" location that WH_IF, WH_UNTIL, and WH_ReadVariable, access... (as you know) ... state machine... Local Value maybe?
thanks for the info about the save file.
0xBC + 0x00 is the program counter
0xBC + 0x08 is the start script
0xBC + 0x0C is the end script
however the start script and end script are ignored. ( hex-edited them to 0xFFFFFFF )
so the exe must use its own values ( or possibly difference the two then align 4 and adjust :p )
004C3C48 + 3A * 4 = 004C3D30 ( aka right after the WH_SaveGame ln the english version )
004C3D90 is the script start in the german version?
«
Last Edit: December 01, 2013, 07:02:29 PM by aqrit
»
Logged
Ghabry
Developer
Offline
Posts: 1020
Re: Cut-Scene Modding
«
Reply #5 on:
December 01, 2013, 10:40:13 PM »
Okay I had something else for 0x0C, but yours looks more correct.
I compared 10 different savegames and excluding the stack (20 ints starting from 0x1C) they are all the same. (I dont think that the stack is used for loading) So the actual location is stored somewhere else
No idea where the script starts in the German version, never checked.
Logged
aqrit
Developer
Offline
Posts: 85
Re: Cut-Scene Modding
«
Reply #6 on:
December 02, 2013, 08:35:07 AM »
I checked, 004C3D90 is start script in the German version.
The save script is a sub-function so the relative return address [program counter] ( marking where we really are in the campaign ) is on the stack. The stack IS restored from the save file. The script entry points are hardcoded in the executable and need to be hooked.
«
Last Edit: December 02, 2013, 08:41:01 AM by aqrit
»
Logged
Ghabry
Developer
Offline
Posts: 1020
Re: Cut-Scene Modding
«
Reply #7 on:
December 02, 2013, 01:50:25 PM »
Can you extend this further? How is the address of that WHMTG "save script" sub-function?
Logged
aqrit
Developer
Offline
Posts: 85
Re: Cut-Scene Modding
«
Reply #8 on:
December 03, 2013, 12:56:13 AM »
I think we lost track of what each other are talking about...
I assume...
two sub-scripts can save the game one is 0x4C3C50 and the other is 0x4C3CF0
in a sav file the program counter will always point to after the call of WH_SaveGame in one of those two functions
when the script resumes at the program counter it will run until it hits the RETURN statement
in which case it pops the return address from the stack and continues from there.
just like a real function call
anyways,
here is a "compilable" dump of the default script
http://bitpatch.com/downloads/default_WHMGT.7z
now all we need is a compiler :p
edit: already found a bug: Voice has two args
though it seems the second one is ignored.
«
Last Edit: December 03, 2013, 02:12:33 AM by aqrit
»
Logged
Ghabry
Developer
Offline
Posts: 1020
Re: Cut-Scene Modding
«
Reply #9 on:
December 03, 2013, 03:21:31 AM »
I know how a stack works
. But thanks for the additional notes, now it makes more sense how the program counter gets the correct value.
The script dump looks great. Have to write an assembler for the mod selector now...
Minor nit-picking:
Can you replace the first argument of IF/UNTIL with !=, ==, <, >?
1: LV == val, 2: LV != val, 3: LV < val, 4: LV > val
And maybe a feature suggestion:
You probably noticed that ClearVariables overwrites 96 bytes at 0x00537FF0. [That is in the savegame header and I called that "Savegame progress struct".
You can view that one in the Wh32Edit header editor (also see
savegame header base
source)]
And all SetVariable/ReadVariable calls are (4 byte aligned) in that 96 bytes (SetVariable doesnt check where it writes *uugh*). Maybe use numbers from 0-23 instead of the hex values when a write is in that range. Makes editing the script easier.
«
Last Edit: December 03, 2013, 03:28:10 AM by Ghabry
»
Logged
aqrit
Developer
Offline
Posts: 85
Re: Cut-Scene Modding
«
Reply #10 on:
December 08, 2013, 03:27:59 AM »
https://github.com/Ghabry/Dark-Omen-Mod-Selector/pull/1
Script Compiler
Completely untested beyond the first mission.
I couldn't build the mod-selector with my C++ compiler,
so I'll leave it to Ghabry to hook it into that.
Code:
ImportScript( "whmtg.txt" );
also updated:
http://bitpatch.com/downloads/default_WHMGT.7z
with a new script and my quickly-made default script disassembler.
I'm sure some people are less than amused by the way I write C++...
but oh well.
edit:
If it is to be used "on-the-fly" then something needs to be changed about the VirtualProtect call in ImportScript()
where it installs its hooks
«
Last Edit: December 08, 2013, 04:38:38 AM by aqrit
»
Logged
Ghabry
Developer
Offline
Posts: 1020
Re: Cut-Scene Modding
«
Reply #11 on:
December 08, 2013, 12:34:47 PM »
My program should compile with Visual Studio 2010 (or newer).
I don't care much about code quality in that project, I'm just happy that it works
Quote
// so fun fact: OutputDebugString() isn't suitable
// because that gets spammed with complaints of heap corruption by dark omen / the kernel
Yes, the corruption spamming after battle end is great... I wonder why this doesnt crash
Update:
The compiler works for me, too. At least in the first mission, not tested further. Great work aqrit.
«
Last Edit: December 08, 2013, 07:57:55 PM by Ghabry
»
Logged
olly
Global Spokesperson
Offline
Posts: 2296
Re: Cut-Scene Modding
«
Reply #12 on:
December 08, 2013, 09:23:33 PM »
Amazing Script Compiler, many Thanks Aqrit! It will really open all sorts of possibilities for Dark Omen. So far, I've been shown how to mod the Tutorial map loading sequence, so it opens the Trading Post level instead.
LABEL TUTORIAL
ForceUnit 1
Deploy
Battle "B1_01" 21
GameOver
Logged
and back in Nuln, the ageing Graf Berhardt smiled his secret smile of pride whenever he heard the latest tales of his eldest son's ever growing chain of glorious victories -(sothr manual)
Ghabry
Developer
Offline
Posts: 1020
Re: Cut-Scene Modding
«
Reply #13 on:
December 08, 2013, 09:41:23 PM »
Dread King and his friends having a quick chat before attempting to conquer the world.
darktalk.jpg
(55.4 KB, 637x480 - viewed 901 times.)
Logged
Jeronimo
Night Goblin Shaman
Offline
Posts: 542
Re: Cut-Scene Modding
«
Reply #14 on:
December 09, 2013, 04:40:38 PM »
Good one Ghabry.
Logged
Pages: [
1
]
2
Go Up
Print
Jump to:
Please select a destination:
-----------------------------
Warhammer Dark Omen Community
-----------------------------
=> News
=> Tavern
===> Introduction
=> Website Related
-----------------------------
Warhammer Dark Omen
-----------------------------
=> Singleplayer
=> Multiplayer
===> Rules and Standards
===> Tournaments
===> Armybuilds
=====> Empire Armybuilds
=====> Greenskin Armybuilds
=====> Undead Armybuilds
===> Tactics
=====> Empire Tactics
=====> Greenskins Tactics
=====> Undeads Tactics
===> Dark Omen Expanded
===> Black Prophecy (Dark Omen Mod)
=> Help Section
=> Tactical wargaming and other Warhammer games
-----------------------------
Multiplayer Campaign
-----------------------------
=> Dark Omen Conquest
-----------------------------
The Remake Project
-----------------------------
=> OMG WARTBED
=> Bright Portents
=> General Suggestions
-----------------------------
Modifications
-----------------------------
=> 3D Scenery Models
=> Maps
=> 2D Sprites
=> Troops
=> Tools
=> Campaigns
Loading...