
    UHjB)                       d Z ddlmZ ddlZddlZddlZddlZddlZddlm	Z	 ddl
mZmZ ddlmZ  e	e      j!                         j"                  d   Zedz  Zed	z  Zd
ZdZdZdZdZdZdZdZdZdZdZdZ dZ!dZ"dZ#dZ$dZ%d'dZ&d(dZ'd)dZ(d)dZ)d)dZ*d)dZ+d*d Z,efd+d!Z-d,d"Z.d,d#Z/d-d$Z0d.d%Z1e2d&k(  r e1        yy)/zJSummarize the original executable's GetTickCount-driven frame timing loop.    )annotationsN)Path)read_sectionsva_to_offset)parse_imports   outzHwanse2.exeidZ iF@ i|@ i@ i[@ i|Y iY iY iY i@ i@ i7@ 0            c                    | y d| dS )N0x08x )values    5/home/exedev/hwanse/tools/summarize_runtime_timing.pyhex32r   '   s    }c{    c                ^    t        ||      }|t        dt        |       d      | |||z    S )NzVA z is outside raw sections)r   
ValueErrorr   )exesectionsvasizeoffsets        r   read_atr   -   s=    (B'F~3uRyk)ABCCvv}%%r   c                $    t        | ||d      d   S )Nr   r   )r   r   r   r   s      r   read_u8r    4   s    3"a(++r   c           	     L    t        j                  dt        | ||d            d   S )N<Ir   r   )structunpackr   r   s      r   read_u32r%   8   s#    ==wsHb!<=a@@r   c           	         t        | ||      }|dk7  rt        dt        |             t        j                  dt        | ||dz   d            d   }|dz   |z   S )N   zexpected near call at z<ir   r   r   r   )r    r   r   r#   r$   r   )r   r   r   opcoderels        r   rel32_targetr*   <   s`    S(B'F~1%)=>>
--gc8R!VQ?
@
CC6C<r   c                    t        | ||d      }|d d dk7  rt        dt        |             t        j                  d|dd        d   S )N      s   zexpected indirect call at r"   r   )r   r   r   r#   r$   )r   r   r   bodys       r   indirect_call_targetr/   D   sS    3"a(DBQx;5eBi[ABB==tABx(++r   c                    | j                  d      xs g D ]I  }|j                  d      xs g D ]/  }|j                  d      |k(  sd|j                  d      i|c c S  K t        d| d      )Nimports	functionsnamedllzimport z
 not found)getr   )r1   r3   r4   fns       r   find_importr7   K   sz    {{9%+ 5''+&," 	5Bvvf~%swwu~444	55 wtfJ/
00r   c                \   | j                         }t        |      }t        |       }t        |d      t        t
        t        g}|D cg c]  }t        |||       }}t        ||t        d      }|d d dk7  rt        dt        t                     t        j                  d|dd       d   }t        j                  d|dd       d   }	t        ||t        dz         }
t        ||t         dz         }t#        ||t$              }|	rd	|	z  nd}|	t&        z  }|	t(        z  }t+        |       j-                  d
      j-                  d      t        j-                  d            |D cg c]  }t        |       c}t/        fd|D              ddt        t              dt        t              t        |      |	t        t0              t        t2              t        t4              t7        |
