That could cause an infinite loop if the XML wasn't complete, but even so it's not the cause of this issue. I've verified that all input is accurate, reading the file and parsing the data I want is ok and there are no infinite loop issues (using my example xml).
It's very strange. Here is the entire function in the snippet below. I can call
img = loadImage("littleshrooms_0.png") pretty much any where inside that function except within the code block starting with
if tag$ = "imagelayer".
Ok, now this same problem has crept up elsewhere. After I delete the loaded map ingame then load a new one, I get the same crash. And I've once again tracked it down to a loadImage command. Now this part isn't something I just added, this part has been working fine since I made this TMX library last year. I never had problems deleting and loading a new map before until now. I'm sure I could do a similar workaround as before.
//////////////////////////////////////////////////
// Load an XML-based TMX map file
//////////////////////////////////////////////////
function tmx_LoadMap(file$)
F = openToRead(file$)
layerId = 0
repeat
s$ = xml_StripLeadingSpaces$(readline(F))
tag$ = xml_GetTagName$(s$)
if tag$ = "map"
attributes$ = xml_GetUnparsedAttributeString$(s$, tag$)
orientation$ = xml_GetAttribute$(attributes$, "orientation")
TMX_Map.mapWidth = val(xml_GetAttribute$(attributes$, "width"))
TMX_Map.mapHeight = val(xml_GetAttribute$(attributes$, "height"))
TMX_Map.tileWidth = val(xml_GetAttribute$(attributes$, "tilewidth"))
TMX_Map.tileHeight = val(xml_GetAttribute$(attributes$, "tileheight"))
TMX_Map.bgColor = val(mid(xml_GetAttribute$(attributes$, "backgroundcolor"), 2, 6), 16)
if orientation$ = "orthogonal" then TMX_Map.orientation = TMX_ORIENTATION_ORTHO
if orientation$ = "isometric" then TMX_Map.orientation = TMX_ORIENTATION_ISO
if orientation$ = "staggered" then TMX_Map.orientation = TMX_ORIENTATION_STAG
// Create a map with a max of 5 layers
dim TMX_Map[5, TMX_Map.mapWidth*TMX_Map.mapHeight] as TMX_Tile
endif
// New tileset detected
if tag$ = "tileset"
attributes$ = xml_GetUnparsedAttributeString$(s$, tag$)
inc _TilesetCount
dim TMX_Tilesets[_TilesetCount] as TMX_Tileset
TMX_Tilesets[_TilesetCount].firstGid = val(xml_GetAttribute$(attributes$, "firstgid"))
TMX_Tilesets[_TilesetCount].tileWidth = val(xml_GetAttribute$(attributes$, "tilewidth"))
TMX_Tilesets[_TilesetCount].tileHeight = val(xml_GetAttribute$(attributes$, "tileheight"))
TMX_Tilesets[_TilesetCount].name = xml_GetAttribute$(attributes$, "name")
TMX_Tilesets[_TilesetCount].spacing = val(xml_GetAttribute$(attributes$, "spacing"))
TMX_Tilesets[_TilesetCount].margin = val(xml_GetAttribute$(attributes$, "margin"))
endif
// Tileset pixel offset
if tag$ = "tileoffset"
attributes$ = xml_GetUnparsedAttributeString$(s$, tag$)
TMX_Tilesets[_TilesetCount].offsetX = val(xml_GetAttribute$(attributes$, "x"))
TMX_Tilesets[_TilesetCount].offsetY = val(xml_GetAttribute$(attributes$, "y"))
endif
// Image detected, load it and set its animation to make up the tiles
if tag$ = "image"
attributes$ = xml_GetUnparsedAttributeString$(s$, tag$)
TMX_Tilesets[_TilesetCount].source = xml_GetAttribute$(attributes$, "source")
imgWidth = val(xml_GetAttribute$(attributes$, "width"))
imgHeight = val(xml_GetAttribute$(attributes$, "height"))
if TMX_Tilesets[_TilesetCount].spacing > 0 or TMX_Tilesets[_TilesetCount].margin > 0
tileCountX = (imgWidth-TMX_Tilesets[_TilesetCount].margin) / (TMX_Tilesets[_TilesetCount].tileWidth + TMX_Tilesets[_TilesetCount].spacing)
tileCountY = (imgHeight-TMX_Tilesets[_TilesetCount].margin) / (TMX_Tilesets[_TilesetCount].tileHeight + TMX_Tilesets[_TilesetCount].spacing)
imgWidth = TMX_Tilesets[_TilesetCount].tileWidth * tileCountX
imgHeight = TMX_Tilesets[_TilesetCount].tileHeight * tileCountY
img = getTrimmedImage(TMX_Tilesets[_TilesetCount].source, TMX_Tilesets[_TilesetCount].tileWidth, TMX_Tilesets[_TilesetCount].tileHeight, TMX_Tilesets[_TilesetCount].margin, TMX_Tilesets[_TilesetCount].spacing)
else
img = loadImage(TMX_Tilesets[_TilesetCount].source)
endif
TMX_Tilesets[_TilesetCount].imgWidth = imgWidth
TMX_Tilesets[_TilesetCount].imgHeight = imgHeight
TMX_Tilesets[_TilesetCount].lastGid = floor(imgWidth / (TMX_Tilesets[_TilesetCount].tileWidth+0.0)) * floor(imgHeight / (TMX_Tilesets[_TilesetCount].tileHeight+0.0)) + TMX_Tilesets[_TilesetCount].firstGid - 1
TMX_Tilesets[_TilesetCount].sprite = createSprite(img)
tileCount = (imgWidth / TMX_Tilesets[_TilesetCount].tileWidth) * (imgHeight / TMX_Tilesets[_TilesetCount].tileHeight)
setSpriteAnimation(TMX_Tilesets[_TilesetCount].sprite, TMX_Tilesets[_TilesetCount].tileWidth, TMX_Tilesets[_TilesetCount].tileHeight, tileCount)
setSpriteVisible(TMX_Tilesets[_TilesetCount].sprite, 0)
endif
// New layer detected
if tag$ = "layer"
inc _TMX_LayerCount
dim TMX_Map_Layers[_TMX_LayerCount] as TMX_LAYER
TMX_Map_Layers[_TMX_LayerCount].imageLayer.isImageLayer = 0
tileNumber = 0
attributes$ = xml_GetUnparsedAttributeString$(s$, tag$)
opacity$ = xml_GetAttribute$(attributes$, "opacity")
isVisible$ = xml_GetAttribute$(attributes$, "visible")
width$ = xml_GetAttribute$(attributes$, "width")
height$ = xml_GetAttribute$(attributes$, "height")
// Layer's name
TMX_Map_Layers[_TMX_LayerCount].name = xml_GetAttribute$(attributes$, "name")
// Layer's offset position
TMX_Map_Layers[_TMX_LayerCount].x = val(xml_GetAttribute$(attributes$, "x"))
TMX_Map_Layers[_TMX_LayerCount].y = val(xml_GetAttribute$(attributes$, "y"))
// If opacity not set, default to 255
if opacity$ = "" then opacity$ = "1"
TMX_Map_Layers[_TMX_LayerCount].alpha = val(opacity$) * 255
// If visible not set, default to true
if isVisible$ = "" : TMX_Map_Layers[_TMX_LayerCount].visible = 1 : else : TMX_Map_Layers[_TMX_LayerCount].visible = val(isVisible$) : endif
// If width or height are not set, default to map dimensions
if width$ = "" : TMX_Map_Layers[_TMX_LayerCount].width = TMX_Map.mapWidth : else : TMX_Map_Layers[_TMX_LayerCount].width = val(width$) : endif
if height$ = "" : TMX_Map_Layers[_TMX_LayerCount].height = TMX_Map.mapHeight : else : TMX_Map_Layers[_TMX_LayerCount].height = val(height$) : endif
endif
// New image layer
if tag$ = "imagelayer"
inc _TMX_LayerCount
dim TMX_Map_Layers[_TMX_LayerCount] as TMX_LAYER
TMX_Map_Layers[_TMX_LayerCount].imageLayer.isImageLayer = 1
attributes$ = xml_GetUnparsedAttributeString$(s$, tag$)
opacity$ = xml_GetAttribute$(attributes$, "opacity")
isVisible$ = xml_GetAttribute$(attributes$, "visible")
// Layer's name
TMX_Map_Layers[_TMX_LayerCount].name = xml_GetAttribute$(attributes$, "name")
// Layer's offset position
TMX_Map_Layers[_TMX_LayerCount].x = 0
TMX_Map_Layers[_TMX_LayerCount].y = 0
// If opacity not set, default to 255
if opacity$ = "" then opacity$ = "1"
TMX_Map_Layers[_TMX_LayerCount].alpha = val(opacity$) * 255
// If visible not set, default to true
if isVisible$ = "" : TMX_Map_Layers[_TMX_LayerCount].visible = 1 : else : TMX_Map_Layers[_TMX_LayerCount].visible = val(isVisible$) : endif
// Meaningless in an image layer
`TMX_Map_Layers[_TMX_LayerCount].width = TMX_Map.mapWidth
`TMX_Map_Layers[_TMX_LayerCount].height = TMX_Map.mapHeight
while tag$ <> "/imagelayer"
s$ = xml_StripLeadingSpaces$(readline(F))
tag$ = xml_GetTagName$(s$)
if tag$ = "image"
attributes$ = xml_GetUnparsedAttributeString$(s$, tag$)
TMX_Map_Layers[_TMX_LayerCount].imageLayer.source = xml_GetAttribute$(attributes$, "source")
endif
endwhile
endif
// Only supports Base64 uncompressed [2-6-2014]
if tag$ = "data"
attributes$ = xml_GetUnparsedAttributeString$(s$, tag$)
encoding$ = xml_GetAttribute$(attributes$, "encoding")
// Base64 encoding
if encoding$ = "base64"
data$ = xml_GetTagInnerContent$(F, "data")
dataSize = decode64ToByteArray(data$)
for i = 1 to dataSize step 4
gid = B64[i] || B64[i+1]<<8 || B64[i+2]<<16 || B64[i+3]<<24
inc tileNumber
checkAndSetGID(_TMX_LayerCount, tileNumber, gid)
next i
// free up memory
undim B64[]
// CSV encoding
elseif encoding$ = "csv"
while tag$ <> "/data"
s$ = xml_StripLeadingSpaces$(readline(F))
tag$ = xml_GetTagName$(s$)
n = countStringTokens(s$, ",")
for i = 1 to n
inc tileNumber
gid = val(getStringToken(s$, ",", i))
checkAndSetGID(_TMX_LayerCount, tileNumber, gid)
next i
endwhile
// Default, no encoding
else
while tag$ <> "/data"
s$ = xml_StripLeadingSpaces$(readline(F))
tag$ = xml_GetTagName$(s$)
if tag$ = "tile"
inc tileNumber
attributes$ = xml_GetUnparsedAttributeString$(s$, tag$)
gid = val(xml_GetAttribute$(attributes$, "gid"))
checkAndSetGID(_TMX_LayerCount, tileNumber, gid)
endif
endwhile
endif
endif
// Tiles from inside a pair of tileset tags, contains terrain info
if tag$ = "tile"
// not yet implemented
endif
until fileEOF(F) = 1
closeFile(F)
// Set background color
r = (TMX_Map.bgColor && 16711680) >> 16
g = (TMX_Map.bgColor && 65280) >> 8
b = TMX_Map.bgColor && 255
setClearColor(r, g, b)
if TMX_Map.orientation = TMX_ORIENTATION_ORTHO then tmx_BuildOrthogonalMap()
if TMX_Map.orientation = TMX_ORIENTATION_ISO then tmx_BuildIsometricMap()
if TMX_Map.orientation = TMX_ORIENTATION_STAG then tmx_BuildStaggeredMap()
endfunction