mirror of
https://github.com/schibo/1964js.git
synced 2025-04-02 10:52:54 -04:00
586 lines
21 KiB
CoffeeScript
586 lines
21 KiB
CoffeeScript
###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
|
|
|
|
`const fivetoeight = new Uint8Array([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])
|
|
const fourtoeight = new Uint8Array([0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff])
|
|
const threetoeight = new Uint8Array([
|
|
0x00, // 000 -> 00 00 00 00
|
|
0x24, // 001 -> 00 10 01 00
|
|
0x49, // 010 -> 01 00 10 01
|
|
0x6d, // 011 -> 01 10 11 01
|
|
0x92, // 100 -> 10 01 00 10
|
|
0xb6, // 101 -> 10 11 01 10
|
|
0xdb, // 110 -> 11 01 10 11
|
|
0xff // 111 -> 11 11 11 11
|
|
])
|
|
const onetoeight = new Uint8Array([
|
|
0x00, // 0 -> 00 00 00 00
|
|
0xff // 1 -> 11 11 11 11
|
|
])`
|
|
|
|
class C1964jsRenderer
|
|
constructor: (settings, glx, webGL) ->
|
|
@settings = settings
|
|
@gl = glx
|
|
@webGL = webGL
|
|
@canvas = undefined
|
|
@texture = new Uint8Array(1024*1024*4)
|
|
|
|
@texrectVertexPositionBuffer = @gl.createBuffer()
|
|
@texrectVertexTextureCoordBuffer = @gl.createBuffer()
|
|
@texrectVertexIndexBuffer = @gl.createBuffer()
|
|
@texrectVertexIndices = [0, 1, 2, 0, 2, 3]
|
|
@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
|
|
@colorsTexture0 = @gl.createTexture()
|
|
|
|
@textureCache = new Object()
|
|
|
|
texRect: (tileno, xl, yl, xh, yh, s, t, dsdx, dtdy, tile, tmem, videoHLE, isFillRect) ->
|
|
|
|
tileWidth = (((tile.lrs >> 2) + 1) - tile.uls)|0
|
|
tileHeight = (((tile.lrt >> 2) + 1) - tile.ult)|0
|
|
|
|
supportsNonPowerOf2 = true
|
|
|
|
if !supportsNonPowerOf2
|
|
nextPow2Width = videoHLE.pow2roundup tileWidth
|
|
nextPow2Height = videoHLE.pow2roundup tileHeight
|
|
widthscale = tileWidth / nextPow2Width
|
|
heightscale = tileHeight / nextPow2Height
|
|
else
|
|
nextPow2Width = tileWidth
|
|
nextPow2Height = tileHeight
|
|
widthscale = 1.0
|
|
heightscale = 1.0
|
|
|
|
rectWidth = xh-xl
|
|
rectHeight = yh-yl
|
|
|
|
#console.log "Rectsize:"+rectWidth+"x"+rectHeight+" S:"+s+"("+dsdx+") T:"+t+"("+dtdy
|
|
|
|
sl = s / tileHeight
|
|
tl = t / tileWidth
|
|
sh = (s + (rectWidth*dsdx)) / tileWidth * widthscale
|
|
th = (t + (rectHeight*dtdy)) / tileHeight * heightscale
|
|
|
|
xTrans = 160
|
|
yTrans = 120
|
|
xl = (xl-xTrans)*0.00625 #0.000625 is 1.0/160.0
|
|
xh = (xh-xTrans)*0.00625
|
|
yl = -(yl-yTrans)/yTrans
|
|
yh = -(yh-yTrans)/yTrans
|
|
|
|
@initQuad xl, yl, xh, yh, sl, tl, sh, th, videoHLE
|
|
@draw @gl, tileno, tile, tmem, videoHLE, nextPow2Width, nextPow2Height, tileWidth, tileHeight, isFillRect
|
|
return
|
|
|
|
formatTexture: (tile, tmem, videoHLE, isFillRect) ->
|
|
return undefined if tile.lrs is undefined or tile.lrt is undefined or tile.uls is undefined or tile.ult is undefined
|
|
|
|
tileWidth = ((tile.lrs >> 2) + 1) - (tile.uls|0)
|
|
tileHeight = ((tile.lrt >> 2) + 1) - (tile.ult|0)
|
|
|
|
supportsNonPowerOf2 = true
|
|
if !supportsNonPowerOf2
|
|
nextPow2Width = videoHLE.pow2roundup (tileWidth*4)
|
|
nextPow2Height = videoHLE.pow2roundup tileHeight
|
|
else
|
|
nextPow2Width = tileWidth<<2
|
|
nextPow2Height = tileHeight
|
|
|
|
textureSize = nextPow2Width * nextPow2Height
|
|
#hacky texture cache unique id (want to see how fast we currently are)
|
|
|
|
if tileWidth is undefined or tileHeight is undefined
|
|
e = Error
|
|
e.message = "Undefined tile dimensions"
|
|
throw e
|
|
|
|
# @useTextureCache = false #change to true to try texture cache
|
|
# if @useTextureCache is true
|
|
# randomPixel = nextPow2Width * nextPow2Height
|
|
# textureId = (tmem[randomPixel]>>>0) << 24 | (tmem[randomPixel+nextPow2Width+1]>>>0) << 16 | (tmem[randomPixel+nextPow2Width*2+1]>>>0) << 8 | tmem[randomPixel+nextPow2Width*3+1]>>>0
|
|
# return @textureCache[textureId] if @textureCache[textureId]?
|
|
|
|
# if (nextPow2Width isnt tileWidth) or (nextPow2Height isnt tileHeight)
|
|
# # handle non-power of 2 textures
|
|
# if @canvas is undefined
|
|
# @canvas = document.getElementById('Canvas');
|
|
# @canvas.width = tileWidth
|
|
# @canvas.height = tileHeight
|
|
# context = @canvas.getContext('2d')
|
|
# imageData = context.createImageData(nextPow2Width, nextPow2Height)
|
|
# texture = imageData.data
|
|
# else
|
|
texture = @texture
|
|
|
|
dstRowOffset = 0
|
|
`const dstRowStride = nextPow2Width`
|
|
`const srcRowStride = tile.line<<3`
|
|
srcRowOffset = tile.tmem<<3
|
|
|
|
if videoHLE.cycleType is 3 or isFillRect is true
|
|
# no need to copy`
|
|
else
|
|
if @useTextureCache is true
|
|
@textureCache[textureId] = texture
|
|
switch tile.fmt
|
|
when consts.TXT_FMT_RGBA # rgba
|
|
switch tile.siz
|
|
when consts.TXT_SIZE_16b # rgba5551
|
|
@convertRGBA16 texture, tmem, tileWidth, tileHeight, srcRowOffset, dstRowOffset, srcRowStride, dstRowStride
|
|
when consts.TXT_SIZE_32b # rgba32
|
|
@convertRGBA32 texture, tmem, tileWidth, tileHeight, srcRowOffset, dstRowOffset, srcRowStride, dstRowStride
|
|
else
|
|
console.error "TODO: tile format " + tile.fmt + ", tile.size:" + tile.siz
|
|
when consts.TXT_FMT_IA # ia
|
|
switch tile.siz
|
|
when consts.TXT_SIZE_8b # ia8
|
|
@convertIA8 texture, tmem, tileWidth, tileHeight, srcRowOffset, dstRowOffset, srcRowStride, dstRowStride
|
|
when consts.TXT_SIZE_4b # ia4
|
|
@convertIA4 texture, tmem, tileWidth, tileHeight, srcRowOffset, dstRowOffset, srcRowStride, dstRowStride
|
|
when consts.TXT_SIZE_16b # ia16
|
|
@convertIA16 texture, tmem, tileWidth, tileHeight, srcRowOffset, dstRowOffset, srcRowStride, dstRowStride
|
|
else
|
|
console.error "TODO: tile format " + tile.fmt + ", tile.size" + tile.siz
|
|
when consts.TXT_FMT_CI
|
|
switch tile.siz
|
|
when consts.TXT_SIZE_8b
|
|
if tile.otherModeH & consts.TLUT_FMT_IA16
|
|
ram = videoHLE.core.memory.u8
|
|
@convertCI8_IA16 texture, tmem, 0x800, videoHLE.tlut, tileWidth, tileHeight, srcRowOffset, dstRowOffset, srcRowStride, dstRowStride
|
|
else # tile.otherModeL & consts.TLUT_FMT_RGBA16 is true or false (TLUT_FMT_UNKNOWN, TLUT_FMT_NONE)
|
|
ram = videoHLE.core.memory.u8
|
|
@convertCI8_RGBA16 texture, tmem, 0x800, videoHLE.tlut, tileWidth, tileHeight, srcRowOffset, dstRowOffset, srcRowStride, dstRowStride
|
|
when consts.TXT_SIZE_16b
|
|
console.error "TODO: tile format " + tile.fmt + ", tile.size" + tile.siz
|
|
when consts.TXT_SIZE_4b
|
|
if tile.otherModeH & consts.TLUT_FMT_IA16
|
|
console.error "TODO: tile format " + tile.fmt + ", consts.TLUT_FMT_IA16"
|
|
else
|
|
ram = videoHLE.core.memory.u8
|
|
@convertCI4_RGBA16 texture, tmem, 0x800 + (tile.pal << 4), videoHLE.tlut, tileWidth, tileHeight, srcRowOffset, dstRowOffset, srcRowStride, dstRowStride
|
|
else
|
|
console.error "TODO: tile format " + tile.fmt + ", tile.size" + tile.siz
|
|
when consts.TXT_FMT_I
|
|
switch tile.siz
|
|
when consts.TXT_SIZE_4b
|
|
@convertI4 texture, tmem, tileWidth, tileHeight, srcRowOffset, dstRowOffset, srcRowStride, dstRowStride
|
|
when consts.TXT_SIZE_8b
|
|
@convertI8 texture, tmem, tileWidth, tileHeight, srcRowOffset, dstRowOffset, srcRowStride, dstRowStride
|
|
else
|
|
console.error "TODO: tile format " + tile.fmt + ", tile.size" + tile.siz
|
|
else
|
|
console.error "TODO: tile format " + tile.fmt + ", tile.size" + tile.siz
|
|
|
|
# if @useTextureCache is true
|
|
# return @textureCache[textureId]
|
|
# if (nextPow2Width isnt tileWidth) or (nextPow2Height isnt tileHeight)
|
|
# context.putImageData(imageData, 0, 0);
|
|
# return @canvas
|
|
return {textureData:texture, nextPow2Width: nextPow2Width, nextPow2Height: nextPow2Height}
|
|
|
|
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]
|
|
@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]
|
|
@gl.bindBuffer @gl.ARRAY_BUFFER, @texrectVertexTextureCoordBuffer
|
|
@gl.bufferData @gl.ARRAY_BUFFER, new Float32Array(textureCoords), @gl.STATIC_DRAW
|
|
@texrectVertexTextureCoordBuffer.itemSize = 2
|
|
@texrectVertexTextureCoordBuffer.numItems = 4
|
|
return
|
|
|
|
convertRGBA16: (texture, tm, texWidth, texHeight, srcRowOffset, dstRowOffset, srcRowStride, dstRowStride) ->
|
|
`const tmem = tm`
|
|
`const height = texHeight|0`
|
|
`const width = texWidth|0`
|
|
|
|
j=-height
|
|
while j < 0
|
|
i=-width
|
|
srcOffset = srcRowOffset|0
|
|
dstOffset = dstRowOffset|0
|
|
while i < 0
|
|
hi = tmem[srcOffset]|0
|
|
lo = tmem[srcOffset+1]|0
|
|
i++
|
|
texture[dstOffset] = fivetoeight[hi >>> 3]
|
|
srcOffset += 2
|
|
texture[dstOffset + 1] = fivetoeight[(lo >>> 6 | ((hi & 7) << 2))]
|
|
texture[dstOffset + 2] = fivetoeight[lo >> 1 & 0x1F]
|
|
texture[dstOffset + 3] = lo << 31 >> 31
|
|
dstOffset += 4
|
|
j++
|
|
srcRowOffset += srcRowStride
|
|
dstRowOffset += dstRowStride
|
|
return
|
|
|
|
convertRGBA32: (texture, tm, texWidth, texHeight, srcRowOffset, dstRowOffset, srcRowStride, dstRowStride) ->
|
|
`const tmem = tm`
|
|
`const height = texHeight|0`
|
|
`const width = texWidth|0`
|
|
|
|
j=-height
|
|
while j < 0
|
|
i=-width
|
|
srcOffset = srcRowOffset|0
|
|
dstOffset = dstRowOffset|0
|
|
while i < 0
|
|
r = tmem[srcOffset]|0
|
|
g = tmem[srcOffset+1]|0
|
|
b = tmem[srcOffset+2]|0
|
|
a = tmem[srcOffset+3]|0
|
|
i++
|
|
texture[dstOffset] = r
|
|
srcOffset += 4
|
|
texture[dstOffset + 1] = g
|
|
texture[dstOffset + 2] = b
|
|
texture[dstOffset + 3] = a
|
|
dstOffset += 4
|
|
j++
|
|
srcRowOffset += srcRowStride<<1
|
|
dstRowOffset += dstRowStride
|
|
return
|
|
|
|
convertIA8: (texture, tm, texWidth, texHeight, srcRowOffset, dstRowOffset, srcRowStride, dstRowStride) ->
|
|
`const tmem = tm`
|
|
`const height = texHeight|0`
|
|
`const width = texWidth|0`
|
|
|
|
j=-height
|
|
while j < 0
|
|
i=-width
|
|
srcOffset = srcRowOffset
|
|
dstOffset = dstRowOffset
|
|
while i < 0
|
|
b = tmem[srcOffset]|0
|
|
i++
|
|
I = ((b >>> 4) & 0xF) | (b & 0xF0)
|
|
srcOffset += 1
|
|
texture[dstOffset] = I
|
|
texture[dstOffset + 1] = I
|
|
texture[dstOffset + 2] = I
|
|
texture[dstOffset + 3] = ((b << 4) & 0xF0) | (b & 0xF)
|
|
dstOffset += 4
|
|
j++
|
|
srcRowOffset += srcRowStride
|
|
dstRowOffset += dstRowStride
|
|
return
|
|
|
|
convertI4: (texture, tm, texWidth, texHeight, srcRowOffset, dstRowOffset, srcRowStride, dstRowStride) ->
|
|
`const tmem = tm`
|
|
`const height = texHeight|0`
|
|
`const width = texWidth|0`
|
|
|
|
j=-height
|
|
while j < 0
|
|
i=-width
|
|
srcOffset = srcRowOffset
|
|
dstOffset = dstRowOffset
|
|
while i < 0
|
|
bHi = tmem[srcOffset]&0xF0 >>> 4
|
|
bLo = tmem[srcOffset]&0xF
|
|
colorHi = fourtoeight[bHi]
|
|
colorLo = fourtoeight[bLo]
|
|
i++
|
|
texture[dstOffset] = colorHi
|
|
srcOffset++
|
|
texture[dstOffset + 1] = colorHi
|
|
texture[dstOffset + 2] = colorHi
|
|
texture[dstOffset + 3] = colorHi
|
|
texture[dstOffset + 4] = colorLo
|
|
texture[dstOffset + 5] = colorLo
|
|
texture[dstOffset + 6] = colorLo
|
|
texture[dstOffset + 7] = colorLo
|
|
dstOffset += 8
|
|
j++
|
|
srcRowOffset += srcRowStride
|
|
dstRowOffset += dstRowStride
|
|
return
|
|
|
|
convertI8: (texture, tm, texWidth, texHeight, srcRowOffset, dstRowOffset, srcRowStride, dstRowStride) ->
|
|
`const tmem = tm`
|
|
`const height = texHeight|0`
|
|
`const width = texWidth|0`
|
|
|
|
j=-height
|
|
while j < 0
|
|
i=-width
|
|
srcOffset = srcRowOffset
|
|
dstOffset = dstRowOffset
|
|
while i < 0
|
|
b = tmem[srcOffset]|0
|
|
i++
|
|
I = b
|
|
srcOffset += 1
|
|
texture[dstOffset] = I
|
|
texture[dstOffset + 1] = I
|
|
texture[dstOffset + 2] = I
|
|
texture[dstOffset + 3] = I
|
|
dstOffset += 4
|
|
j++
|
|
srcRowOffset += srcRowStride
|
|
dstRowOffset += dstRowStride
|
|
return
|
|
|
|
|
|
convertCI4_RGBA16: (texture, tm, palette, ram, texWidth, texHeight, srcRowOffset, dstRowOffset, srcRowStride, dstRowStride) ->
|
|
`const tmem = tm`
|
|
`const pal = palette`
|
|
`const height = texHeight|0`
|
|
`const width = texWidth|0`
|
|
`const u8 = ram`
|
|
|
|
j=-height
|
|
while j < 0
|
|
i=-width
|
|
srcOffset = srcRowOffset
|
|
dstOffset = dstRowOffset
|
|
while i < 0
|
|
bHi = tmem[srcOffset]&0xF0 >>> 4
|
|
bLo = tmem[srcOffset]&0xF
|
|
colorHi = u8[pal+bHi]<<8 | u8[pal+bHi+1]
|
|
colorLo = u8[pal+bLo]<<8 | u8[pal+bLo+1]
|
|
i++
|
|
texture[dstOffset] = fivetoeight[colorHi >> 11 & 0x1F]
|
|
srcOffset += 1
|
|
texture[dstOffset + 1] = fivetoeight[colorHi >> 6 & 0x1F]
|
|
texture[dstOffset + 2] = fivetoeight[colorHi >> 1 & 0x1F]
|
|
texture[dstOffset + 3] = colorHi << 31 >> 31
|
|
texture[dstOffset + 4] = fivetoeight[colorLo >> 11 & 0x1F]
|
|
texture[dstOffset + 5] = fivetoeight[colorLo >> 6 & 0x1F]
|
|
texture[dstOffset + 6] = fivetoeight[colorLo >> 1 & 0x1F]
|
|
texture[dstOffset + 7] = colorLo << 31 >> 31
|
|
dstOffset += 8
|
|
j++
|
|
srcRowOffset += srcRowStride
|
|
dstRowOffset += dstRowStride
|
|
return
|
|
|
|
convertCI8_RGBA16: (texture, tm, palette, tlut, texWidth, texHeight, srcRowOffset, dstRowOffset, srcRowStride, dstRowStride) ->
|
|
`const tmem = tm`
|
|
`const pal = palette`
|
|
`const height = texHeight|0`
|
|
`const width = texWidth|0`
|
|
`const u8 = tlut`
|
|
|
|
j=-height
|
|
while j < 0
|
|
i=-width
|
|
srcOffset = srcRowOffset
|
|
dstOffset = dstRowOffset
|
|
while i < 0
|
|
b = tmem[srcOffset]
|
|
color = u8[pal+b]<<8 | u8[pal+b+1]
|
|
i++
|
|
srcOffset += 1
|
|
texture[dstOffset] = fivetoeight[color >>> 11 & 0x1F]
|
|
texture[dstOffset + 1] = fivetoeight[color >>> 6 & 0x1F]
|
|
texture[dstOffset + 2] = fivetoeight[color >>> 1 & 0x1F]
|
|
texture[dstOffset + 3] = color << 31 >> 31
|
|
dstOffset += 4
|
|
j++
|
|
srcRowOffset += srcRowStride
|
|
dstRowOffset += dstRowStride
|
|
return
|
|
|
|
|
|
convertCI8_IA16: (texture, tm, palette, tlut, texWidth, texHeight, srcRowOffset, dstRowOffset, srcRowStride, dstRowStride) ->
|
|
`const tmem = tm`
|
|
`const pal = palette`
|
|
`const height = texHeight|0`
|
|
`const width = texWidth|0`
|
|
`const u8 = tlut`
|
|
|
|
j=-height
|
|
while j < 0
|
|
i=-width
|
|
srcOffset = srcRowOffset
|
|
dstOffset = dstRowOffset
|
|
while i < 0
|
|
b = tmem[srcOffset]
|
|
I = u8[pal+b]
|
|
a = u8[pal+b+1]
|
|
i++
|
|
srcOffset += 1
|
|
texture[dstOffset] = I
|
|
texture[dstOffset + 1] = I
|
|
texture[dstOffset + 2] = I
|
|
texture[dstOffset + 3] = a
|
|
dstOffset += 4
|
|
j++
|
|
srcRowOffset += srcRowStride
|
|
dstRowOffset += dstRowStride
|
|
return
|
|
|
|
|
|
convertIA16ToRGBA: (wIA) ->
|
|
intensity = (wIA >> 8) & 0xFF
|
|
alpha = (wIA ) & 0xFF
|
|
return @COLOR_RGBA dwIntensity, dwIntensity, dwIntensity, dwAlpha
|
|
|
|
|
|
convertIA4: (texture, tm, texWidth, texHeight, srcRowOffset, dstRowOffset, srcRowStride, dstRowStride) ->
|
|
`const tmem = tm`
|
|
`const height = texHeight|0`
|
|
`const width = texWidth|0`
|
|
|
|
j=-height
|
|
while j < 0
|
|
i=-width
|
|
srcOffset = srcRowOffset
|
|
dstOffset = dstRowOffset
|
|
while i < 0
|
|
b = tmem[srcOffset]|0
|
|
i+=2
|
|
I0 = threetoeight[(b & 0xe0)>>>5]
|
|
srcOffset += 1
|
|
I1 = threetoeight[(b & 0x0e)>>>1]
|
|
texture[dstOffset] = I0
|
|
texture[dstOffset + 1] = I0
|
|
texture[dstOffset + 2] = I0
|
|
texture[dstOffset + 3] = b << 27 >> 31
|
|
texture[dstOffset + 4] = I1
|
|
texture[dstOffset + 5] = I1
|
|
texture[dstOffset + 6] = I1
|
|
texture[dstOffset + 7] = b << 31 >> 31
|
|
dstOffset += 8
|
|
if width & 1
|
|
b = tmem[srcOffset]|0
|
|
i+=1
|
|
I0 = threetoeight[(b & 0xe0)>>>5]
|
|
srcOffset += 1
|
|
texture[dstOffset] = I0
|
|
texture[dstOffset + 1] = I0
|
|
texture[dstOffset + 2] = I0
|
|
texture[dstOffset + 3] = b << 27 >> 31
|
|
dstOffset += 4
|
|
j++
|
|
srcRowOffset += srcRowStride
|
|
dstRowOffset += dstRowStride
|
|
return
|
|
|
|
convertIA16: (texture, tm, texWidth, texHeight, srcRowOffset, dstRowOffset, srcRowStride, dstRowStride) ->
|
|
`const tmem = tm`
|
|
`const height = texHeight|0`
|
|
`const width = texWidth|0`
|
|
|
|
j=-height
|
|
while j < 0
|
|
i=-width
|
|
srcOffset = srcRowOffset
|
|
dstOffset = dstRowOffset
|
|
while i < 0
|
|
I = tmem[srcOffset]|0
|
|
i++
|
|
texture[dstOffset] = I
|
|
texture[dstOffset + 1] = I
|
|
texture[dstOffset + 2] = I
|
|
texture[dstOffset + 3] = tmem[srcOffset+1]
|
|
srcOffset += 2
|
|
dstOffset += 4
|
|
j++
|
|
srcRowOffset += srcRowStride
|
|
dstRowOffset += dstRowStride
|
|
return
|
|
|
|
draw: (gl, tileno, tile, tmem, videoHLE, nextPow2Width, nextPow2Height, tileWidth, tileHeight, isFillRect) ->
|
|
videoHLE.setBlendFunc()
|
|
# gl.useProgram webGL.shaderProgram
|
|
|
|
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
|
|
|
|
#console.log "Binding Texture Size: "+tileWidth+" x "+tileHeight+" -> "+canvaswidth+" x "+canvasheight
|
|
|
|
tData = @formatTexture(tile, tmem, videoHLE, isFillRect)
|
|
|
|
if tileWidth <= 0 or tileHeight <= 0
|
|
else if tData isnt undefined and tData.textureData isnt undefined
|
|
textureData = tData.textureData
|
|
|
|
gl.activeTexture(gl.TEXTURE0 + tileno)
|
|
gl.bindTexture(gl.TEXTURE_2D, @colorsTexture0)
|
|
gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, tileWidth, tileHeight, 0, gl.RGBA, gl.UNSIGNED_BYTE, textureData)
|
|
|
|
wrapS = gl.REPEAT
|
|
wrapT = gl.REPEAT
|
|
if ((tile.cms is consts.RDP_TXT_CLAMP) or (tile.masks is 0))
|
|
wrapS = gl.CLAMP_TO_EDGE
|
|
else if tile.cms is consts.RDP_TXT_MIRROR
|
|
wrapS = gl.MIRRORED_REPEAT
|
|
if ((tile.cmt is consts.RDP_TXT_CLAMP) or (tile.maskt is 0))
|
|
wrapT = gl.CLAMP_TO_EDGE
|
|
else if tile.cmt is consts.RDP_TXT_MIRROR
|
|
wrapT = gl.MIRRORED_REPEAT
|
|
gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS)
|
|
gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT)
|
|
|
|
gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
|
|
gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
|
|
gl.uniform1i @webGL.shaderProgram.samplerUniform, @colorsTexture0
|
|
|
|
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
|
|
|
|
|
|
if isFillRect is true
|
|
cycleType = 3
|
|
else
|
|
cycleType = videoHLE.cycleType
|
|
gl.uniform1i @webGL.shaderProgram.cycleType, cycleType
|
|
|
|
gl.bindBuffer gl.ELEMENT_ARRAY_BUFFER, @texrectVertexIndexBuffer
|
|
@webGL.setMatrixUniforms @webGL.shaderProgram
|
|
# webGL.setCombineUniforms videoHLE, webGL.shaderProgram
|
|
|
|
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
|
|
|
|
@texrectVertexTextureCoordBuffer.numItems = 0
|
|
@texrectVertexPositionBuffer.numItems = 0
|
|
return
|
|
|
|
#hack global space until we export classes properly
|
|
#node.js uses exports; browser uses this (window)
|
|
root = exports ? self
|
|
root.C1964jsRenderer = C1964jsRenderer
|