22using System . Collections . Generic ;
33using System . IO ;
44using System . Linq ;
5+ using System . Net ;
56using System . Text ;
67using System . Threading . Tasks ;
78using Newtonsoft . Json ;
@@ -34,7 +35,11 @@ public void Run(string[] args)
3435 {
3536 // This file ended up being more than just cond testing, but hack pile of one-time
3637 // scripts still basically applies to these as well.
37- if ( args . Contains ( "gen" ) )
38+ if ( args . Contains ( "ac6" ) )
39+ {
40+ DumpAc6Unknown ( ) ;
41+ }
42+ else if ( args . Contains ( "gen" ) )
3843 {
3944 DumpEldenNew ( args ) ;
4045 }
@@ -48,20 +53,21 @@ public void Run(string[] args)
4853 }
4954 }
5055
56+ private static readonly Dictionary < string , int > Types = new Dictionary < string , int > ( )
57+ {
58+ [ "byte" ] = 0 ,
59+ [ "ushort" ] = 1 ,
60+ [ "uint" ] = 2 ,
61+ [ "sbyte" ] = 3 ,
62+ [ "short" ] = 4 ,
63+ [ "int" ] = 5 ,
64+ [ "float" ] = 6 ,
65+ } ;
66+ private static readonly Dictionary < int , string > RevTypes = Types . ToDictionary ( e => e . Value , e => e . Key ) ;
67+
5168 public void DumpTypes ( )
5269 {
5370 InstructionDocs docs = new InstructionDocs ( "er-common.emedf.json" ) ;
54- Dictionary < string , int > types = new Dictionary < string , int > ( )
55- {
56- [ "byte" ] = 0 ,
57- [ "ushort" ] = 1 ,
58- [ "uint" ] = 2 ,
59- [ "sbyte" ] = 3 ,
60- [ "short" ] = 4 ,
61- [ "int" ] = 5 ,
62- [ "float" ] = 6 ,
63- } ;
64- Dictionary < int , string > revTypes = types . ToDictionary ( e => e . Value , e => e . Key ) ;
6571 SortedDictionary < ( string , string ) , List < string > > cmdsByType = new SortedDictionary < ( string , string ) , List < string > > ( ) ;
6672 foreach ( EMEDF . ClassDoc bank in docs . DOC . Classes . OrderBy ( i => i . Index ) )
6773 {
@@ -71,7 +77,7 @@ public void DumpTypes()
7177 string name = instr . DisplayName ;
7278 foreach ( EMEDF . ArgDoc arg in instr . Arguments )
7379 {
74- string type = revTypes [ ( int ) arg . Type ] ;
80+ string type = RevTypes [ ( int ) arg . Type ] ;
7581 if ( arg . EnumName == null && type != "float" )
7682 {
7783 var key = ( arg . Name , type ) ;
@@ -120,24 +126,11 @@ public void DumpEldenUnknown()
120126 }
121127 }
122128
123- public void DumpEldenNew ( ICollection < string > opt )
129+ private EMEDF . ArgDoc ParseArgType ( string text )
124130 {
125- doc = EMEDF . ReadFile ( $ "DarkScript3/Resources/er-common.emedf.json") ;
126- Dictionary < string , int > types = new Dictionary < string , int > ( )
127- {
128- [ "byte" ] = 0 ,
129- [ "ushort" ] = 1 ,
130- [ "uint" ] = 2 ,
131- [ "sbyte" ] = 3 ,
132- [ "short" ] = 4 ,
133- [ "int" ] = 5 ,
134- [ "float" ] = 6 ,
135- // ["uint"] = 8,
136- } ;
137- Dictionary < int , string > revTypes = types . ToDictionary ( e => e . Value , e => e . Key ) ;
138131 string getType ( string prefix )
139132 {
140- foreach ( KeyValuePair < string , int > type in types )
133+ foreach ( KeyValuePair < string , int > type in Types )
141134 {
142135 if ( prefix . StartsWith ( type . Key + " " ) ) return type . Key ;
143136 }
@@ -151,11 +144,41 @@ EMEDF.EnumDoc getEnum(string prefix)
151144 }
152145 return null ;
153146 }
147+ string desc = text . Split ( '=' ) [ 0 ] . Trim ( ) ;
148+ EMEDF . EnumDoc enumDoc = null ;
149+ string type = getType ( desc ) ;
150+ if ( type == null )
151+ {
152+ enumDoc = getEnum ( desc ) ;
153+ if ( enumDoc == null ) throw new Exception ( $ "Can't parse { text } ") ;
154+ desc = desc . Substring ( enumDoc . Name . Length ) . Trim ( ) ;
155+ type = getType ( desc ) ;
156+ if ( type == null ) throw new Exception ( $ "Can't parse type in { text } ") ;
157+ }
158+ desc = desc . Substring ( type . Length ) . Trim ( ) ;
159+ EMEDF . ArgDoc argDoc = new EMEDF . ArgDoc
160+ {
161+ Name = desc ,
162+ Type = Types [ type ] ,
163+ EnumName = enumDoc ? . Name ,
164+ Default = desc == "Number of Target Characters" ? 1 : 0 ,
165+ Min = 0 ,
166+ Max = 0 ,
167+ Increment = 0 ,
168+ FormatString = type == "float" ? "%0.3f" : "%d" ,
169+ } ;
170+ if ( argDoc . Name == "Parameters" ) argDoc . Vararg = true ;
171+ return argDoc ;
172+ }
173+
174+ public void DumpEldenNew ( ICollection < string > opt )
175+ {
176+ doc = EMEDF . ReadFile ( $ "DarkScript3/Resources/er-common.emedf.json") ;
154177 string getArgKey ( EMEDF . ArgDoc argDoc )
155178 {
156179 List < string > parts = new List < string > ( ) ;
157180 if ( argDoc . EnumName != null ) parts . Add ( argDoc . EnumName ) ;
158- if ( ! revTypes . TryGetValue ( ( int ) argDoc . Type , out string typeName ) ) throw new Exception ( $ "Unknown type in { argDoc . Name } : { argDoc . Type } ") ;
181+ if ( ! RevTypes . TryGetValue ( ( int ) argDoc . Type , out string typeName ) ) throw new Exception ( $ "Unknown type in { argDoc . Name } : { argDoc . Type } ") ;
159182 parts . Add ( typeName ) ;
160183 parts . Add ( argDoc . Name ) ;
161184 return string . Join ( " " , parts ) ;
@@ -213,40 +236,16 @@ string getMinorDetailDesc(EMEDF.ArgDoc argDoc)
213236 }
214237 EMEDF . ArgDoc getArg ( string text , string debugInfo = "" )
215238 {
216- string desc = text . Split ( '=' ) [ 0 ] . Trim ( ) ;
217- EMEDF . EnumDoc enumDoc = null ;
218- string type = getType ( desc ) ;
219- if ( type == null )
220- {
221- enumDoc = getEnum ( desc ) ;
222- if ( enumDoc == null ) throw new Exception ( $ "Can't parse { text } ") ;
223- desc = desc . Substring ( enumDoc . Name . Length ) . Trim ( ) ;
224- type = getType ( desc ) ;
225- if ( type == null ) throw new Exception ( $ "Can't parse type in { text } ") ;
226- }
227- desc = desc . Substring ( type . Length ) . Trim ( ) ;
228- EMEDF . ArgDoc argDoc = new EMEDF . ArgDoc
229- {
230- Name = desc ,
231- Type = types [ type ] ,
232- EnumName = enumDoc ? . Name ,
233- // TODO: Definitely make this non-zero when required
234- Default = desc == "Number of Target Characters" ? 1 : 0 ,
235- // TODO: Fill these in
236- Min = 0 ,
237- Max = 0 ,
238- Increment = 0 ,
239- FormatString = type == "float" ? "%0.3f" : "%d" ,
240- } ;
239+ EMEDF . ArgDoc argDoc = ParseArgType ( text ) ;
241240 // It seems enums don't get default values etc.
242241 if ( argDoc . EnumName == null )
243242 {
244243 string argKey = getArgKey ( argDoc ) ;
245244 EMEDF . ArgDoc old = null ;
246- if ( ! desc . StartsWith ( "Unknown" ) )
245+ if ( ! argDoc . Name . StartsWith ( "Unknown" ) )
247246 {
248247 exampleDocs . TryGetValue ( argKey , out old ) ;
249- if ( old == null && type == "uint" && desc . EndsWith ( "Entity ID" ) )
248+ if ( old == null && RevTypes [ ( int ) argDoc . Type ] == "uint" && argDoc . Name . EndsWith ( "Entity ID" ) )
250249 {
251250 exampleDocs . TryGetValue ( "uint Target Entity ID" , out old ) ;
252251 }
@@ -352,6 +351,129 @@ public void RunEldenTests(IList<string> args)
352351 }
353352 }
354353
354+ public void DumpAc6Unknown ( )
355+ {
356+ InstructionDocs docs = new InstructionDocs ( "er-common.emedf.json" ) ;
357+ doc = docs . DOC ;
358+ SortedSet < ( int , int ) > used = new ( ) ;
359+ Dictionary < ( int , int ) , int > bad = new ( ) ;
360+ Dictionary < ( int , int ) , SortedSet < int > > badBytes = new ( ) ;
361+ string dir = @"C:\Program Files (x86)\Steam\steamapps\common\ARMORED CORE VI FIRES OF RUBICON\Game\event" ;
362+ foreach ( string path in Directory . GetFiles ( dir , "*.emevd.dcx" ) )
363+ {
364+ string fileName = Path . GetFileName ( path ) ;
365+ emevd = EMEVD . Read ( path ) ;
366+ foreach ( EMEVD . Event e in emevd . Events )
367+ {
368+ Dictionary < EMEVD . Parameter , string > pn = e . Parameters . ToDictionary ( p => p , p => $ "X{ p . SourceStartByte } _{ p . ByteCount } ") ;
369+ for ( int i = 0 ; i < e . Instructions . Count ; i ++ )
370+ {
371+ EMEVD . Instruction ins = e . Instructions [ i ] ;
372+ var insId = ( ins . Bank , ins . ID ) ;
373+ used . Add ( insId ) ;
374+ try
375+ {
376+ EMEDF . InstrDoc instrDoc = doc [ ins . Bank ] [ ins . ID ] ;
377+ List < object > args = docs . UnpackArgsWithParams (
378+ ins , i , instrDoc , pn , ( argDoc , val ) => argDoc . GetDisplayValue ( val ) ) ;
379+ }
380+ catch ( Exception ex )
381+ {
382+ int len = ins . ArgData . Length / 4 ;
383+ bad [ insId ] = len ;
384+ if ( ! badBytes . ContainsKey ( insId ) ) badBytes [ insId ] = new ( ) ;
385+ for ( int k = 0 ; k < ins . ArgData . Length ; k ++ )
386+ {
387+ if ( ins . ArgData [ k ] != 0 )
388+ {
389+ badBytes [ insId ] . Add ( k ) ;
390+ }
391+ }
392+ }
393+ }
394+ }
395+ }
396+ foreach ( var insId in used )
397+ {
398+ ( int bank , int id ) = insId ;
399+ string insStr = InstructionDocs . FormatInstructionID ( bank , id ) ;
400+ string name = $ "XUnknown { insStr } ";
401+ List < string > args ;
402+ if ( bad . TryGetValue ( insId , out int len ) )
403+ {
404+ bool init = bank == 2000 && ( id == 7 || id == 8 ) ;
405+ if ( init ) len = 3 ;
406+ ISet < int > bytes = badBytes [ insId ] ;
407+ string byteChar ( int i ) => bytes . Contains ( i ) ? "X" : "0" ;
408+ string bytesChar ( int i ) => $ "{ byteChar ( i ) } { byteChar ( i + 1 ) } { byteChar ( i + 2 ) } { byteChar ( i + 3 ) } ";
409+ args = Enumerable . Range ( 0 , len ) . Select ( i => $ "uint Unknown{ i * 4 } _{ bytesChar ( i * 4 ) } ") . ToList ( ) ;
410+ if ( bank < 100 )
411+ {
412+ args . RemoveAt ( 0 ) ;
413+ int maxByte = bytes . Where ( x => x < 4 ) . OrderByDescending ( x => x ) . FirstOrDefault ( ) ;
414+ for ( int i = maxByte ; i >= 0 ; i -- )
415+ {
416+ string s = i == 0 ? "Condition Group sbyte Result Condition Group" : $ "sbyte Unknown{ i } _{ byteChar ( i ) } ";
417+ args . Insert ( 0 , s ) ;
418+ }
419+ }
420+ else if ( init ) args [ 2 ] = "uint Parameters" ;
421+ }
422+ else
423+ {
424+ EMEDF . InstrDoc instrDoc = doc [ bank ] [ id ] ;
425+ name = instrDoc . Name ;
426+ args = instrDoc . Arguments . Select ( a => ( a . EnumName == null ? "" : $ "{ a . EnumName } ") + $ "{ RevTypes [ ( int ) a . Type ] } { a . Name } ") . ToList ( ) ;
427+ }
428+ Console . WriteLine ( $ "{ insStr } , { name } { string . Join ( "" , args . Select ( s => $ ", { s } ") ) } ") ;
429+ }
430+ }
431+
432+ public void AddUnknownValues ( EMEDF emedf , string csv )
433+ {
434+ doc = emedf ;
435+ foreach ( string line in File . ReadAllLines ( csv ) )
436+ {
437+ string [ ] cells = line . Split ( "," ) . Select ( s => s . Trim ( ) ) . ToArray ( ) ;
438+ string cmd = cells [ 0 ] ;
439+ int bank , id ;
440+ try
441+ {
442+ ( bank , id ) = InstructionDocs . ParseInstructionID ( cmd ) ;
443+ }
444+ catch ( FormatException )
445+ {
446+ continue ;
447+ }
448+ string name = cells [ 1 ] . Trim ( new [ ] { '?' , ' ' } ) ;
449+ List < EMEDF . ArgDoc > args = cells . Skip ( 2 )
450+ . Where ( c => ! string . IsNullOrWhiteSpace ( c ) )
451+ . Select ( c => ParseArgType ( c ) )
452+ . ToList ( ) ;
453+ EMEDF . ClassDoc classDoc = doc [ bank ] ;
454+ if ( classDoc == null )
455+ {
456+ doc . Classes . Add ( new EMEDF . ClassDoc { Name = "Unk" , Index = bank , Instructions = new ( ) } ) ;
457+ }
458+ EMEDF . InstrDoc instrDoc = doc [ bank ] [ id ] ;
459+ if ( instrDoc == null )
460+ {
461+ instrDoc = new EMEDF . InstrDoc
462+ {
463+ Name = name ,
464+ Index = id ,
465+ Arguments = args . ToArray ( ) ,
466+ } ;
467+ doc [ bank ] . Instructions . Add ( instrDoc ) ;
468+ }
469+ }
470+ doc . Classes = doc . Classes . OrderBy ( x => x . Index ) . ToList ( ) ;
471+ foreach ( EMEDF . ClassDoc classDoc in doc . Classes )
472+ {
473+ classDoc . Instructions = classDoc . Instructions . OrderBy ( x => x . Index ) . ToList ( ) ;
474+ }
475+ }
476+
355477 public void ValidateEmedf ( ICollection < string > opt )
356478 {
357479 InstructionDocs docs = new InstructionDocs ( "er-common.emedf.json" ) ;
0 commit comments