Navigation

    Fuze Arena Logo
    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Popular
    • Users
    • Groups
    • Help
    • Discord

    drawMap() into an image has problems if the map is unloaded before the next update() call

    Bug Reporting (FUZE 4 Nintendo Switch)
    1
    1
    113
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Z-Mann
      Z-Mann last edited by

      Sorry, I've been abusing your systems again :)

      Project share code (pending): 517C7MND51


      The project has two maps. "empty" is just empty with no media configured, "full" has some trees in it from "Ansimuz/TinyRPGForestObjectTiles".
      The code loads the "full" map, renders it into img1, then loads "empty", renders it into img2, then "full" again, rendering it into img3.
      Then img1 and img3 are drawn to the screen. For img1, the trees are corrupted.
      All operations on img3 can be removed, the corruption persists.
      Only a call to update() before loading the map "empty"

      Code:

      function test()
        w = 640
      
        loadMap("full")
        img1 = createImage(w,w,false,image_rgb)
        setDrawTarget(img1)
        drawMap()
       
        // uncommenting this fixes the problem
        // update()
       
        loadMap("empty")
        img2 = createImage(w,w,false,image_rgb)
        setDrawTarget(img2)
        drawMap()
      
        loadMap("full")
        img3 = createImage(w,w,false,image_rgb)
        setDrawTarget(img3)
        drawMap()
      
        setDrawTarget(frameBuffer)
        clear()
        drawImage(img1,0,0,1)
        drawImage(img2,w,0,1)
        update()
        sleep(20)
      return void
      
      test()
      

      Guessing: It's documented that all draw operations only execute once update() is called. That probably includes drawing to the image targets. The only problem there is that the assets "full" is using are probably thrown out when "empty" is loaded (assets shared by the two maps don't cause problems, the map loading code is smart enough to just keep them), so when the drawing operations need them, they're no longer available. Or at least not available where they're expected in the case that "full" is loaded again.

      Even simpler code that triggers the bug for me; as with all use-after-free bugs, the results are a bit nondeterministic:

      function test2()
        w = 640
      
        loadMap("full")
        drawMap()
       
        unloadMap()
        img2 = createImage(w,w,false,image_rgb)
      
        update()
        sleep(20)
      return void
      
      test2()
      

      So the crucial ingredients seem to be that you need to unload the map (and its assets) between drawMap() and update(), and something between unloading the map and update() needs to get lucky and corrupt the memory where the assets had been.

      No rush! I definitely don't want to swap between maps in a single frame! Nobody should even think about that!

      1 Reply Last reply Reply Quote 1
      • First post
        Last post