     #    X = bit 1 of XXXXX
 
     renderBackgroundPixel: ->
-        @fetchCurrentPattern() if @fineXScroll is 0 # When coarse scroll X was incremented.
+        @fetchPattern() if @fineXScroll is 0 # When coarse scroll X was incremented.
         bitNumber = @fineXScroll ^ 0x07 # 7 - fineXScroll
         colorSelect1 =  (@patternLayer1Row >>> bitNumber) & 0x01
         colorSelect2 = ((@patternLayer2Row >>> bitNumber) & 0x01) << 1
-        @read 0x3F00 | @paletteSelect | colorSelect2 | colorSelect1
-
-    fetchCurrentPattern: ->
+        0x3F00 | @paletteSelect | colorSelect2 | colorSelect1
+
+    fetchPattern: ->
+        @fetchPalette() if (@vramAddress & 0x0001) is 0 # When coarse scroll was incremented by 2
         patternNumer = @read 0x2000 | @vramAddress & 0x0FFF
         patternTableAddress = @backgroundPatternTableIndex << 12
         patternAddress = patternTableAddress + (patternNumer << 4)
         fineYScroll = (@vramAddress >>> 12) & 0x07
         @patternLayer1Row = @read patternAddress + fineYScroll
         @patternLayer2Row = @read patternAddress + fineYScroll + 8
-        @fetchCurrentPalette() if (@vramAddress & 0x0001) is 0 # When coarse scroll was incremented by 2
-
-    fetchCurrentPalette: ->
-        @fetchCurrentAttribute() if (@vramAddress & 0x0002) is 0 # When coarse scroll was incremented by 4
+
+    fetchPalette: ->
+        @fetchAttribute() if (@vramAddress & 0x0002) is 0 # When coarse scroll was incremented by 4
         areaSelect = (@vramAddress >>> 4) & 0x04 | @vramAddress & 0x02
         @paletteSelect = ((@attribute >>> areaSelect) & 0x03) << 2
 
-    fetchCurrentAttribute: ->
+    fetchAttribute: ->
         attributeTableAddress = 0x23C0 | @vramAddress & 0x0C00
         attributeNumber = (@vramAddress >>> 4) & 0x38 | (@vramAddress >>> 2) & 0x07
         @attribute = @read attributeTableAddress + attributeNumber
 
+    ###########################################################
+    # Sprite rendering
+    ###########################################################
+
     renderSpritePixel: ->
-        color = 0 # TODO implement sprite rendering
-        @read 0x3F10 + color
-
-    setFramePixel: (color) ->
-        colorPosition = color << 2 # Each RGBA color is 4B.
-        @framebuffer[@framePosition++] = RGBA_COLORS[colorPosition++]
-        @framebuffer[@framePosition++] = RGBA_COLORS[colorPosition++]
-        @framebuffer[@framePosition++] = RGBA_COLORS[colorPosition]
-        @framePosition++ # Skip alpha because it was already set to 0xFF.
-
-    updateScrolling: ->
-        @incrementFineYScroll() if @cycle is 256
-        @incrementFineXScroll() if 1 <= @cycle <= 256
-        @copyHorizontalScrollBits() if @cycle is 257
-        @copyVerticalScrollBits() if @scanline is -1 and 280 <= @cycle <= 304
-
-    incrementCycle: ->
-        @cycle++
-        @incementScanline() if @cycle is 341
-
-    incementScanline: ->
-        @cycle = 0
-        @scanline++
-        if @scanline is 241
-            @vblankStarted = 1
-            @frameAvailable = true
-            @cpu.nonMaskableInterrupt() if @vblankGeneratesNMI
-        else if @scanline is 262
-            @vblankStarted = 0
-            @scanline = -1
-
-    readFrame: ->
-        @frameAvailable = false
-        @renderDebugFrame() if @debugMode # Rewrites the current frame.
-        @framebuffer
-
-    isFrameAvailable: ->
-        @frameAvailable
+        # TODO rewrite and optimize this
+        @fetchSprites() if @cycle is 1
+        @spriteZeroRendered = false
+        currentX = @cycle
+        currentY = @scanline
+        heightMask = if @bigSprites then 0x0F else 0x07
+        for address in @spriteAddresses
+            innerX = currentX - @objectAttributeMemory[address + 3]
+            if 0 <= innerX <= 7
+                innerY = currentY - @objectAttributeMemory[address]
+                tile = @objectAttributeMemory[address + 1]
+                attributes = @objectAttributeMemory[address + 2]
+                innerX ^= 0x07 if not (attributes & 0x40)
+                innerY ^= heightMask if attributes & 0x80
+                patternTableIndex = if @bigSprites then tile & 0x01 else @spritesPatternTableIndex
+                patternTableAddress = patternTableIndex << 12
+                patternNumber = tile
+                if innerY >= 8
+                    patternNumber++
+                    innerY -= 8
+                patternAddress = patternTableAddress + (patternNumber << 4)
+                patternLayer1Row = @read patternAddress + innerY
+                patternLayer2Row = @read patternAddress + innerY + 8
+                colorSelect1 =  (patternLayer1Row >>> innerX) & 0x01
+                colorSelect2 = ((patternLayer2Row >>> innerX) & 0x01) << 1
+                colorSelect = colorSelect2 | colorSelect1
+                if colorSelect
+                    @spriteZeroRendered ||= address is 0
+                    @spriteInFront = (attributes & 0x20) is 0
+                    paletteSelect = (attributes & 0x03) << 2
+                    return 0x10 | paletteSelect | colorSelect
+        return 0
+
+    fetchSprites: ->
+        @spriteScalineOverflow = 0
+        @spriteAddresses = []
+        bottomY = @scanline
+        topY = Math.max 0, @scanline - (if @bigSprites then 16 else 8)
+        for spriteY, address in @objectAttributeMemory by 4
+            if topY < spriteY <= bottomY
+                @spriteAddresses.push address
+                if @spriteAddresses.length >= 8
+                    @spriteScalineOverflow = 1
+                    return
 
     ###########################################################
     # Debug rendering

        @resetVariables()

    resetOAM: ->
        @objectAttributeMemory = (0 for [0..0x100]) # 256B

    resetRegisters: ->
        @setControl 0       #  8-bit
        @setMask 0          #  8-bit
        @setStatus 0        #  8-bit
        @oamAddress = 0     # 15-bit
        @tempAddress = 0    # 15-bit also known as 'Loopy_T'
        @vramAddress = 0    # 15-bit also known as 'Loopy_V'
        @vramReadBuffer = 0 #  8-bit
        @writeToogle = 0    #  1-bit        
        @fineXScroll = 0    #  3-bit

    resetVariables: ->
        @scanline = -1 # Total 262+1 scanlines (-1..261)
        @cycle = 0     # Total 341 cycles per scanline (0..340)

    ###########################################################
    # Control register

        value

    copyHorizontalScrollBits: ->
        @fineXScroll = @tempFineXScroll
        @vramAddress = (@vramAddress & 0x7BE0) | (@tempAddress & 0x041F) # V[10,4-0] = T[10,4-0]

    copyVerticalScrollBits: ->