|      t        t              t        t               gt        t$              t        |      t9        |d      |	t7        |
|      z  dt:        t&        |t(        |t9        |d	z  d      ddd|	t<        k(  |t>        k(  |
t@        k(  xr	 |t@        k(  j-                  d      tB        k(  dddd}|S c c}w c c}w )NGetTickCount
   r-   s   z!expected frame interval write at r"   r,   r   i  r4   r3   iatVac              3  d   K   | ]'  }|j                  d       cxk(  xr	 t        k(  nc  ) yw)r;   N)r5   GET_TICK_IAT).0targetget_ticks     r   	<genexpr>z build_summary.<locals>.<genexpr>l   s(     )u^d&HLL4I*Y\*Y*Y)us   -0)r4   r3   iatVaHexdirectTextCallRefsallCallTargetsMatchIat
0x00401850
0x00401965r   )setupFunctionVaHextimingStartVaHexwaitLoopVaHexframeIntervalWriteVaHexframeIntervalGlobalHexframeIntervalMslastTickGlobalHexelapsedGlobalHexframeCountGlobalHexframeCapframeCapCompareVasupdateCallVaHexupdateTargetVaHex
nominalFpscatchUpWindowMsz&actor-controller-tile-mutation-derivedF)playerWalkFramesplayerMovingFrameshistoricalFourMovingFrameStepMsplayerTileStepCommandscurrentWebDefaultTileStepMs currentWebDefaultTileStepSecondsmappingClassexactActorConsumerStillInferred)frameIntervalMatchesExpected"frameIntervalGlobalMatchesExpectedframeCapMatchesExpectedgetTickIatMatchesExpectedzmovement-timing-groundeda.  The original executable uses KERNEL32!GetTickCount around the main update loop and stores a 0x30 ms frame interval at 0x0059e37c. The loop waits until elapsed time covers the current frame count, computes a catch-up count, caps it at 3, and calls 0x00411476 with that count. The browser runtime therefore uses 48 ms as the original timing tick and, with the actor-controller tile mutation evidence from runtime_movement, maps one actor-controller pass to one tile step. The old four-moving-frame 192 ms browser default is retained only as historical context.)source	timingApiloop
webMappingverificationpromotionStatus
conclusion)"
read_bytesr   r   r7   TIMING_INIT_CALLTIMING_LOOP_CALLTIMING_INTERPOLATION_CALLr/   r   FRAME_MS_WRITEr   r   r#   r$   r    FRAME_CAP_COMPARE_AFRAME_CAP_COMPARE_Br*   UPDATE_CALLPLAYER_MOVING_FRAMESPLAYER_TILE_STEP_COMMANDSstrr5   allLAST_TICK_GLOBALELAPSED_MS_GLOBALFRAME_COUNT_GLOBALminroundPLAYER_WALK_FRAMESEXPECTED_FRAME_MSFRAME_INTERVAL_GLOBALEXPECTED_FRAME_CAPr=   )exe_pathr   r   r1   
call_sitesr   call_targetsframe_writeframe_globalframe_mscap_acap_bupdate_targetnominal_fpshistorical_four_frame_walk_mscurrent_tile_step_mssummaryr@   s                    @r   build_summaryr   S   s   



CS!HH%G7N3H"$46OPJFPQ(h;QLQ#x<K2A+%<U>=R<STUU=={1Q'78;L}}T;q#45a8HC#6#:;EC#6#:;E h<M%-$/1K$,/C$C!#&??h-<<&LL(hll7347A"B59"B&))uht)u&u
 #/ %&6 7)',^'<&+L&9'!&'7!8 %&7 8#();#<E5)#()<#=uEX?Y"Z$[1!&}!5Q/'#eU*;;
$ !3"6/L&?+?056JT6QST0UD/4	
 -58I,I2>BW2W',0B'B'buPbGb)1g)>,)N	
 6gY3Gh NA R$ #Cs   	J$'J)c                   | d   }| d   }| d   }ddd|d    d|d	    d
|d    dddj                  d |d   D               d|d    d|d    d|d    dd|d    dd|d    dd|d    d|d    dd|d     d!|d"    d#|d    d$d%|d&    d!|d'    d(|d    d$d)|d*    d+| d,    dd| d-   dd.dd/d0g}| d1   j                         D ]  \  }}|j                  d2| d3| d4        |j                  d       d5j                  |      S )6Nrc   rd   re   z# Runtime Timing z- timing API: `r4   !r3   z` IAT `rB   `z- GetTickCount refs: , c              3  (   K   | ]
  }d | d   yw)r   Nr   r>   refs     r   rA   zmarkdown.<locals>.<genexpr>   s     )]AcU!*)]s   rC   z- frame interval: `rL   z` ms from `rJ   z` -> `rK   z- nominal tick rate: `rT   z` fpsz- frame count cap: `rP   z- update call: `rR   rS   z- web tile step: `rZ   z` ms (rY    actor-controller command * z ms)z- historical four-frame step: `rX   rW    moving frames * z*- actor movement consumer still inferred: r]   z- status: `rg   rh   z## Verificationz| check | value |z| --- | --- |rf   z| z | z |
)joinitemsappend)r   timingrd   mappinglineskeyr   s          r   markdownr      s+   [!F6?Dl#G

&-&.)9
AS@TTUV
		)]G[@\)] ]^_
d#456k$G`BaAbbhim  oG  jH  iI  IJ  	K
 l!3 4E:
