
    Jj/                        d Z ddlmZ ddlZddlmZ ddlmZ ddlm	Z	m
Z
  ee      j                         j                  d   Zedz  Zed	z  Zdd
ZdddZddZddZddZedk(  r e e             y)zHBuild a focused review of the DirectDraw palette buffer/copy/apply path.    )annotationsN)Path)Any)read_sectionsva_to_offset   outHwanse2.exec                    | y d| dS )N0x08x )values    &tools/build_palette_pipeline_review.pyhxr      s    }c{    c                    t        ||      }|t        |      d d ddS | |||z    }t        |      t        |      |j                  d      ddS )NF)vaHexfileOffsetHexbytes	available T)r   r   hex)exesectionsvasizeoffsetblobs         r   	exe_bytesr       se    (B'F~V!	
 	
 v&DBF#	 r   c                v    g d}|D cg c]  \  }}}}i t        | |||      ||d c}}}}S c c}}}}w )N))iX\A    zpalette header versionz1writes 0x0300 to the palette header at 0x004676e4)ib\A r"   zpalette entry countz9writes 0x0100 to palette header +2, grounding 256 entries)ih\A    zpalette entries pointerzAsets 0x004676e8 to palette header +4, the first PALETTEENTRY byte)i\A 
   zPC flag byte loopz:writes byte 0x04 to entry flag byte for entries 0x0a..0xf5)i.eA r"   zCreatePalette callz5calls IDirectDraw::CreatePalette through vtable +0x14)iUeA r"   zprimary SetPalette callzHattaches the created palette to the primary surface through vtable +0x7c)ieA r"   zrange apply wrapperz8calls the SetEntries helper for range start 0 count 0xff)i!fA    zSetEntries source pointerzBcomputes 0x004676e8 + start * 4 as the PALETTEENTRY source pointer)iIfA r"   zSetEntries call A9calls IDirectDrawPalette::SetEntries through vtable +0x18)iwfA r"   zSetEntries helper Bz;second range-apply helper used by VM/deferred palette paths)igA r"   zSetEntries call Br&   )izgA r#   zcopy red channelzCcopies caller/source red byte into the current palette entry buffer)igA r#   zcopy green channelzEcopies caller/source green byte into the current palette entry buffer)igA r#   zcopy blue channelzDcopies caller/source blue byte into the current palette entry buffer)igA r"   zcopy then applyz<calls the range SetEntries helper after RGB bytes are copied)iVhA r"   zGetEntries callzDreads current palette entries through IDirectDrawPalette::GetEntries)labelmeaning)r    )r   r   rowsr   r   r'   r(   s          r   byte_evidencer*   )   sR    aDH )- $BeW 	S9S(B-R'R  s   !3
