###1964js - JavaScript/HTML5 port of 1964 - N64 emulator
Copyright (C) 2012 Joel Middendorf
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.###
useExternalTextures = false #for loading community texture packs
C1964jsRenderer = (settings, glx, webGL) ->
gl = glx
texrectVertexPositionBuffer = undefined
texrectVertexTextureCoordBuffer = undefined
texrectVertexIndexBuffer = undefined
@videoHLE = undefined
fivetoeight = [0x00,0x08,0x10,0x18,0x21,0x29,0x31,0x39,0x42,0x4A,0x52,0x5A,0x63,0x6B,0x73,0x7B,0x84,0x8C,0x94,0x9C,0xA5,0xAD,0xB5,0xBD,0xC6,0xCE,0xD6,0xDE,0xE7,0xEF,0xF7,0xFF]
@textureCache = new Object()
@texRect = (xl, yl, xh, yh, s, t, dsdx, dtdy, tile, tmem, videoHLE) ->
@videoHLE = videoHLE
canvaswidth = videoHLE.pow2roundup tile.width
canvasheight = videoHLE.pow2roundup tile.height
widthscale = tile.width / canvaswidth
heightscale = tile.height / canvasheight
rectWidth = xh-xl
rectHeight = yh-yl
#console.log "Rectsize:"+rectWidth+"x"+rectHeight+" S:"+s+"("+dsdx+") T:"+t+"("+dtdy
sl = s / tile.height
tl = t / tile.width
sh = (s + (rectWidth*dsdx)) / tile.width * widthscale
th = (t + (rectHeight*dtdy)) / tile.height * heightscale
xl = (xl-160)/160
xh = (xh-160)/160
yl = -(yl-120)/120
yh = -(yh-120)/120
initQuad xl, yl, xh, yh, sl, tl, sh, th, videoHLE
@draw tile, tmem, videoHLE
return
@formatTexture = (tile, tmem, cw, ch) ->
canvaswidth = cw
canvasheight = ch
texturesize = canvasheight * canvaswidth * 4
#hacky texture cache unique id (want to see how fast we currently are)
@useTextureCache = true #change to true to try texture cache
if @useTextureCache is true
randomPixel = canvasheight * canvaswidth
textureId = (tmem[randomPixel]>>>0) << 24 | (tmem[randomPixel+canvaswidth+1]>>>0) << 16 | (tmem[randomPixel+canvaswidth*2+1]>>>0) << 8 | tmem[randomPixel+canvaswidth*3+1]>>>0
return @textureCache[textureId] if @textureCache[textureId]?
buffer = new ArrayBuffer(texturesize)
texture = new Uint8Array(buffer)
if @useTextureCache is true
@textureCache[textureId] = texture
switch tile.fmt
when 0
switch tile.siz
when 2
width = tile.width;
j=0
while j < tile.height
i=0
while i < tile.width
base2 = (j*width*2) + (i*2)
base4 = (j*canvaswidth*4) + (i*4)
color16 = tmem[base2]<<8 | tmem[base2+1]
texture[base4] = fivetoeight[color16 >> 11 & 0x1F]
texture[base4 + 1] = fivetoeight[color16 >> 6 & 0x1F]
texture[base4 + 2] = fivetoeight[color16 >> 1 & 0x1F]
texture[base4 + 3] = if color16 & 0x01 == 0 then 0x00 else 0xFF
i++
j++
# if @useTextureCache is true
# return @textureCache[textureId]
return texture
initQuad = (xl, yl, xh, yh, sl, tl, sh, th, videoHLE) ->
vertices = [xh, yh, 0.0, xh, yl, 0.0, xl, yl, 0.0, xl, yh, 0.0]
texrectVertexPositionBuffer = gl.createBuffer()
gl.bindBuffer gl.ARRAY_BUFFER, texrectVertexPositionBuffer
gl.bufferData gl.ARRAY_BUFFER, new Float32Array(vertices), gl.DYNAMIC_DRAW
texrectVertexPositionBuffer.itemSize = 3
texrectVertexPositionBuffer.numItems = 4
textureCoords = [sh, th, sh, tl, sl, tl, sl, th]
texrectVertexTextureCoordBuffer = gl.createBuffer()
gl.bindBuffer gl.ARRAY_BUFFER, texrectVertexTextureCoordBuffer
gl.bufferData gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW
texrectVertexTextureCoordBuffer.itemSize = 2
texrectVertexTextureCoordBuffer.numItems = 4
texrectVertexIndices = [0, 1, 2, 0, 2, 3]
texrectVertexIndexBuffer = gl.createBuffer()
gl.bindBuffer gl.ELEMENT_ARRAY_BUFFER, texrectVertexIndexBuffer
gl.bufferData gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(texrectVertexIndices), gl.STATIC_DRAW
texrectVertexIndexBuffer.itemSize = 1
texrectVertexIndexBuffer.numItems = 6
return
@draw = (tile, tmem, videoHLE) ->
gl.useProgram webGL.shaderProgram
# basic settings
gl.disable gl.DEPTH_TEST
gl.enable gl.BLEND
gl.blendFunc gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA
gl.enableVertexAttribArray webGL.shaderProgram.vertexPositionAttribute
gl.bindBuffer gl.ARRAY_BUFFER, texrectVertexPositionBuffer
gl.vertexAttribPointer webGL.shaderProgram.vertexPositionAttribute, texrectVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0
gl.enableVertexAttribArray webGL.shaderProgram.textureCoordAttribute
gl.bindBuffer gl.ARRAY_BUFFER, texrectVertexTextureCoordBuffer
gl.vertexAttribPointer webGL.shaderProgram.textureCoordAttribute, texrectVertexTextureCoordBuffer.itemSize, gl.FLOAT, false, 0, 0
canvaswidth = videoHLE.pow2roundup tile.width
canvasheight = videoHLE.pow2roundup tile.height
#console.log "Binding Texture Size: "+tile.width+" x "+tile.height+" -> "+canvaswidth+" x "+canvasheight
texture = @formatTexture(tile, tmem, canvaswidth, canvasheight)
if texture isnt undefined
colorsTexture = gl.createTexture()
gl.activeTexture(gl.TEXTURE0)
gl.bindTexture(gl.TEXTURE_2D, colorsTexture)
gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, canvaswidth, canvasheight, 0, gl.RGBA, gl.UNSIGNED_BYTE, texture)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
gl.uniform1i webGL.shaderProgram.samplerUniform, colorsTexture
if videoHLE.primColor.length > 0
gl.uniform4fv webGL.shaderProgram.uPrimColor, videoHLE.primColor
if videoHLE.fillColor.length > 0
gl.uniform4fv webGL.shaderProgram.uFillColor, videoHLE.fillColor
if videoHLE.blendColor.length > 0
gl.uniform4fv webGL.shaderProgram.uBlendColor, videoHLE.blendColor
if videoHLE.envColor.length > 0
gl.uniform4fv webGL.shaderProgram.uEnvColor, videoHLE.envColor
gl.bindBuffer gl.ELEMENT_ARRAY_BUFFER, texrectVertexIndexBuffer
webGL.setMatrixUniforms webGL.shaderProgram
webGL.setCombineUniforms webGL.shaderProgram
gl.uniform1i webGL.shaderProgram.wireframeUniform, if settings.wireframe then 1 else 0
if settings.wireframe is true
gl.drawElements gl.LINE_LOOP, texrectVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0
else
gl.drawElements gl.TRIANGLES, texrectVertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0
return
return this
#hack global space until we export classes properly
#node.js uses exports; browser uses this (window)
root = exports ? this
root.C1964jsRenderer = C1964jsRenderer