{"kind":"hwanse-map-animation-redraw-consumer-review","status":"redraw-consumer-grounded-visible-motion-producer-unbound","source":["Hwanse2.exe","tools/build_map_animation_redraw_consumer_review.py","out/map_animation_tile_review.json","out/map_animation_live_buffer_writer_review.json"],"globals":{"liveLayer0Grid":"0x00595af0","liveLayer1FlagGrid":"0x0058d7d0","dirtyWorkGrid":"0x005957d0","mapWidth":"0x00595ada","mapHeight":"0x00595adc","cameraCurrentX":"0x004576dc","cameraCurrentY":"0x004576de","cameraPreviousX":"0x00595ade","cameraPreviousY":"0x00595ae0","drawSurfaceSlot":"0x0055b580","drawDirtyMask":"0x0055b588"},"summary":{"viewportTileWidth":37,"viewportTileHeight":21,"layer1AnimatedFlagBit":"0x40","dirtyGridBitFor0x40":"0x01","redrawPathGrounded":true,"layer1AnimatedFlagConsumerGrounded":true,"liveLayer0RendererGrounded":true,"alternateTileSelectionFound":false,"visibleMotionProducerFound":false,"decision":"0x40 cells are definitely consumed by the viewport redraw path, but this consumer only invalidates/redraws. Visible motion still needs either a live layer0 mutation producer or a draw-time tile transform that is not proven here."},"landmarks":[{"name":"viewport dirty scan","va":4346883,"endVa":4347424,"role":"Scans the 37x21 visible viewport and marks dirty cells.","vaHex":"0x00425403","endVaHex":"0x00425620","byteSnippet":"55 8b ec 83 ec 08 53 56 57 c7 45 f8 00 00 00 00 e9 03 00 00 00 ff 45 f8 83 7d f8 15 0f 83 b9 00 00 00 c7 45 fc 00 00 00 00 e9 03 00 00 00 ff 45 fc 83 7d fc 25 0f 83 9b 00 00 00 8b 45 f8 8b c8"},{"name":"full surface dirty redraw","va":4345959,"endVa":4346084,"role":"Sets draw surface/mask, renders dirty rows, snapshots camera.","vaHex":"0x00425067","endVaHex":"0x004250e4","byteSnippet":"55 8b ec 83 ec 04 53 56 57 8b 45 08 25 ff ff 00 00 83 3c 85 d8 ab 55 00 00 0f 85 05 00 00 00 e9 55 00 00 00 66 8b 45 08 66 a3 80 b5 55 00 66 c7 05 88 b5 55 00 01 00 c7 45 fc 00 00 00 00 e9 03"},{"name":"dirty row renderer","va":4346211,"endVa":4346639,"role":"Reads live layer0 tile ids and draws dirty visible rows.","vaHex":"0x00425163","endVaHex":"0x0042530f","byteSnippet":"55 8b ec 83 ec 08 53 56 57 c7 45 f8 00 00 00 00 e9 03 00 00 00 ff 45 f8 83 7d f8 25 0f 83 f0 00 00 00 8b 45 08 25 ff ff 00 00 8b c8 8d 04 c0 8d 04 81 8b 4d f8 33 d2 8a 94 08 d0 57 59 00 33 c0"},{"name":"active object projection","va":4344362,"endVa":4345046,"role":"Projects object tile positions into viewport/screen positions.","vaHex":"0x00424a2a","endVaHex":"0x00424cd6","byteSnippet":"55 8b ec 83 ec 0c 53 56 57 c7 45 f8 00 00 00 00 e9 03 00 00 00 ff 45 f8 8b 45 f8 8b 4d 08 8b 04 81 89 45 fc 83 7d fc 00 0f 84 fa 00 00 00 8b 45 fc 33 c9 66 8b 48 14 f6 c5 01 0f 85 05 00 00 00"},{"name":"occlusion dirty projection","va":4345046,"endVa":4345892,"role":"Projects object/occlusion coverage into the dirty work grid.","vaHex":"0x00424cd6","endVaHex":"0x00425024","byteSnippet":"55 8b ec 83 ec 30 53 56 57 8b 45 08 f6 40 03 1a 0f 85 12 00 00 00 33 c0 8a 45 0c 85 c0 0f 84 05 00 00 00 e9 64 03 00 00 8d 45 ec 50 8b 45 08 50 e8 d7 1f ff ff 83 c4 08 83 7d f4 00 0f 85 05 00"}],"steps":[{"step":"clear dirty bits before viewport scan","vaHex":"0x00425413","evidence":"The 37x21 dirty work grid at 0x005957d0 is masked before the new viewport pass.","meaning":"The routine starts from an invalidation pass, not from a frame-selection table."},{"step":"scan visible layer1 flags","vaHex":"0x00425494","evidence":"Reads WORD PTR [index*2 + 0x0058d7d0] and tests low byte with 0x40.","meaning":"layer1 bit 0x40 is consumed as redraw/animation coverage over the current viewport."},{"step":"mark dirty work grid","vaHex":"0x004254a5","evidence":"When 0x40 is present, ORs the matching byte in 0x005957d0 with 0x01.","meaning":"The consumer schedules redraw work.  It does not choose a replacement tile id here."},{"step":"camera movement invalidation","vaHex":"0x004254e0","evidence":"Compares current camera 0x004576dc/de with previous 0x00595ade/e0, then compares visible layer0 cells.","meaning":"Camera scrolling also marks dirty cells when the visible layer0 tile differs."},{"step":"render dirty rows from live layer0","vaHex":"0x00425163","evidence":"Row renderer reads live layer0 grid 0x00595af0 and combines it with the active surface slot.","meaning":"The renderer draws whatever tile id is currently in the live layer0 grid."},{"step":"snapshot camera after redraw","vaHex":"0x004250c4","evidence":"After dirty row rendering, current camera is copied into 0x00595ade/e0.","meaning":"The pass is a viewport redraw/cache maintenance step."},{"step":"object/occlusion dirty projection","vaHex":"0x00424a2a","evidence":"Active object positions are projected relative to the camera and coverage is written into dirty/occlusion buffers.","meaning":"This explains foreground/actor redraw interaction, not map animation frame generation."}],"surfaces":[{"surface":"layer1 0x40 viewport consumer","promotion":"confirmed-redraw-consumer","finding":"0x00425403 scans 37x21 visible layer1 cells and marks 0x005957d0 dirty bit 0x01 when layer1&0x40 is set.","gap":"No alternate tile id, palette frame, or shift offset is selected in this path."},{"surface":"live layer0 row draw","promotion":"confirmed-render-consumer","finding":"0x00425163 draws dirty rows by reading live layer0 0x00595af0.","gap":"If visible motion uses changing tile ids, the producer must mutate live layer0 before this renderer."},{"surface":"camera scroll invalidation","promotion":"confirmed-redraw-cache","finding":"0x00425403 also compares current/previous camera and marks dirty cells when visible layer0 differs.","gap":"This is camera cache invalidation, not animation timing."},{"surface":"object/foreground dirty projection","promotion":"confirmed-occlusion-redraw","finding":"0x00424a2a..0x00425024 projects active-object coverage into redraw buffers.","gap":"This handles actor/foreground redraw and does not bind animated map cells to frame loops."}],"nextFrontier":["Inspect draw-time tile conversion under/after 0x00425163 and 0x004175d3 for frame-counter-based tile transforms.","Search for a timer/tick path that mutates 0x00595af0 before the redraw consumer runs.","If static route remains blocked, runtime-watch 0x00595af0 on map1_01a/map1_02b during one visible animation loop."]}