     # Byte 3 = x screen coordinate
 
     renderSpritePixel: ->
-        # TODO rewrite and optimize this
         @fetchSprites() if @cycle is 1
+        @renderedSprite = null
         return 0 if not @spritesVisible or (@cycle < 9 and @spriteClipping)
-        @spriteZeroRendered = false
-        currentX = @cycle - 1
-        currentY = @scanline - 1
-        heightMask = if @bigSprites then 0x0F else 0x07
-        for address in @spriteAddresses
-            innerX = currentX - @objectAttributeMemory[address + 3]
-            if 0 <= innerX <= 7
-                innerY = currentY - @objectAttributeMemory[address]
-                patternNumber = @objectAttributeMemory[address + 1]
-                attributes = @objectAttributeMemory[address + 2]
-                innerX ^= 0x07 if not (attributes & 0x40)
-                innerY ^= heightMask if attributes & 0x80
-                patternTableIndex = if @bigSprites then patternNumber & 0x01 else @spritesPatternTableIndex
-                patternTableAddress = patternTableIndex << 12
-                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
+        rightX = @cycle - 1
+        leftX = rightX - 8
+        for sprite in @secondaryOAM when leftX <= sprite.x <= rightX
+            columnNumber = rightX - sprite.x
+            columnNumber ^= 0x07 if not sprite.horizontalFlip
+            colorSelect1 =  (sprite.patternLayer1Row >>> columnNumber) & 1
+            colorSelect2 = ((sprite.patternLayer2Row >>> columnNumber) & 1) << 1
+            colorSelect = colorSelect2 | colorSelect1
+            if colorSelect
+                @renderedSprite = sprite
+                return sprite.paletteSelect | colorSelect
         return 0
 
     fetchSprites: ->
+        @secondaryOAM = []
         @spriteScalineOverflow = 0
-        @spriteAddresses = []
+        spriteHeight = if @bigSprites then 16 else 8
         bottomY = @scanline - 1
-        topY = Math.max 0, bottomY - (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
+        topY = Math.max 0, bottomY - spriteHeight
+        for spriteY, address in @primaryOAM by 4 when topY < spriteY <= bottomY
+            @fetchSprite address, spriteHeight, bottomY - spriteY
+            if @secondaryOAM.length >= 8
+                @spriteScalineOverflow = 1
+                return
+
+    fetchSprite: (address, height, rowNumber) ->
+        patternNumber = @primaryOAM[++address]
+        patternTableAddress = if @bigSprites then (patternNumber & 1) << 12 else @spPatternTableAddress
+        attributes = @primaryOAM[++address]
+        rowNumber = height - rowNumber - 1 if attributes & 0x80 # Vertical flip
+        if rowNumber >= 8
+            rowNumber -= 8
+            patternNumber++
+        patternAddress = patternTableAddress + (patternNumber << 4)
+        @secondaryOAM.push
+            x:                @primaryOAM[++address]
+            horizontalFlip:   attributes & 0x40
+            paletteSelect:    0x10 | (attributes & 0x03) << 2
+            inFront:          (attributes & 0x20) is 0
+            zeroSprite:       address is 3 # 0 before multiple incrementation
+            patternLayer1Row: @read patternAddress + rowNumber
+            patternLayer2Row: @read patternAddress + rowNumber + 8
 
     ###########################################################
     # Debug rendering

        @vblankStarted         << 7   # S[7]

    setStatus: (value) ->
        @vramWritesIgnored     = (value >>> 4) & 0x01 # S[4]
        @spriteScalineOverflow = (value >>> 5) & 0x01 # S[5]
        @spriteZeroHit         = (value >>> 6) & 0x01 # S[6]
        @vblankStarted         = (value >>> 7)        # S[7]

    ###########################################################
    # Object attribute memory access

        value

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

    copyVerticalScrollBits: ->
