1964js/coffee/videoHLE.coffee

1228 lines
No EOL
42 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.###
#jslint todo: true, bitwise: true
#globals window, mat4, C1964jsRenderer, consts, dec2hex, Float32Array
C1964jsVideoHLE = (core, glx) ->
"use strict"
@processDisplayList = @callBind @processDisplayList, this
i = undefined
@core = core #only needed for gfxHelpers prototypes to access.
@gl = glx
@DirectX_OGL_BlendFuncMaps = [
@gl.SRC_ALPHA,
@gl.ZERO,
@gl.ONE,
@gl.SRC_COLOR,
@gl.ONE_MINUS_SRC_COLOR,
@gl.SRC_ALPHA,
@gl.ONE_MINUS_SRC_ALPHA,
@gl.DST_ALPHA,
@gl.ONE_MINUS_DST_ALPHA,
@gl.DST_COLOR,
@gl.ONE_MINUS_DST_COLOR,
@gl.SRC_ALPHA_SATURATE,
@gl.SRC_ALPHA_SATURATE,
@gl.SRC_ALPHA_SATURATE
]
#todo: make gRSP a class object.
@RICE_MATRIX_STACK = 60
@MAX_TEXTURES = 8
@MAX_VERTICES = 80
@MAX_TILES = 8
@tmem = new Uint8Array(1024 * 4)
@activeTile = 0
@textureTile = []
@N64VertexList = []
@vtxTransformed = []
@vtxNonTransformed = []
@vecProjected = []
@vtxProjected5 = []
@geometryMode = 0
@gRSP = {}
@matToLoad = mat4.create()
@gRSPworldProject = mat4.create()
@triangleVertexPositionBuffer = `undefined`
@triangleVertexColorBuffer = `undefined`
@dlistStackPointer = 0
@dlistStack = []
@renderer = new C1964jsRenderer(@core.settings, @core.webGL.gl, @core.webGL)
@texImg = {}
@segments = []
@primColor = []
@fillColor = []
@blendColor = []
@envColor = []
@triVertices = new Float32Array(16384)
@triColorVertices = new Uint8Array(16384)
@triTextureCoords = new Float32Array(16384)
@otherModeL = 0
@otherModeH = 0
#todo: different microcodes support
@currentMicrocodeMap = @microcodeMap0
i = 0
while i < @MAX_TILES
@textureTile[i] = []
i += 1
i = 0
while i < @MAX_VERTICES
@N64VertexList[i] = {}
i += 1
i = 0
while i < consts.MAX_DL_STACK_SIZE
@dlistStack[i] = {}
i += 1
i = 0
while i < @segments.length
@segments[i] = 0
i += 1
@gRSP.projectionMtxs = []
@gRSP.modelviewMtxs = []
#todo: allocate on-demand
i = 0
while i < @RICE_MATRIX_STACK
@gRSP.projectionMtxs[i] = mat4.create()
@gRSP.modelviewMtxs[i] = mat4.create()
i += 1
@gRSP.vertexMult = 10
@triangleVertexTextureCoordBuffer = `undefined`
return this
(->
"use strict"
C1964jsVideoHLE::callBind = (fn, me) ->
->
fn.call me
C1964jsVideoHLE::processDisplayList = ->
if @core.showFB is true
@initBuffers()
@core.webGL.show3D()
@core.showFB = false
@resetState()
@core.webGL.beginDList()
@dlParserProcess()
#this.core.interrupts.triggerDPInterrupt(0, false);
@core.interrupts.triggerSPInterrupt 0, false
C1964jsVideoHLE::videoLog = (msg) ->
#console.log msg
return
C1964jsVideoHLE::dlParserProcess = ->
@dlistStackPointer = 0
@dlistStack[@dlistStackPointer].pc = (@core.memory.spMemUint8Array[consts.TASK_DATA_PTR] << 24 | @core.memory.spMemUint8Array[consts.TASK_DATA_PTR + 1] << 16 | @core.memory.spMemUint8Array[consts.TASK_DATA_PTR + 2] << 8 | @core.memory.spMemUint8Array[consts.TASK_DATA_PTR + 3])>>>0
@dlistStack[@dlistStackPointer].countdown = consts.MAX_DL_COUNT
#see RSP_Parser.cpp
#TODO: purge old textures
#TODO: stats
#TODO: force screen clear
#TODO: set vi scales
@renderReset()
#TODO: render reset
#TODO: begin rendering
#TODO: set viewport
#TODO: set fill mode
while @dlistStackPointer >= 0
pc = @dlistStack[@dlistStackPointer].pc
cmd = @getCommand(pc)
func = @currentMicrocodeMap[cmd]
@dlistStack[@dlistStackPointer].pc += 8
this[func] pc
if @dlistStackPointer >= 0
@dlistStack[@dlistStackPointer].countdown -= 1
@dlistStackPointer -= 1 if @dlistStack[@dlistStackPointer].countdown < 0
#@videoLog "finished dlist"
@core.interrupts.triggerSPInterrupt 0, false
return
#TODO: end rendering
C1964jsVideoHLE::RDP_GFX_PopDL = ->
@dlistStackPointer -= 1
return
C1964jsVideoHLE::RSP_RDP_Nothing = (pc) ->
#@videoLog "RSP RDP NOTHING"
@dlistStackPointer -= 1
return
C1964jsVideoHLE::RSP_GBI1_MoveMem = (pc) ->
addr = undefined
length = undefined
type = @getGbi1Type(pc)
length = @getGbi1Length(pc)
addr = @getGbi1RspSegmentAddr(pc)
#@videoLog "movemem type=" + type + ", length=" + length + " addr=" + addr
return
C1964jsVideoHLE::RSP_GBI1_SpNoop = (pc) ->
#@videoLog "RSP_GBI1_SpNoop"
return
C1964jsVideoHLE::RSP_GBI1_Reserved = (pc) ->
#@videoLog "RSP_GBI1_Reserved"
return
C1964jsVideoHLE::setProjection = (mat, bPush, bReplace) ->
if bPush is true
if @gRSP.projectionMtxTop >= (@RICE_MATRIX_STACK - 1)
@gRSP.bMatrixIsUpdated = true
return
@gRSP.projectionMtxTop += 1
if bReplace
# Load projection matrix
mat4.set mat, @gRSP.projectionMtxs[@gRSP.projectionMtxTop]
else
mat4.multiply @gRSP.projectionMtxs[@gRSP.projectionMtxTop - 1], mat, @gRSP.projectionMtxs[@gRSP.projectionMtxTop]
else
if bReplace
# Load projection matrix
mat4.set mat, @gRSP.projectionMtxs[@gRSP.projectionMtxTop]
else
mat4.multiply @gRSP.projectionMtxs[@gRSP.projectionMtxTop], mat, @gRSP.projectionMtxs[@gRSP.projectionMtxTop]
@gRSP.bMatrixIsUpdated = true
return
C1964jsVideoHLE::setWorldView = (mat, bPush, bReplace) ->
if bPush is true
if @gRSP.modelViewMtxTop >= (@RICE_MATRIX_STACK - 1)
@gRSP.bMatrixIsUpdated = true
return
@gRSP.modelViewMtxTop += 1
# We should store the current projection matrix...
if bReplace
# Load projection matrix
mat4.set mat, @gRSP.modelviewMtxs[@gRSP.modelViewMtxTop]
else # Multiply projection matrix
mat4.multiply @gRSP.modelviewMtxs[@gRSP.modelViewMtxTop - 1], mat, @gRSP.modelviewMtxs[@gRSP.modelViewMtxTop]
# this.gRSP.modelviewMtxs[this.gRSP.modelViewMtxTop] = mat * this.gRSP.modelviewMtxs[this.gRSP.modelViewMtxTop-1];
else # NoPush
if bReplace
# Load projection matrix
mat4.set mat, @gRSP.modelviewMtxs[@gRSP.modelViewMtxTop]
else
# Multiply projection matrix
mat4.multiply @gRSP.modelviewMtxs[@gRSP.modelViewMtxTop], mat, @gRSP.modelviewMtxs[@gRSP.modelViewMtxTop]
#this.gRSP.modelviewMtxs[this.gRSP.modelViewMtxTop] = mat * this.gRSP.modelviewMtxs[this.gRSP.modelViewMtxTop];
#gRSPmodelViewTop = this.gRSP.modelviewMtxs[this.gRSP.modelViewMtxTop];
@gRSP.bMatrixIsUpdated = true
return
C1964jsVideoHLE::RSP_GBI0_Mtx = (pc) ->
addr = undefined
seg = @getGbi0DlistAddr(pc)
addr = @getRspSegmentAddr(seg)
#@videoLog "RSP_GBI0_Mtx addr: " + dec2hex(addr)
@loadMatrix addr
if @gbi0isProjectionMatrix(pc)
@setProjection @matToLoad, @gbi0PushMatrix(pc), @gbi0LoadMatrix(pc)
else
@setWorldView @matToLoad, @gbi0PushMatrix(pc), @gbi0LoadMatrix(pc)
return
C1964jsVideoHLE::loadMatrix = (addr) ->
# todo: port and probably log warning message if true
# if (addr + 64 > g_dwRamSize)
# {
# return;
# }
i = undefined
j = undefined
lo = undefined
hi = undefined
a = undefined
k = 0
i = 0
while i < 4
j = 0
while j < 4
a = addr + (i << 3) + (j << 1)
hi = (@core.memory.rdramUint8Array[a] << 8 | @core.memory.rdramUint8Array[a + 1]) & 0x0000FFFF
lo = (@core.memory.rdramUint8Array[a + 32] << 8 | @core.memory.rdramUint8Array[a + 32 + 1]) & 0x0000FFFF
@matToLoad[k] = ((hi << 16) | lo) / 65536.0
k += 1
j += 1
i += 1
return
#tile info.
C1964jsVideoHLE::DLParser_SetTImg = (pc) ->
@texImg.format = @getTImgFormat(pc)
@texImg.size = @getTImgSize(pc)
@texImg.width = @getTImgWidth(pc) + 1
@texImg.addr = @getTImgAddr(pc)
@texImg.bpl = @texImg.width << @texImg.size >> 1
@texImg.changed = true #no texture cache
#console.log "SetTImg: Format:"+ @texImg.format + " Size:" + @texImg.size + " Width: "+ @texImg.width
#@videoLog "TODO: DLParser_SetTImg"
return
#this.videoLog('Texture: format=' + this.texImg.format + ' size=' + this.texImg.size + ' ' + 'width=' + this.texImg.width + ' addr=' + this.texImg.addr + ' bpl=' + this.texImg.bpl);
C1964jsVideoHLE::RSP_GBI0_Vtx = (pc) ->
v0 = undefined
seg = undefined
addr = undefined
num = @getGbi0NumVertices(pc) + 1
v0 = @getGbi0Vertex0(pc)
seg = @getGbi0DlistAddr(pc)
addr = @getRspSegmentAddr(seg)
num = 32 - v0 if (v0 + num) > 80
#TODO: check that address is valid
@processVertexData addr, v0, num
return
C1964jsVideoHLE::updateCombinedMatrix = ->
return #this is set in the shader
if @gRSP.bMatrixIsUpdated
pmtx = undefined
vmtx = @gRSP.modelviewMtxs[@gRSP.modelViewMtxTop]
pmtx = @gRSP.projectionMtxs[@gRSP.projectionMtxTop]
mat4.multiply pmtx, vmtx, @gRSPworldProject
#this.gRSPworldProject = this.gRSP.modelviewMtxs[this.gRSP.modelViewMtxTop] * this.gRSP.projectionMtxs[this.gRSP.projectionMtxTop];
@gRSP.bMatrixIsUpdated = false
return
C1964jsVideoHLE::processVertexData = (addr, v0, num) ->
a = undefined
i = v0
@updateCombinedMatrix()
i = v0
texWidth = @textureTile[@activeTile].width
texHeight = @textureTile[@activeTile].height
while i < v0 + num
a = addr + 16 * (i - v0)
@N64VertexList[i].x = @getVertexX(a)
@N64VertexList[i].y = @getVertexY(a)
@N64VertexList[i].z = @getVertexZ(a)
@N64VertexList[i].s = @getVertexS(a)/32 / texWidth
@N64VertexList[i].t = @getVertexT(a)/32 / texHeight
@N64VertexList[i].r = @getVertexColorR(a)
@N64VertexList[i].g = @getVertexColorG(a)
@N64VertexList[i].b = @getVertexColorB(a)
@N64VertexList[i].a = @getVertexAlpha(a)
#until we use it..
#@N64VertexList[i].nx = (@toSByte @getVertexNormalX(a))
#@N64VertexList[i].ny = (@toSByte @getVertexNormalY(a))
#@N64VertexList[i].nz = (@toSByte @getVertexNormalZ(a))
#console.log "Vertex "+i+": XYZ("+@N64VertexList[i].x+" , "+@N64VertexList[i].y+" , "+@N64VertexList[i].z+") ST("+@N64VertexList[i].s+" , "+@N64VertexList[i].t+") RGBA("+@N64VertexList[i].r+" , "+@N64VertexList[i].g+" , "+@N64VertexList[i].b+" , "+@N64VertexList[i].a+") N("+@N64VertexList[i].nx+" , "+@N64VertexList[i].ny+" , "+@N64VertexList[i].nz+")"
i += 1
return
C1964jsVideoHLE::DLParser_SetCImg = (pc) ->
#@videoLog "TODO: DLParser_SetCImg"
return
#Gets new display list address
C1964jsVideoHLE::RSP_GBI0_DL = (pc) ->
param = undefined
seg = @getGbi0DlistAddr(pc)
addr = @getRspSegmentAddr(seg)
#@videoLog "dlist address = " + dec2hex(addr)
#TODO: address adjust
param = @getGbi0DlistParam(pc)
@dlistStackPointer += 1 if param is consts.RSP_DLIST_PUSH
@dlistStack[@dlistStackPointer].pc = addr
@dlistStack[@dlistStackPointer].countdown = consts.MAX_DL_COUNT
return
C1964jsVideoHLE::DLParser_SetCombine = (pc) ->
@combineA0 = @getCombineA0(pc)
@combineB0 = @getCombineB0(pc)
@combineC0 = @getCombineC0(pc)
@combineD0 = @getCombineD0(pc)
#@combineA0 = 0xFF if @combineA0 is 15
#@combineB0 = 0xFF if @combineB0 is 15
#@combineC0 = 0xFF if @combineC0 is 31
#@combineD0 = 0xFF if @combineD0 is 7
@combineA0a = @getCombineA0a(pc)
@combineB0a = @getCombineB0a(pc)
@combineC0a = @getCombineC0a(pc)
@combineD0a = @getCombineD0a(pc)
#@combineA0a = 0xFF if @combineA0a is 7
#@combineB0a = 0xFF if @combineB0a is 7
#@combineC0a = 0xFF if @combineC0a is 7
#@combineD0a = 0xFF if @combineD0a is 7
@combineA1 = @getCombineA1(pc)
@combineB1 = @getCombineB1(pc)
@combineC1 = @getCombineC1(pc)
@combineD1 = @getCombineD1(pc)
#@combineA1 = 0xFF if @combineA1 is 15
#@combineB1 = 0xFF if @combineB1 is 15
#@combineC1 = 0xFF if @combineC1 is 31
#@combineD1 = 0xFF if @combineD1 is 7
@combineA1a = @getCombineA1a(pc)
@combineB1a = @getCombineB1a(pc)
@combineC1a = @getCombineC1a(pc)
@combineD1a = @getCombineD1a(pc)
#@combineA1a = 0xFF if @combineA1a is 7
#@combineB1a = 0xFF if @combineB1a is 7
#@combineC1a = 0xFF if @combineC1a is 7
#@combineD1a = 0xFF if @combineD1a is 7
w0 = @core.memory.rdramUint8Array[pc] << 24 | @core.memory.rdramUint8Array[pc + 1] << 16 | @core.memory.rdramUint8Array[pc + 2] << 8 | @core.memory.rdramUint8Array[pc + 3]
w1 = @core.memory.rdramUint8Array[pc + 4] << 24 | @core.memory.rdramUint8Array[pc + 5] << 16 | @core.memory.rdramUint8Array[pc + 6] << 8 | @core.memory.rdramUint8Array[pc + 7]
#if (@combineD0 == 4)
# console.log " a0:" + @combineA0 + " b0:" + @combineB0 + " c0:" + @combineC0 + " d0:" + @combineD0 + " a0a:" + @combineA0a + " b0a:" + @combineB0a + " c0a:" + @combineC0a + " d0a:" + @combineD0a + " a1:" + @combineA1 + " b1:" + @combineB1 + " c1:" + @combineC1 + " d1:" + @combineD1 + " a1a:" + @combineA1a + " b1a:" + @combineB1a + " c1a:" + @combineC1a + " d1a:" + @combineD1a
#@videoLog "TODO: DLParser_SetCombine"
return
C1964jsVideoHLE::RSP_GBI1_MoveWord = (pc) ->
#@videoLog "RSP_GBI1_MoveWord"
switch @getGbi0MoveWordType(pc)
when consts.RSP_MOVE_WORD_MATRIX
@RSP_RDP_InsertMatrix()
when consts.RSP_MOVE_WORD_SEGMENT
dwBase = undefined
dwSegment = (@getGbi0MoveWordOffset(pc) >> 2) & 0x0F
dwBase = @getGbi0MoveWordValue(pc) & 0x00FFFFFF
@segments[dwSegment] = dwBase
else
return
C1964jsVideoHLE::renderReset = ->
#UpdateClipRectangle();
@resetMatrices()
#SetZBias(0);
@gRSP.numVertices = 0
@gRSP.curTile = 0
@gRSP.fTexScaleX = 1 / 32.0
@gRSP.fTexScaleY = 1 / 32.0
return
C1964jsVideoHLE::resetMatrices = ->
@gRSP.projectionMtxTop = 0
@gRSP.modelViewMtxTop = 0
@gRSP.projectionMtxs[0] = mat4.create()
@gRSP.modelviewMtxs[0] = mat4.create()
mat4.identity @gRSP.modelviewMtxs[0]
mat4.identity @gRSP.projectionMtxs[0]
@gRSP.bMatrixIsUpdated = true
@updateCombinedMatrix()
return
C1964jsVideoHLE::RSP_RDP_InsertMatrix = ->
@updateCombinedMatrix()
@gRSP.bMatrixIsUpdated = false
return
C1964jsVideoHLE::DLParser_SetScissor = (pc) ->
#@videoLog "TODO: DLParser_SetScissor"
return
C1964jsVideoHLE::RSP_GBI1_SetOtherModeH = (pc) ->
#@videoLog "TODO: DLParser_GBI1_SetOtherModeH"
@otherModeH = @getOtherModeH()
#alert @otherModeH
return
C1964jsVideoHLE::RSP_GBI1_SetOtherModeL = (pc) ->
#@videoLog "TODO: DLParser_GBI1_SetOtherModeL"
@otherModeL = @getOtherModeL()
#alert dec2hex @otherModeL
return
C1964jsVideoHLE::RSP_GBI0_Sprite2DBase = (pc) ->
#@videoLog "TODO: RSP_GBI0_Sprite2DBase"
return
C1964jsVideoHLE::RSP_GBI0_Tri4 = (pc) ->
#@videoLog "TODO: RSP_GBI0_Tri4"
return
C1964jsVideoHLE::RSP_GBI1_RDPHalf_Cont = (pc) ->
#@videoLog "TODO: RSP_GBI1_RDPHalf_Cont"
return
C1964jsVideoHLE::RSP_GBI1_RDPHalf_2 = (pc) ->
#@videoLog "TODO: RSP_GBI1_RDPHalf_2"
return
C1964jsVideoHLE::RSP_GBI1_RDPHalf_1 = (pc) ->
#@videoLog "TODO: RSP_GBI1_RDPHalf_1"
return
C1964jsVideoHLE::RSP_GBI1_Line3D = (pc) ->
#@videoLog "TODO: RSP_GBI1_Line3D"
return
C1964jsVideoHLE::RSP_GBI1_ClearGeometryMode = (pc) ->
data = @getClearGeometryMode(pc)
@geometryMode &= ~data
#@videoLog "TODO: RSP_GBI1_ClearGeometryMode"
return
C1964jsVideoHLE::RSP_GBI1_SetGeometryMode = (pc) ->
data = @getSetGeometryMode(pc)
@geometryMode |= data
#@videoLog "TODO: RSP_GBI1_SetGeometryMode"
return
C1964jsVideoHLE::RSP_GBI1_EndDL = (pc) ->
#@videoLog "RSP_GBI1_EndDL"
@RDP_GFX_PopDL()
@drawScene(false, 7)
#alert "EndFrame"
return
C1964jsVideoHLE::RSP_GBI1_Texture = (pc) ->
tile = @getTextureTile(pc)
@textureTile[tile].on = @getTextureOn(pc)
@textureTile[tile].level = @getTextureLevel(pc)
@textureTile[tile].scales = @getTextureScaleS(pc) / 0x8000
@textureTile[tile].scalet = @getTextureScaleT(pc) / 0x8000
#console.log "RSP_GBI1_Texture: Tile:" + tile + " On:" + @textureTile[tile].on + " Level:" + @textureTile[tile].level + " ScaleS:" + @textureTile[tile].scales + " ScaleT:" + @textureTile[tile].scalet
return
C1964jsVideoHLE::RSP_GBI1_PopMtx = (pc) ->
#@videoLog "TODO: RSP_GBI1_PopMtx"
return
C1964jsVideoHLE::RSP_GBI1_CullDL = (pc) ->
#@videoLog "TODO: RSP_GBI1_CullDL"
return
C1964jsVideoHLE::RSP_GBI1_Tri1 = (pc) ->
v0 = @getGbi0Tri1V0(pc) / @gRSP.vertexMult
v1 = @getGbi0Tri1V1(pc) / @gRSP.vertexMult
v2 = @getGbi0Tri1V2(pc) / @gRSP.vertexMult
flag = @getGbi0Tri1Flag(pc)
#console.log "Tri1: "+v0+", "+v1+", "+v2+" Flag: "+flag
didSucceed = @prepareTriangle v0, v1, v2
if didSucceed is false
return
cmd = @getCommand(pc+8)
func = @currentMicrocodeMap[cmd]
# @drawScene(false, 7)
# if func isnt "RSP_GBI1_Tri1"
# @drawScene false, 7
return
C1964jsVideoHLE::RSP_GBI1_Noop = (pc) ->
#@videoLog "TODO: RSP_GBI1_Noop"
return
C1964jsVideoHLE::RDP_TriFill = (pc) ->
#@videoLog "TODO: RDP_TriFill"
return
C1964jsVideoHLE::RDP_TriFillZ = (pc) ->
#@videoLog "RDP_TriFillZ"
return
C1964jsVideoHLE::RDP_TriTxtr = (pc) ->
#@videoLog "TODO: RDP_TriTxtr"
return
C1964jsVideoHLE::RDP_TriTxtrZ = (pc) ->
#@videoLog "TODO: RDP_TriTxtrZ"
return
C1964jsVideoHLE::RDP_TriShade = (pc) ->
#@videoLog "TODO: RDP_TriShade"
return
C1964jsVideoHLE::RDP_TriShadeZ = (pc) ->
#@videoLog "TODO: RDP_TriShadeZ"
return
C1964jsVideoHLE::RDP_TriShadeTxtr = (pc) ->
#@videoLog "TODO: RDP_TriShadeTxtr"
return
C1964jsVideoHLE::RDP_TriShadeTxtrZ = (pc) ->
#@videoLog "TODO: RDP_TriShadeTxtrZ"
return
C1964jsVideoHLE::DLParser_TexRect = (pc) ->
#@videoLog "TODO: DLParser_TexRect"
xh = @getTexRectXh(pc) / 4
yh = @getTexRectYh(pc) / 4
tileno = @getTexRectTileNo(pc)
xl = @getTexRectXl(pc) / 4
yl = @getTexRectYl(pc) / 4
s = @getTexRectS(pc) / 32
t = @getTexRectT(pc) / 32
dsdx = @getTexRectDsDx(pc) / 1024
dtdy = @getTexRectDtDy(pc) / 1024
#console.log "Texrect: UL("+xl+","+yl+") LR("+xh+","+yh+") Tile:"+tileno+" TexCoord:("+s+","+t+") TexSlope:("+dsdx+","+dtdy+")"
@renderer.texRect xl, yl, xh, yh, s, t, dsdx, dtdy, @textureTile[tileno], @tmem, this
@dlistStack[@dlistStackPointer].pc += 8
@hasTexture = true
return
C1964jsVideoHLE::DLParser_TexRectFlip = (pc) ->
@dlistStack[@dlistStackPointer].pc += 8
#@videoLog "TODO: DLParser_TexRectFlip"
return
C1964jsVideoHLE::DLParser_RDPLoadSynch = (pc) ->
#@videoLog "TODO: DLParser_RDPLoadSynch"
return
C1964jsVideoHLE::DLParser_RDPPipeSynch = (pc) ->
#@videoLog "TODO: DLParser_RDPPipeSynch"
return
C1964jsVideoHLE::DLParser_RDPTileSynch = (pc) ->
#@videoLog "TODO: DLParser_RDPTileSynch"
return
C1964jsVideoHLE::DLParser_RDPFullSynch = (pc) ->
#@videoLog "TODO: DLParser_RDPFullSynch"
@core.interrupts.triggerDPInterrupt 0, false
#@drawScene(7, false)
return
C1964jsVideoHLE::DLParser_SetKeyGB = (pc) ->
#@videoLog "TODO: DLParser_SetKeyGB"
return
C1964jsVideoHLE::DLParser_SetKeyR = (pc) ->
#@videoLog "TODO: DLParser_SetKeyR"
return
C1964jsVideoHLE::DLParser_SetConvert = (pc) ->
#@videoLog "TODO: DLParser_SetConvert"
return
C1964jsVideoHLE::DLParser_SetPrimDepth = (pc) ->
#@videoLog "TODO: DLParser_SetPrimDepth"
return
C1964jsVideoHLE::DLParser_RDPSetOtherMode = (pc) ->
#@videoLog "TODO: DLParser_RDPSetOtherMode"
return
C1964jsVideoHLE::DLParser_LoadTLut = (pc) ->
#@videoLog "TODO: DLParser_LoadTLut"
return
C1964jsVideoHLE::DLParser_SetTileSize = (pc) ->
tile = @getSetTileSizeTile(pc)
@textureTile[tile].uls = @getSetTileSizeUls(pc)
@textureTile[tile].ult = @getSetTileSizeUlt(pc)
@textureTile[tile].lrs = (@getSetTileSizeLrs(pc) >> 2) + 1
@textureTile[tile].lrt = (@getSetTileSizeLrt(pc) >> 2) + 1
@textureTile[tile].width = @textureTile[tile].lrs - @textureTile[tile].uls
@textureTile[tile].height = @textureTile[tile].lrt - @textureTile[tile].ult
#console.log "SetTileSize: UL("+@textureTile[tile].uls+"/"+@textureTile[tile].ult+") LR("+@textureTile[tile].lrs+"/"+@textureTile[tile].lrt+") Dim: "+@textureTile[tile].width+"x"+@textureTile[tile].height
#@videoLog "TODO: DLParser_SetTileSize"
return
C1964jsVideoHLE::DLParser_LoadBlock = (pc) ->
tile = @getLoadBlockTile(pc)
uls = @getLoadBlockUls(pc)
ult = @getLoadBlockUlt(pc)
lrs = @getLoadBlockLrs(pc)+1
dxt = @getLoadBlockDxt(pc)
#console.log "LoadBlock: Tile:"+tile+" UL("+uls+"/"+ult+") LRS:"+lrs+" DXT: 0x"+dec2hex(dxt)
#textureAddr = @core.memory.rdramUint8Array[@texImg.addr])
bytesToXfer = lrs * @textureTile[tile].siz
if bytesToXfer > 4096
console.error "LoadBlock is making too large of a transfer. "+bytesToXfer+" bytes"
i=0
while i < bytesToXfer
@tmem[i]= @core.memory.rdramUint8Array[@texImg.addr+i]
i++
#@videoLog "TODO: DLParser_LoadBlock"
return
C1964jsVideoHLE::DLParser_LoadTile = (pc) ->
#@videoLog "TODO: DLParser_LoadTile"
return
C1964jsVideoHLE::DLParser_SetTile = (pc) ->
tile = @getSetTileTile(pc)
@activeTile = tile
@textureTile[tile].fmt = @getSetTileFmt(pc);
@textureTile[tile].siz = @getSetTileSiz(pc);
@textureTile[tile].line = @getSetTileLine(pc);
@textureTile[tile].tmem = @getSetTileTmem(pc);
@textureTile[tile].pal = @getSetTilePal(pc);
@textureTile[tile].cmt = @getSetTileCmt(pc);
@textureTile[tile].cms = @getSetTileCms(pc);
@textureTile[tile].maskt = @getSetTileMaskt(pc);
@textureTile[tile].masks = @getSetTileMasks(pc);
@textureTile[tile].shiftt = @getSetTileShiftt(pc);
@textureTile[tile].shifts = @getSetTileShifts(pc);
#if @combineD0 == 4
#console.log "SetTile:"+tile+" FMT:"+@textureTile[tile].fmt+" SIZ:"+@textureTile[tile].siz+" LINE: "+@textureTile[tile].line+" TMEM:"+@textureTile[tile].tmem+" PAL:"+@textureTile[tile].pal+" CMS/T:"+@textureTile[tile].cms+"/"+@textureTile[tile].cmt+" MASKS/T:"+@textureTile[tile].masks+"/"+@textureTile[tile].maskt+" SHIFTS/T:"+@textureTile[tile].shifts+"/"+@textureTile[tile].shiftt
#@videoLog "TODO: DLParser_SetTile"
return
C1964jsVideoHLE::DLParser_FillRect = (pc) ->
#@videoLog "TODO: DLParser_FillRect"
return
C1964jsVideoHLE::DLParser_SetFillColor = (pc) ->
@fillColor = []
@fillColor.push @getSetFillColorR(pc)/255.0;
@fillColor.push @getSetFillColorG(pc)/255.0;
@fillColor.push @getSetFillColorB(pc)/255.0;
@fillColor.push @getSetFillColorA(pc)/255.0;
#@videoLog "TODO: DLParser_SetFillColor"
return
C1964jsVideoHLE::DLParser_SetFogColor = (pc) ->
#@videoLog "TODO: DLParser_SetFogColor"
return
C1964jsVideoHLE::DLParser_SetBlendColor = (pc) ->
@blendColor = []
@blendColor.push @getSetFillColorR(pc)/255.0
@blendColor.push @getSetFillColorG(pc)/255.0
@blendColor.push @getSetFillColorB(pc)/255.0
@blendColor.push @getSetFillColorA(pc)/255.0
return
C1964jsVideoHLE::blendFunc = (src, dest) ->
@gl.blendFunc DirectX_OGL_BlendFuncMaps[src], DirectX_OGL_BlendFuncMaps[dest]
return
C1964jsVideoHLE::DLParser_SetPrimColor = (pc) ->
@primColor = []
@primColor.push (@getSetPrimColorR(pc))/255;
@primColor.push (@getSetPrimColorG(pc))/255;
@primColor.push (@getSetPrimColorB(pc))/255;
@primColor.push @getSetPrimColorA(pc)/255;
#alert @primColor
#@videoLog "TODO: DLParser_SetPrimColor"
return
C1964jsVideoHLE::DLParser_SetEnvColor = (pc) ->
@envColor = []
@envColor.push (@getSetEnvColorR(pc))/255.0;
@envColor.push (@getSetEnvColorG(pc))/255.0;
@envColor.push (@getSetEnvColorB(pc))/255.0;
@envColor.push @getSetEnvColorA(pc)/255.0;
#@videoLog "TODO: DLParser_SetEnvColor"
return
C1964jsVideoHLE::DLParser_SetZImg = (pc) ->
#@videoLog "TODO: DLParser_SetZImg"
return
C1964jsVideoHLE::prepareTriangle = (dwV0, dwV1, dwV2) ->
#SP_Timing(SP_Each_Triangle);
didSucceed = undefined #(CRender::g_pRender->IsTextureEnabled() || this.gRSP.ucode == 6 );
textureFlag = false
didSucceed = @initVertex(dwV0, @gRSP.numVertices, textureFlag)
didSucceed = @initVertex(dwV1, @gRSP.numVertices + 1, textureFlag) if didSucceed
didSucceed = @initVertex(dwV2, @gRSP.numVertices + 2, textureFlag) if didSucceed
@gRSP.numVertices += 3 if didSucceed
didSucceed
C1964jsVideoHLE::initVertex = (dwV, vtxIndex, bTexture) ->
#console.log "Vertex Index: "+vtxIndex+" dwV:"+dwV
return false if dwV >= consts.MAX_VERTS
offset = 3 * (@triangleVertexPositionBuffer.numItems)
@triVertices[offset] = @N64VertexList[dwV].x
@triVertices[offset+1] = @N64VertexList[dwV].y
@triVertices[offset+2] = @N64VertexList[dwV].z - 2.0
@triangleVertexPositionBuffer.numItems += 1
colorOffset = @triangleVertexColorBuffer.numItems << 2
@triColorVertices[colorOffset] = @N64VertexList[dwV].r | 128;
@triColorVertices[colorOffset + 1] = @N64VertexList[dwV].g | 128;
@triColorVertices[colorOffset + 2] = @N64VertexList[dwV].b | 128;
@triColorVertices[colorOffset + 3] = @N64VertexList[dwV].a;
@triangleVertexColorBuffer.numItems += 1
texOffset = @triangleVertexTextureCoordBuffer.numItems << 1
@triTextureCoords[texOffset] = @N64VertexList[dwV].s
@triTextureCoords[texOffset + 1] = @N64VertexList[dwV].t
@triangleVertexTextureCoordBuffer.numItems += 1
true
#TODO: Port this code for blend modes
# C1964jsVideoHLE::initBlenderMode = (blendMode1, blendMode2, cycleType) ->
#void CBlender::InitBlenderMode(void) // Set Alpha Blender mode {
# //1. Z_COMPARE -- Enable / Disable Zbuffer compare, SetRenderState( D3DRS_ZENABLE )
# // 1 - Enable ZBuffer
# // 0 - Disable ZBuffer
# //2. Z_UPDATE -- Enable / Disable Zbuffer update, SetRenderState( D3DRS_ZWRITEENABLE )
# // 1 - Enable ZBuffer writeable
# // 0 - Zbuffer not writeable
# //3. AA_EN and IM_RD -- Anti-Alias
# // AA_EN - Enable anti-aliase
# // AA_EN | IM_RD - Reduced anti-aliase
# // IM_RD - ??
# // - - Disable anti-aliase
# //4. ZMode
# // #define ZMODE_OPA 0 -- Usually used with Z_COMPARE and Z_UPDATE
# // or used without neither Z_COMPARE or Z_UPDATE
# // if used with Z_COMPARE and Z_UPDATE, then this is
# // the regular ZBuffer mode, with compare and update
# // #define ZMODE_INTER 0x400
# // #define ZMODE_XLU 0x800 -- Usually used with Z_COMPARE, but not with Z_UPDATE
# // Do only compare, no zbuffer update.
# // Not output if the z value is the same
# // #define ZMODE_DEC 0xc00 -- Usually used with Z_COMPARE, but not with Z_UPDATE
# // Do only compare, no update, but because this is
# // decal mode, so image should be updated even
# // the z value is the same as compared.
# CRender *render = CRender::g_pRender;
# // Alpha Blender Modes
# /*
#6. FORCE_BL - Alpha blending at blender stage
# 1 - Enable alpha blending at blender
# 0 - Disable alpha blending at blender
# Alpha blending at blender is usually used to render XLU surface
# if enabled, then use the blending setting of C1 and C2
#7. ALPHA_CVG_SEL - Output full alpha from the color combiner, usually not used together
# with FORCE_BL. If it is used together with FORCE_BL, then ignore this
#8. CVG_X_ALPHA - Before output the color from color combiner, mod it with alpha
#9. TEX_EDGE - Ignore this
#10.CLR_ON_CVG - Used with XLU surfaces, ignore it
#11.CVG_DST
#define CVG_DST_CLAMP 0 - Usually used with OPA surface
#define CVG_DST_WRAP 0x100 - Usually used with XLU surface or OPA line
#define CVG_DST_FULL 0x200 - ?
#define CVG_DST_SAVE 0x300 - ?
#Possible Blending Inputs:
# In - Input from color combiner
# Mem - Input from current frame buffer
# Fog - Fog generator
# BL - Blender
#Possible Blending Factors:
# A-IN - Alpha from color combiner
# A-MEM - Alpha from current frame buffer
# (1-A) -
# A-FOG - Alpha of fog color
# A-SHADE - Alpha of shade
# 1 - 1
# 0 - 0
#*/
#define BLEND_NOOP 0x0000
#define BLEND_NOOP5 0xcc48 // Fog * 0 + Mem * 1
#define BLEND_NOOP4 0xcc08 // Fog * 0 + In * 1
#define BLEND_FOG_ASHADE 0xc800
#define BLEND_FOG_3 0xc000 // Fog * AIn + In * 1-A
#define BLEND_FOG_MEM 0xc440 // Fog * AFog + Mem * 1-A
#define BLEND_FOG_APRIM 0xc400 // Fog * AFog + In * 1-A
#define BLEND_BLENDCOLOR 0x8c88
#define BLEND_BI_AFOG 0x8400 // Bl * AFog + In * 1-A
#define BLEND_BI_AIN 0x8040 // Bl * AIn + Mem * 1-A
#define BLEND_MEM 0x4c40 // Mem*0 + Mem*(1-0)?!
#define BLEND_FOG_MEM_3 0x44c0 // Mem * AFog + Fog * 1-A
#define BLEND_NOOP3 0x0c48 // In * 0 + Mem * 1
#define BLEND_PASS 0x0c08 // In * 0 + In * 1
#define BLEND_FOG_MEM_IN_MEM 0x0440 // In * AFog + Mem * 1-A
#define BLEND_FOG_MEM_FOG_MEM 0x04c0 // In * AFog + Fog * 1-A
#define BLEND_OPA 0x0044 // In * AIn + Mem * AMem
#define BLEND_XLU 0x0040
#define BLEND_MEM_ALPHA_IN 0x4044 // Mem * AIn + Mem * AMem
# uint32 blendmode_1 = uint32( gRDP.otherMode.blender & 0xcccc );
# uint32 blendmode_2 = uint32( gRDP.otherMode.blender & 0x3333 );
# uint32 cycletype = gRDP.otherMode.cycle_type;
# switch( cycletype )
# {
# case CYCLE_TYPE_FILL:
# //BlendFunc(D3DBLEND_ONE, D3DBLEND_ZERO);
# //Enable();
# Disable();
# break;
# case CYCLE_TYPE_COPY:
# //Disable();
# BlendFunc(D3DBLEND_ONE, D3DBLEND_ZERO);
# Enable();
# break;
# case CYCLE_TYPE_2:
# if( gRDP.otherMode.force_bl && gRDP.otherMode.z_cmp )
# {
# BlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
# Enable();
# break;
# }
# /*
# if( gRDP.otherMode.alpha_cvg_sel && gRDP.otherMode.cvg_x_alpha==0 )
# {
# BlendFunc(D3DBLEND_ONE, D3DBLEND_ZERO);
# Enable();
# break;
# }
# */
# switch( blendmode_1+blendmode_2 )
# {
# case BLEND_PASS+(BLEND_PASS>>2): // In * 0 + In * 1
# case BLEND_FOG_APRIM+(BLEND_PASS>>2):
# BlendFunc(D3DBLEND_ONE, D3DBLEND_ZERO);
# if( gRDP.otherMode.alpha_cvg_sel )
# {
# Enable();
# }
# else
# {
# Enable();
# }
# break;
# case BLEND_PASS+(BLEND_OPA>>2):
# // 0x0c19
# // Cycle1: In * 0 + In * 1
# // Cycle2: In * AIn + Mem * AMem
# if( gRDP.otherMode.cvg_x_alpha && gRDP.otherMode.alpha_cvg_sel )
# {
# BlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
# Enable();
# }
# else
# {
# BlendFunc(D3DBLEND_ONE, D3DBLEND_ZERO);
# Enable();
# }
# break;
# case BLEND_PASS + (BLEND_XLU>>2):
# // 0x0c18
# // Cycle1: In * 0 + In * 1
# // Cycle2: In * AIn + Mem * 1-A
# case BLEND_FOG_ASHADE + (BLEND_XLU>>2):
# //Cycle1: Fog * AShade + In * 1-A
# //Cycle2: In * AIn + Mem * 1-A
# case BLEND_FOG_APRIM + (BLEND_XLU>>2):
# //Cycle1: Fog * AFog + In * 1-A
# //Cycle2: In * AIn + Mem * 1-A
# //case BLEND_FOG_MEM_FOG_MEM + (BLEND_OPA>>2):
# //Cycle1: In * AFog + Fog * 1-A
# //Cycle2: In * AIn + Mem * AMem
# case BLEND_FOG_MEM_FOG_MEM + (BLEND_PASS>>2):
# //Cycle1: In * AFog + Fog * 1-A
# //Cycle2: In * 0 + In * 1
# case BLEND_XLU + (BLEND_XLU>>2):
# //Cycle1: Fog * AFog + In * 1-A
# //Cycle2: In * AIn + Mem * 1-A
# case BLEND_BI_AFOG + (BLEND_XLU>>2):
# //Cycle1: Bl * AFog + In * 1-A
# //Cycle2: In * AIn + Mem * 1-A
# case BLEND_XLU + (BLEND_FOG_MEM_IN_MEM>>2):
# //Cycle1: In * AIn + Mem * 1-A
# //Cycle2: In * AFog + Mem * 1-A
# case BLEND_PASS + (BLEND_FOG_MEM_IN_MEM>>2):
# //Cycle1: In * 0 + In * 1
# //Cycle2: In * AFog + Mem * 1-A
# BlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
# Enable();
# break;
# case BLEND_FOG_MEM_FOG_MEM + (BLEND_OPA>>2):
# //Cycle1: In * AFog + Fog * 1-A
# //Cycle2: In * AIn + Mem * AMem
# BlendFunc(D3DBLEND_ONE, D3DBLEND_ZERO);
# Enable();
# break;
# case BLEND_FOG_APRIM + (BLEND_OPA>>2):
# // For Golden Eye
# //Cycle1: Fog * AFog + In * 1-A
# //Cycle2: In * AIn + Mem * AMem
# case BLEND_FOG_ASHADE + (BLEND_OPA>>2):
# //Cycle1: Fog * AShade + In * 1-A
# //Cycle2: In * AIn + Mem * AMem
# case BLEND_BI_AFOG + (BLEND_OPA>>2):
# //Cycle1: Bl * AFog + In * 1-A
# //Cycle2: In * AIn + Mem * 1-AMem
# case BLEND_FOG_ASHADE + (BLEND_NOOP>>2):
# //Cycle1: Fog * AShade + In * 1-A
# //Cycle2: In * AIn + In * 1-A
# case BLEND_NOOP + (BLEND_OPA>>2):
# //Cycle1: In * AIn + In * 1-A
# //Cycle2: In * AIn + Mem * AMem
# case BLEND_NOOP4 + (BLEND_NOOP>>2):
# //Cycle1: Fog * AIn + In * 1-A
# //Cycle2: In * 0 + In * 1
# case BLEND_FOG_ASHADE+(BLEND_PASS>>2):
# //Cycle1: Fog * AShade + In * 1-A
# //Cycle2: In * 0 + In * 1
# case BLEND_FOG_3+(BLEND_PASS>>2):
# BlendFunc(D3DBLEND_ONE, D3DBLEND_ZERO);
# Enable();
# break;
# case BLEND_FOG_ASHADE+0x0301:
# // c800 - Cycle1: Fog * AShade + In * 1-A
# // 0301 - Cycle2: In * 0 + In * AMem
# BlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_ZERO);
# Enable();
# break;
# case 0x0c08+0x1111:
# // 0c08 - Cycle1: In * 0 + In * 1
# // 1111 - Cycle2: Mem * AFog + Mem * AMem
# BlendFunc(D3DBLEND_ZERO, D3DBLEND_DESTALPHA);
# Enable();
# break;
# default:
# if( blendmode_2 == (BLEND_PASS>>2) )
# {
# BlendFunc(D3DBLEND_ONE, D3DBLEND_ZERO);
# }
# else
# {
# BlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
# }
# Enable();
# break;
# }
# break;
# default: // 1/2 Cycle or Copy
# if( gRDP.otherMode.force_bl && gRDP.otherMode.z_cmp && blendmode_1 != BLEND_FOG_ASHADE )
# {
# BlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
# Enable();
# break;
# }
# if( gRDP.otherMode.force_bl && options.enableHackForGames == HACK_FOR_COMMANDCONQUER )
# {
# BlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
# Enable();
# break;
# }
# switch ( blendmode_1 )
# //switch ( blendmode_2<<2 )
# {
# case BLEND_XLU: // IN * A_IN + MEM * (1-A_IN)
# case BLEND_BI_AIN: // Bl * AIn + Mem * 1-A
# case BLEND_FOG_MEM: // c440 - Cycle1: Fog * AFog + Mem * 1-A
# case BLEND_FOG_MEM_IN_MEM: // c440 - Cycle1: In * AFog + Mem * 1-A
# case BLEND_BLENDCOLOR: //Bl * 0 + Bl * 1
# case 0x00c0: //In * AIn + Fog * 1-A
# BlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
# Enable();
# break;
# case BLEND_MEM_ALPHA_IN: // Mem * AIn + Mem * AMem
# BlendFunc(D3DBLEND_ZERO, D3DBLEND_DESTALPHA);
# Enable();
# break;
# case BLEND_PASS: // IN * 0 + IN * 1
# BlendFunc(D3DBLEND_ONE, D3DBLEND_ZERO);
# if( gRDP.otherMode.alpha_cvg_sel )
# {
# Enable();
# }
# else
# {
# Disable();
# }
# break;
# case BLEND_OPA: // IN * A_IN + MEM * A_MEM
# if( options.enableHackForGames == HACK_FOR_MARIO_TENNIS )
# {
# BlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
# }
# else
# {
# BlendFunc(D3DBLEND_ONE, D3DBLEND_ZERO);
# }
# Enable();
# break;
# case BLEND_NOOP: // IN * A_IN + IN * (1 - A_IN)
# case BLEND_FOG_ASHADE: // Fog * AShade + In * 1-A
# case BLEND_FOG_MEM_3: // Mem * AFog + Fog * 1-A
# case BLEND_BI_AFOG: // Bl * AFog + In * 1-A
# BlendFunc(D3DBLEND_ONE, D3DBLEND_ZERO);
# Enable();
# break;
# case BLEND_FOG_APRIM: // Fog * AFog + In * 1-A
# BlendFunc(D3DBLEND_INVSRCALPHA, D3DBLEND_ZERO);
# Enable();
# break;
# case BLEND_NOOP3: // In * 0 + Mem * 1
# case BLEND_NOOP5: // Fog * 0 + Mem * 1
# BlendFunc(D3DBLEND_ZERO, D3DBLEND_ONE);
# Enable();
# break;
# case BLEND_MEM: // Mem * 0 + Mem * 1-A
# // WaveRace
# BlendFunc(D3DBLEND_ZERO, D3DBLEND_ONE);
# Enable();
# break;
# default:
# BlendFunc(D3DBLEND_SRCALPHA, D3DBLEND_INVSRCALPHA);
# Enable();
# render->SetAlphaTestEnable(TRUE);
# break;
# }
# }
# return
C1964jsVideoHLE::drawScene = (useTexture, tileno) ->
@gl.useProgram @core.webGL.shaderProgram
@gl.enable @gl.DEPTH_TEST
@gl.depthFunc(@gl.LEQUAL);
@gl.enable @gl.BLEND
#@gl.blendFunc @gl.SRC_ALPHA, @gl.ONE_MINUS_SRC_ALPHA
if @triangleVertexPositionBuffer.numItems > 0
@gl.bindBuffer @gl.ARRAY_BUFFER, @triangleVertexPositionBuffer
@gl.bufferData @gl.ARRAY_BUFFER, @triVertices.subarray(0, @triangleVertexPositionBuffer.numItems*@triangleVertexPositionBuffer.itemSize*4), @gl.STATIC_DRAW
@gl.enableVertexAttribArray @core.webGL.shaderProgram.vertexPositionAttribute
@gl.vertexAttribPointer @core.webGL.shaderProgram.vertexPositionAttribute, @triangleVertexPositionBuffer.itemSize, @gl.FLOAT, false, 0, 0
if @triangleVertexColorBuffer.numItems > 0
@gl.bindBuffer @gl.ARRAY_BUFFER, @triangleVertexColorBuffer
@gl.bufferData @gl.ARRAY_BUFFER, @triColorVertices.subarray(0, @triangleVertexColorBuffer.numItems*@triangleVertexColorBuffer.itemSize), @gl.STATIC_DRAW
@gl.enableVertexAttribArray @core.webGL.shaderProgram.vertexColorAttribute
@gl.vertexAttribPointer @core.webGL.shaderProgram.vertexColorAttribute, @triangleVertexColorBuffer.itemSize, @gl.UNSIGNED_BYTE, true, 0, 0
if @triangleVertexTextureCoordBuffer.numItems > 0
@gl.bindBuffer @gl.ARRAY_BUFFER, @triangleVertexTextureCoordBuffer
@gl.bufferData @gl.ARRAY_BUFFER, @triTextureCoords.subarray(0, @triangleVertexTextureCoordBuffer.numItems*@triangleVertexTextureCoordBuffer.itemSize*4), @gl.STATIC_DRAW
@gl.enableVertexAttribArray @core.webGL.shaderProgram.textureCoordAttribute
@gl.vertexAttribPointer @core.webGL.shaderProgram.textureCoordAttribute, @triangleVertexTextureCoordBuffer.itemSize, @gl.FLOAT, false, 0, 0
tile = @textureTile[@activeTile]
canvaswidth = @pow2roundup tile.width
canvasheight = @pow2roundup tile.height
texture = @renderer.formatTexture(tile, @tmem, canvaswidth, canvasheight)
colorsTexture = @gl.createTexture()
@gl.activeTexture(@gl.TEXTURE0)
@gl.bindTexture(@gl.TEXTURE_2D, colorsTexture)
@gl.texImage2D( @gl.TEXTURE_2D, 0, @gl.RGBA, tile.width, tile.height, 0, @gl.RGBA, @gl.UNSIGNED_BYTE, texture)
@gl.texParameteri(@gl.TEXTURE_2D, @gl.TEXTURE_MAG_FILTER, @gl.LINEAR)
@gl.texParameteri(@gl.TEXTURE_2D, @gl.TEXTURE_MIN_FILTER, @gl.NEAREST)
@gl.uniform1i @core.webGL.shaderProgram.samplerUniform, colorsTexture
if @primColor.length > 0
@gl.uniform4fv @core.webGL.shaderProgram.uPrimColor, @primColor
if @fillColor.length > 0
@gl.uniform4fv @core.webGL.shaderProgram.uFillColor, @fillColor
if @envColor.length > 0
@gl.uniform4fv @core.webGL.shaderProgram.uEnvColor, @envColor
if @blendColor.length > 0
@gl.uniform4iv @core.webGL.shaderProgram.uBlendColor, @blendColor
@gl.uniform1i @core.webGL.shaderProgram.otherModeL, @otherModeL
@gl.uniform1i @core.webGL.shaderProgram.otherModeH, @otherModeH
@core.webGL.setCombineUniforms @core.webGL.shaderProgram
@gl.uniform1i @core.webGL.shaderProgram.wireframeUniform, if @core.settings.wireframe then 1 else 0
# Matrix Uniforms
@gl.uniformMatrix4fv(@core.webGL.shaderProgram.pMatrixUniform, false, @gRSP.projectionMtxs[@gRSP.projectionMtxTop]);
@gl.uniformMatrix4fv(@core.webGL.shaderProgram.mvMatrixUniform, false, @gRSP.modelviewMtxs[@gRSP.modelViewMtxTop]);
if @triangleVertexPositionBuffer.numItems > 0
if @core.settings.wireframe is true
@gl.drawArrays @gl.LINES, 0, @triangleVertexPositionBuffer.numItems
else
@gl.drawArrays @gl.TRIANGLES, 0, @triangleVertexPositionBuffer.numItems
@resetState()
return
C1964jsVideoHLE::resetState = ->
@triangleVertexPositionBuffer.numItems = 0
@triangleVertexColorBuffer.numItems = 0
@triangleVertexTextureCoordBuffer.numItems = 0
return
C1964jsVideoHLE::initBuffers = ->
@triangleVertexPositionBuffer = @gl.createBuffer()
@gl.bindBuffer @gl.ARRAY_BUFFER, @triangleVertexPositionBuffer
@triangleVertexPositionBuffer.itemSize = 3
@triangleVertexPositionBuffer.numItems = 0
@triangleVertexColorBuffer = @gl.createBuffer()
@gl.bindBuffer @gl.ARRAY_BUFFER, @triangleVertexColorBuffer
@triangleVertexColorBuffer.itemSize = 4
@triangleVertexColorBuffer.numItems = 0
@triangleVertexTextureCoordBuffer = @gl.createBuffer()
@gl.bindBuffer @gl.ARRAY_BUFFER, @triangleVertexTextureCoordBuffer
@triangleVertexTextureCoordBuffer.itemSize = 2
@triangleVertexTextureCoordBuffer.numItems = 0
return
)()
#hack global space until we export classes properly
#node.js uses exports; browser uses this (window)
root = exports ? this
root.C1964jsVideoHLE = C1964jsVideoHLE