tJ/02
4 1236$?R:S9TTUV
W%BCDF7SkKlJm  nJ  KO  Pa  Kb  Jc  cg  	h
)'2S*T)UU[\cdx\y[z  {L  MQ  Rc  Md  Le  ei  	j
4W=^5_4`a
g/013


'E* n-335 -
Ur#c%+,-	LL99Ur   c                   | d   }| d   }| d   }dj                  d | d   j                         D              }dj                  ddd	d
dt        j                  |d          dt        j                  |d          d|d    dddj                  d |d   D               dd|d    d|d    d|d    d|d    d	d|d     d!|d"    d#|d    d$d%|d&    d!|d'    d(|d    d$d)|d*    dd+t        j                  | d,          dd-d.|d/g      S )0Nrc   rd   re   r   c           	   3     K   | ]?  \  }}d t        j                  |       dt        j                  t        |             d A yw)z<tr><td>z	</td><td>z
</td></tr>Nhtmlescapers   )r>   r   r   s      r   rA   zhtml_page.<locals>.<genexpr>   sC      C 4;;s#$Idkk#e*.E-FjQs   AArf   z%<!doctype html><meta charset='utf-8'>z<title>Runtime Timing</title>z<style>body{font-family:system-ui,sans-serif;margin:24px;line-height:1.45;max-width:980px}table{border-collapse:collapse}th,td{border:1px solid #ddd;padding:6px 8px;text-align:left}th{background:#f4f4f4}code{white-space:nowrap}</style>z<h1>Runtime Timing</h1>z<p><b>Timing API:</b> <code>r4   r   r3   z</code> IAT <code>rB   z</code></p>z<p><b>GetTickCount refs:</b> r   c              3  `   K   | ]&  }d t        j                  t        |             d ( yw)z<code>z</code>Nr   r   s     r   rA   zhtml_page.<locals>.<genexpr>   s/       2C^aF4;;s3x;P:QQX2Y  2Cs   ,.rC   z</p>z<p><b>Frame interval:</b> rL   z ms at <code>rK   z</code>; <b>nominal tick:</b> rT   z fps; <b>catch-up cap:</b> rP   z<p><b>Web tile step:</b> rZ   z	 ms from rY   r   z ms.</p>z&<p><b>Historical four-frame step:</b> rX   rW   r   z+<p>actor movement consumer still inferred: r]   z<p>rh   z<h2>Verification</h2>zB<table><thead><tr><th>check</th><th>value</th></tr></thead><tbody>z</tbody></table>)r   r   r   r   )r   r   rd   r   checkss        r   	html_pager      s%   [!F6?Dl#GYY !.1779 F 99/' 	v!
&t{{6%='A&B!DKKPVW]P^D_C``rsy  {E  tF  sG  GR  	S
'		  2Cek  mA  fB  2C  )C  (D  DH  	I
$T*;%<$=]4PhKiJj k  $\ 233NtT^O_N``d	f
#G,I$J#K9U\]uUvTw  xT  UY  Zk  Ul  Tm  mu  	v
09Z1[0\\efm  oC  gD  fE  EV  W[  \m  Wn  Vo  ow  	x
5g>_6`5aaef
dkk',/016L!  r   c                    |j                  dd       |dz  j                  t        j                  | dd      dz   d	       |d
z  j                  t	        |       d	       y )NT)parentsexist_okzruntime_timing.jsonFr-   )ensure_asciiindentr   zutf-8)encodingruntime_timing.html)mkdir
write_textjsondumpsr   )r   out_dirs     r   write_outputsr      sc    MM$M.$$00

7q9D@ 1  $$0071Cg0Vr   c                 T   t        j                  t              } | j                  dt        t
               | j                  dt        t               | j                         }t        |j                        }t        ||j                         t        d|j                  dz          y )N)descriptionz--exe)typedefaultz	--out-dirzwrote runtime timing -> r   )argparseArgumentParser__doc__add_argumentr   EXEOUT
parse_argsr   r   r   r   print)parserargsr   s      r   mainr      s    $$9F
dC8
$<DDHH%G'4<<(	$T\\4I%I$J
KLr   __main__)r   z
int | Nonereturnz
str | None)
r   bytesr   
list[dict]r   intr   r   r   r   )r   r   r   r   r   r   r   r   )r1   dictr3   rs   r   r   )r~   r   r   r   )r   r   r   rs   )r   r   r   r   r   None)r   r   )3r   
__future__r   r   r   r   mathr#   pathlibr   probe_exe_scene_tablesr   r   summarize_exe_importsr   __file__resolver   ROOTr   r   r=   rj   rk   rl   rm   r|   rw   rv   ru   rp   rn   ro   r{   r}   rz   rq   rr   r   r   r    r%   r*   r/   r7   r   r   r   r   r   __name__r   r   r   <module>r      s   P "       > / H~''*
Ul
]  & "             &,A,1 $' FR>8WM zF r   