private BgMapState createTileState(StateMap stateMap, int address, RawMemoryMap memoryMap, int scene, int frame, int scanLine, int firstRowScanLine) {
    byte[] tileData = new byte[16];
    byte[] paletteData = new byte[8];
    boolean flipHorizontally;
    boolean flipVertically;
    boolean bgToOamPriority;
    for (int dy = 0; dy < 8; dy++) {
      int frameCycle = Math.max(0, firstRowScanLine + dy) * GbConstants.LINE_CYCLES + 80 * GbConstants.DOUBLE_SPEED_FACTOR;
      TimeStamp time = new TimeStamp(scene, frame, frameCycle);
      int lcdc = memoryMap.getLCDC(time);
      int bgMapTile = memoryMap.getVramValue(0, address, time);
      int bgMapTileAddress = ((lcdc & 0x10) != 0 ? 0x8000 : 0x9000) + bgMapTile * 0x10;
      if (bgMapTileAddress >= 0x9800)
        bgMapTileAddress -= 0x1000;
      int bgMapAttribute = memoryMap.getVramValue(1, address, time);
      int vramBank = (bgMapAttribute & 0x08) >> 3;
      tileData[2 * dy] = (byte)memoryMap.getVramValue(vramBank, bgMapTileAddress + 2*dy, time);
      tileData[2 * dy + 1] = (byte)memoryMap.getVramValue(vramBank, bgMapTileAddress + 2*dy + 1, time);
    }
    
    int frameCycle = scanLine * GbConstants.LINE_CYCLES + 80 * GbConstants.DOUBLE_SPEED_FACTOR;
    TimeStamp time = new TimeStamp(scene, frame, frameCycle);
    
    int bgMapAttribute = memoryMap.getVramValue(1, address, time);
    int paletteIndex = bgMapAttribute & 0x7;
    for (int i = 0; i < 8; i++) {
      paletteData[i] = (byte)memoryMap.getBgPaletteValue(paletteIndex * 8 + i, time);
      if ((i & 1) != 0)
        paletteData[i] &= 0x7f;
    }
    TileResult tileResult = stateMap.tileRegistry.registerForBg(new Tile(tileData));
    flipHorizontally = tileResult.flipHorizontally ^ ((bgMapAttribute & 0x20) != 0);
    flipVertically = tileResult.flipVertically ^ ((bgMapAttribute & 0x40) != 0);
    bgToOamPriority = ((bgMapAttribute & 0x80) != 0);

    return new BgMapState(tileResult.tile, flipHorizontally, flipVertically, bgToOamPriority, stateMap.bgPaletteRegistry.register(new Palette(paletteData)));
  }