c                 ^   t         j                         } t        |       }t        | |      }|D ci c]  }t	        |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g}dddddddd ddd!d"d#ddd$d%d&ddg}d'd(g d)d*d+d,d-d.d/d0d1d2dd!gd$t        |      d3d4d+d5d6d7d,d8d9d7d-d:d;d7d<d=d>d7g||d?d@gdAdBdCdD|t         j                         |j                  dEi       j                  dF      dGu |j                  di       j                  dF      dGu |j                  di       j                  dF      dGu |j                  di       j                  dF      dGu |j                  dHi       j                  dF      dGu dGdIdJdKdLdMdNdOdPdMdQdRdSdMgg dTdUS c c}w )VNr   
0x0041652ezIDirectDraw::CreatePalette0x14z.flags=0x04, entries=0x004676e8, out=0x004676c4zKcreates the 8-bit DirectDraw palette object from the EXE-owned entry buffer)r   methodvtableOffsetHex	argumentsrole
0x00416555zIDirectDrawSurface::SetPalette0x7cz9surface=primary wrapper at 0x0055abd8, palette=0x004676c4z>attaches the DirectDraw palette to the primary display surface
0x00416649zIDirectDrawPalette::SetEntries0x18z:start/count from helper args, entries=0x004676e8 + start*4zAapplies a current-palette range after computing the entry pointer
0x00416708z9second range apply path used after palette VM/list writes
0x00416856zIDirectDrawPalette::GetEntries0x20zreads entries into EXE bufferz palette snapshot/readback helper
0x00415c53zpalette buffer initializerzjinitializes a DD-style palette header, 256-entry count, entry pointer, and PC flags for entries 0x0a..0xf5grounded)r   nameeffectstatus
0x004165b8zrange SetEntries helper Azhoptionally reattaches the palette to the primary surface, then applies a range from 0x004676e8 + start*4
0x00416677zrange SetEntries helper BzQsame range-apply class as A; this one is reached by deferred palette update paths
0x00416736zRGB copy then SetEntrieszacopies count RGB triples into the current palette entry buffer, then calls the range apply helperzhwanse-palette-pipeline-reviewz'palette-buffer-copy-apply-path-grounded)r
   zout/directdraw_flow.jsonz0web/map_animation_execution_boundary_review.htmlz(tools/build_map_animation_tile_review.pyz640x480x8 indexed color
0x004676c4
0x004676e4
0x004676e8      zR, G, B, flagsz
0x0a..0xf50x04zThe EXE keeps a mutable 256-entry palette buffer at 0x004676e8. Palette effects copy or step RGB bytes inside that buffer, then push a range to DirectDraw with SetEntries. This is a color/fade/ramp pipeline, not proof of tile-position animation.)displayModepaletteObjectGlobalpaletteHeaderGlobalpaletteEntriesGlobal
entryCountentryStrideBytesentryLayoutpcFlagRangepcFlagValuesetEntriesHelperscopyThenApplyHelperbyteEvidenceRowscoreConclusionz!DirectDraw palette object pointerz@receives the IDirectDrawPalette pointer created by CreatePalette)
addressHexr;   r(   zpalette header/allocationzCstores version 0x0300 and entry count 0x0100 before the entry byteszcurrent palette entriesz7first mutable PALETTEENTRY; entry i is 0x004676e8 + i*4
0x00559d98zpalette dirty flagzYmap/VM palette handlers mark pending palette changes before the deferred SetEntries apply0x380x39zz0x38 steps palette entries toward target/list/backup RGB values; 0x39 writes/fills current or backup palette ranges/lists.zoif dirty flag 0x00559d98 is set, the VM path applies start 0 count 0x100 through 0x00416677 and clears the flagz~these handlers explain palette color transforms and fades, but do not identify per-map waterfall/fire tile source-index motion)knownOpcodeFamiliesconfirmedMeaningdeferredApplyboundary
0x00415c58r   T
0x004167f1)hasExepaletteHeaderWriteAvailablecreatePaletteCallAvailablesetEntriesCallAAvailablesetEntriesCallBAvailablecopyThenApplyAvailablenotMapTileMotionProofzpalette fade/rampzjrange/list RGB writes plus SetEntries are grounded and should be treated as the EXE palette animation pathpromoted)area
conclusionr=   zindexed CNS renderingzweb rendering should preserve palette-index semantics where fidelity matters; precolored immutable PNGs cannot model later SetEntries updateszimplementation-guidancezmap animated tileszpalette changes can recolor indexed pixels, but visible waterfall/fire source-tile motion still needs a separate tile/source-index producerzboundary-fixed)zaName the exact callers that feed palette opcode 0x38/0x39 streams for each scene/map/effect root.zwFind the non-palette producer for map tile source-index motion if waterfall/fire animation is not purely palette-based.zsCapture or statically bind which palette ranges are used by individual battle helper effects that are palette-only.)kindr=   sourcesummarymemoryModeldirectDrawPaletteCallsupdateRoutinespaletteVmBoundarybyteEvidenceverificationmodelBoundariesopenQuestions)	EXE
read_bytesr   r*   strlowerlenexistsget)r   r   	byte_rowsrow
byte_by_vadirect_draw_palette_callsupdate_routiness          r   build_reportr      s   
..
CS!Hc8,I<EFS#c'l#))+S0FJF "2%Ia	
 "6%TT	
 "6%UW	
 "6%UO	
 "6%86	
;$!P "0 C 		
 "/ A 		
 "/i 		
 ".y 		
'O8 1;
 5#/#/$0 !+'!".!=#/ #I\
* +;] +3` +1T +,v!
, #<)$*F#3L O Y
 "jjl+5>>,+K+O+OP[+\`d+d*4..r*J*N*N{*[_c*c(2|R(H(L(L[(Y]a(a(2|R(H(L(L[(Y]a(a&0nn\2&F&J&J;&W[_&_%)
 , K$ 0 n3 - l*
"
q] ]G Gs   $F*c                     t               } t        j                  d       t        dz  j                  t	        j
                  | dd      dz   d	       y
)NT)exist_okzpalette_pipeline_review.jsonF   )ensure_asciiindent
zutf-8)encodingr   )r   OUTmkdir
write_textjsondumps)reports    r   mainr   9  sM    ^FIItI))55

6a84? 6  r   __main__)r   z
int | Nonereturnz
str | None)   )
r   r   r   list[dict[str, Any]]r   intr   r   r   dict[str, Any])r   r   r   r   r   r   )r   r   )r   r   )__doc__
__future__r   r   pathlibr   typingr   probe_exe_scene_tablesr   r   __file__resolveparentsROOTr   rs   r   r    r*   r   r   __name__
SystemExitr   r   r   <module>r      s    N "    > H~''*
Ul
]$fRdN z
TV
 r   