X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=inline;f=source%2Fgles2n64%2Fsrc%2FgDP.cpp;fp=source%2Fgles2n64%2Fsrc%2FgDP.cpp;h=afe65ff29a4588a2a55d0717c4b52143266237f7;hb=34cf40586ac07c54d9bfc5be30f28743232b6d67;hp=0000000000000000000000000000000000000000;hpb=22726e4d55be26faa48b57b22689cbedde27ae44;p=mupen64plus-pandora.git diff --git a/source/gles2n64/src/gDP.cpp b/source/gles2n64/src/gDP.cpp new file mode 100644 index 0000000..afe65ff --- /dev/null +++ b/source/gles2n64/src/gDP.cpp @@ -0,0 +1,970 @@ +#include + +#include "gles2N64.h" +#include "N64.h" +#include "GBI.h" +#include "RSP.h" +#include "gDP.h" +#include "gSP.h" +#include "Types.h" +#include "Debug.h" +#include "convert.h" +#include "OpenGL.h" +#include "CRC.h" +#include "DepthBuffer.h" +#include "VI.h" +#include "Config.h" + + +//thank rice_video for this: +bool _IsRenderTexture() +{ + bool foundSetScissor=false; + bool foundFillRect=false; + bool foundSetFillColor=false; + bool foundSetCImg=false; + bool foundTxtRect=false; + int height; + unsigned int newFillColor = 0; + unsigned int dwPC = RSP.PC[RSP.PCi]; // This points to the next instruction + + for(int i=0; i<10; i++ ) + { + unsigned int w0 = *(unsigned int *)(RDRAM + dwPC + i*8); + unsigned int w1 = *(unsigned int *)(RDRAM + dwPC + 4 + i*8); + + if ((w0>>24) == G_SETSCISSOR) + { + height = ((w1>>0 )&0xFFF)/4; + foundSetScissor = true; + continue; + } + + if ((w0>>24) == G_SETFILLCOLOR) + { + height = ((w1>>0 )&0xFFF)/4; + foundSetFillColor = true; + newFillColor = w1; + continue; + } + + if ((w0>>24) == G_FILLRECT) + { + unsigned int x0 = ((w1>>12)&0xFFF)/4; + unsigned int y0 = ((w1>>0 )&0xFFF)/4; + unsigned int x1 = ((w0>>12)&0xFFF)/4; + unsigned int y1 = ((w0>>0 )&0xFFF)/4; + + if (x0 == 0 && y0 == 0) + { + if( x1 == gDP.colorImage.width) + { + height = y1; + foundFillRect = true; + continue; + } + + if(x1 == (unsigned int)(gDP.colorImage.width-1)) + { + height = y1+1; + foundFillRect = true; + continue; + } + } + } + + if ((w0>>24) == G_TEXRECT) + { + foundTxtRect = true; + break; + } + + if ((w0>>24) == G_SETCIMG) + { + foundSetCImg = true; + break; + } + } + + if (foundFillRect ) + { + if (foundSetFillColor) + { + if (newFillColor != 0xFFFCFFFC) + return true; // this is a render_texture + else + return false; + } + + if (gDP.fillColor.i == 0x00FFFFF7) + return true; // this is a render_texture + else + return false; // this is a normal ZImg + } + else if (foundSetFillColor && newFillColor == 0xFFFCFFFC && foundSetCImg ) + { + return false; + } + else + return true; + + + if (!foundSetCImg) return true; + + if (foundSetScissor ) return true; + + return false; +} + +gDPInfo gDP; + +void gDPSetOtherMode( u32 mode0, u32 mode1 ) +{ + gDP.otherMode.h = mode0; + gDP.otherMode.l = mode1; + gDP.changed |= CHANGED_RENDERMODE | CHANGED_CYCLETYPE | CHANGED_ALPHACOMPARE; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetOtherMode( %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s, %s | %s | %s%s%s%s%s | %s | %s%s%s );\n", + AlphaDitherText[gDP.otherMode.alphaDither], + ColorDitherText[gDP.otherMode.colorDither], + CombineKeyText[gDP.otherMode.combineKey], + TextureConvertText[gDP.otherMode.textureConvert], + TextureFilterText[gDP.otherMode.textureFilter], + TextureLUTText[gDP.otherMode.textureLUT], + TextureLODText[gDP.otherMode.textureLOD], + TextureDetailText[gDP.otherMode.textureDetail], + TexturePerspText[gDP.otherMode.texturePersp], + CycleTypeText[gDP.otherMode.cycleType], + PipelineModeText[gDP.otherMode.pipelineMode], + AlphaCompareText[gDP.otherMode.alphaCompare], + DepthSourceText[gDP.otherMode.depthSource], + gDP.otherMode.AAEnable ? "AA_EN | " : "", + gDP.otherMode.depthCompare ? "Z_CMP | " : "", + gDP.otherMode.depthUpdate ? "Z_UPD | " : "", + gDP.otherMode.imageRead ? "IM_RD | " : "", + CvgDestText[gDP.otherMode.cvgDest], + DepthModeText[gDP.otherMode.depthMode], + gDP.otherMode.cvgXAlpha ? "CVG_X_ALPHA | " : "", + gDP.otherMode.alphaCvgSel ? "ALPHA_CVG_SEL | " : "", + gDP.otherMode.forceBlender ? "FORCE_BL" : "" ); +#endif +} + +void gDPSetPrimDepth( u16 z, u16 dz ) +{ + z = z&0x7FFF; + + //gDP.primDepth.z = (_FIXED2FLOAT( z, 15 ) - gSP.viewport.vtrans[2]) / gSP.viewport.vscale[2] ; + gDP.primDepth.z = (z - gSP.viewport.vtrans[2]) / gSP.viewport.vscale[2] ; + gDP.primDepth.deltaZ = dz; + gDP.changed |= CHANGED_PRIMITIVEZ; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetPrimDepth( %f, %f );\n", + gDP.primDepth.z, + gDP.primDepth.deltaZ); +#endif +} + +void gDPPipelineMode( u32 mode ) +{ + gDP.otherMode.pipelineMode = mode; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPPipelineMode( %s );\n", + PipelineModeText[gDP.otherMode.pipelineMode] ); +#endif +} + +void gDPSetCycleType( u32 type ) +{ + gDP.otherMode.cycleType = type; + gDP.changed |= CHANGED_CYCLETYPE; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetCycleType( %s );\n", + CycleTypeText[gDP.otherMode.cycleType] ); +#endif +} + +void gDPSetTexturePersp( u32 enable ) +{ + gDP.otherMode.texturePersp = enable; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTexturePersp( %s );\n", + TexturePerspText[gDP.otherMode.texturePersp] ); +#endif +} + +void gDPSetTextureDetail( u32 type ) +{ + gDP.otherMode.textureDetail = type; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTextureDetail( %s );\n", + TextureDetailText[gDP.otherMode.textureDetail] ); +#endif +} + +void gDPSetTextureLOD( u32 mode ) +{ + gDP.otherMode.textureLOD = mode; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTextureLOD( %s );\n", + TextureLODText[gDP.otherMode.textureLOD] ); +#endif +} + +void gDPSetTextureLUT( u32 mode ) +{ + gDP.otherMode.textureLUT = mode; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTextureLUT( %s );\n", + TextureLUTText[gDP.otherMode.textureLUT] ); +#endif +} + +void gDPSetTextureFilter( u32 type ) +{ + gDP.otherMode.textureFilter = type; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTextureFilter( %s );\n", + TextureFilterText[gDP.otherMode.textureFilter] ); +#endif +} + +void gDPSetTextureConvert( u32 type ) +{ + gDP.otherMode.textureConvert = type; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTextureConvert( %s );\n", + TextureConvertText[gDP.otherMode.textureConvert] ); +#endif +} + +void gDPSetCombineKey( u32 type ) +{ + gDP.otherMode.combineKey = type; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_COMBINE, "gDPSetCombineKey( %s );\n", + CombineKeyText[gDP.otherMode.combineKey] ); +#endif +} + +void gDPSetColorDither( u32 type ) +{ + gDP.otherMode.colorDither = type; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetColorDither( %s );\n", + ColorDitherText[gDP.otherMode.colorDither] ); +#endif +} + +void gDPSetAlphaDither( u32 type ) +{ + gDP.otherMode.alphaDither = type; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetAlphaDither( %s );\n", + AlphaDitherText[gDP.otherMode.alphaDither] ); +#endif +} + +void gDPSetAlphaCompare( u32 mode ) +{ + gDP.otherMode.alphaCompare = mode; + gDP.changed |= CHANGED_ALPHACOMPARE; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetAlphaCompare( %s );\n", + AlphaCompareText[gDP.otherMode.alphaCompare] ); +#endif +} + +void gDPSetDepthSource( u32 source ) +{ + gDP.otherMode.depthSource = source; + gDP.changed |= CHANGED_DEPTHSOURCE; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetDepthSource( %s );\n", + DepthSourceText[gDP.otherMode.depthSource] ); +#endif +} + +void gDPSetRenderMode( u32 mode1, u32 mode2 ) +{ + gDP.otherMode.l &= 0x00000007; + gDP.otherMode.l |= mode1 | mode2; + gDP.changed |= CHANGED_RENDERMODE; + +#ifdef DEBUG + // THIS IS INCOMPLETE!!! + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetRenderMode( %s%s%s%s%s | %s | %s%s%s );\n", + gDP.otherMode.AAEnable ? "AA_EN | " : "", + gDP.otherMode.depthCompare ? "Z_CMP | " : "", + gDP.otherMode.depthUpdate ? "Z_UPD | " : "", + gDP.otherMode.imageRead ? "IM_RD | " : "", + CvgDestText[gDP.otherMode.cvgDest], + DepthModeText[gDP.otherMode.depthMode], + gDP.otherMode.cvgXAlpha ? "CVG_X_ALPHA | " : "", + gDP.otherMode.alphaCvgSel ? "ALPHA_CVG_SEL | " : "", + gDP.otherMode.forceBlender ? "FORCE_BL" : "" ); +#endif +} + +void gDPSetCombine( s32 muxs0, s32 muxs1 ) +{ + gDP.combine.muxs0 = muxs0; + gDP.combine.muxs1 = muxs1; + gDP.changed |= CHANGED_COMBINE; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_COMBINE, "gDPSetCombine( %s, %s, %s, %s, %s, %s, %s, %s,\n", + saRGBText[gDP.combine.saRGB0], + sbRGBText[gDP.combine.sbRGB0], + mRGBText[gDP.combine.mRGB0], + aRGBText[gDP.combine.aRGB0], + saAText[gDP.combine.saA0], + sbAText[gDP.combine.sbA0], + mAText[gDP.combine.mA0], + aAText[gDP.combine.aA0] ); + + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_COMBINE, " %s, %s, %s, %s, %s, %s, %s, %s );\n", + saRGBText[gDP.combine.saRGB1], + sbRGBText[gDP.combine.sbRGB1], + mRGBText[gDP.combine.mRGB1], + aRGBText[gDP.combine.aRGB1], + saAText[gDP.combine.saA1], + sbAText[gDP.combine.sbA1], + mAText[gDP.combine.mA1], + aAText[gDP.combine.aA1] ); + +#endif +} + +void gDPSetColorImage( u32 format, u32 size, u32 width, u32 address ) +{ + if (config.updateMode == SCREEN_UPDATE_AT_CI_CHANGE) + OGL_SwapBuffers(); + + if (config.updateMode == SCREEN_UPDATE_AT_1ST_CI_CHANGE && OGL.screenUpdate) + OGL_SwapBuffers(); + + u32 addr = RSP_SegmentToPhysical( address ); + + if (gDP.colorImage.address != addr) + { + gDP.colorImage.changed = FALSE; + if (width == VI.width) + gDP.colorImage.height = VI.height; + else + gDP.colorImage.height = 1; + } + + gDP.colorImage.format = format; + gDP.colorImage.size = size; + gDP.colorImage.width = width; + gDP.colorImage.address = addr; + + if (config.ignoreOffscreenRendering) + { + int i; + + //colorimage byte size: + //color image height is not the best thing to base this on, its normally set + //later on in the code + + if (gDP.colorImage.address == gDP.depthImageAddress) + { + OGL.renderingToTexture = false; + } + else if (size == G_IM_SIZ_16b && format == G_IM_FMT_RGBA) + { + int s = 0; + switch(size) + { + case G_IM_SIZ_4b: s = (gDP.colorImage.width * gDP.colorImage.height) / 2; break; + case G_IM_SIZ_8b: s = (gDP.colorImage.width * gDP.colorImage.height); break; + case G_IM_SIZ_16b: s = (gDP.colorImage.width * gDP.colorImage.height) * 2; break; + case G_IM_SIZ_32b: s = (gDP.colorImage.width * gDP.colorImage.height) * 4; break; + } + u32 start = addr & 0x00FFFFFF; + u32 end = min(start + s, RDRAMSize); + for(i = 0; i < VI.displayNum; i++) + { + if (VI.display[i].start <= end && VI.display[i].start >= start) break; + if (start <= VI.display[i].end && start >= VI.display[i].start) break; + } + + OGL.renderingToTexture = (i == VI.displayNum); + } + else + { + OGL.renderingToTexture = true; + } + +#if 0 + if (OGL.renderingToTexture) + { + printf("start=%i end=%i\n", start, end); + printf("display="); + for(int i=0; i< VI.displayNum; i++) printf("%i,%i:", VI.display[i].start, VI.display[i].end); + printf("\n"); + } +#endif + } + else + { + OGL.renderingToTexture = false; + } + + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetColorImage( %s, %s, %i, 0x%08X );\n", + ImageFormatText[gDP.colorImage.format], + ImageSizeText[gDP.colorImage.size], + gDP.colorImage.width, + gDP.colorImage.address ); +#endif +} + +void gDPSetTextureImage( u32 format, u32 size, u32 width, u32 address ) +{ + gDP.textureImage.format = format; + gDP.textureImage.size = size; + gDP.textureImage.width = width; + gDP.textureImage.address = RSP_SegmentToPhysical( address ); + gDP.textureImage.bpl = gDP.textureImage.width << gDP.textureImage.size >> 1; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTextureImage( %s, %s, %i, 0x%08X );\n", + ImageFormatText[gDP.textureImage.format], + ImageSizeText[gDP.textureImage.size], + gDP.textureImage.width, + gDP.textureImage.address ); +#endif +} + +void gDPSetDepthImage( u32 address ) +{ +// if (address != gDP.depthImageAddress) +// OGL_ClearDepthBuffer(); + + u32 addr = RSP_SegmentToPhysical(address); + DepthBuffer_SetBuffer(addr); + + if (depthBuffer.current->cleared) + OGL_ClearDepthBuffer(); + + gDP.depthImageAddress = addr; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetDepthImage( 0x%08X );\n", gDP.depthImageAddress ); +#endif +} + +void gDPSetEnvColor( u32 r, u32 g, u32 b, u32 a ) +{ + gDP.envColor.r = r * 0.0039215689f; + gDP.envColor.g = g * 0.0039215689f; + gDP.envColor.b = b * 0.0039215689f; + gDP.envColor.a = a * 0.0039215689f; + + gDP.changed |= CHANGED_ENV_COLOR; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_COMBINE, "gDPSetEnvColor( %u, %u, %u, %u );\n", + r, g, b, a ); +#endif +} + +void gDPSetBlendColor( u32 r, u32 g, u32 b, u32 a ) +{ + gDP.blendColor.r = r * 0.0039215689f; + gDP.blendColor.g = g * 0.0039215689f; + gDP.blendColor.b = b * 0.0039215689f; + gDP.blendColor.a = a * 0.0039215689f; + gDP.changed |= CHANGED_BLENDCOLOR; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetBlendColor( %u, %u, %u, %u );\n", + r, g, b, a ); +#endif +} + +void gDPSetFogColor( u32 r, u32 g, u32 b, u32 a ) +{ + gDP.fogColor.r = r * 0.0039215689f; + gDP.fogColor.g = g * 0.0039215689f; + gDP.fogColor.b = b * 0.0039215689f; + gDP.fogColor.a = a * 0.0039215689f; + + gDP.changed |= CHANGED_FOGCOLOR; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetFogColor( %u, %u, %u, %u );\n", + r, g, b, a ); +#endif +} + +void gDPSetFillColor( u32 c ) +{ + + gDP.fillColor.i = c; + gDP.fillColor.r = _SHIFTR( c, 11, 5 ) * 0.032258064f; + gDP.fillColor.g = _SHIFTR( c, 6, 5 ) * 0.032258064f; + gDP.fillColor.b = _SHIFTR( c, 1, 5 ) * 0.032258064f; + gDP.fillColor.a = _SHIFTR( c, 0, 1 ); + + gDP.fillColor.z = _SHIFTR( c, 2, 14 ); + gDP.fillColor.dz = _SHIFTR( c, 0, 2 ); + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetFillColor( 0x%08X );\n", c ); +#endif +} + +void gDPSetPrimColor( u32 m, u32 l, u32 r, u32 g, u32 b, u32 a ) +{ + gDP.primColor.m = m; + gDP.primColor.l = l * 0.0039215689f; + gDP.primColor.r = r * 0.0039215689f; + gDP.primColor.g = g * 0.0039215689f; + gDP.primColor.b = b * 0.0039215689f; + gDP.primColor.a = a * 0.0039215689f; + + gDP.changed |= CHANGED_PRIM_COLOR; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_COMBINE, "gDPSetPrimColor( %u, %u, %u, %u, %u, %u );\n", + m, l, r, g, b, a ); +#endif +} + +void gDPSetTile( u32 format, u32 size, u32 line, u32 tmem, u32 tile, u32 palette, u32 cmt, u32 cms, u32 maskt, u32 masks, u32 shiftt, u32 shifts ) +{ + if (((size == G_IM_SIZ_4b) || (size == G_IM_SIZ_8b)) && (format == G_IM_FMT_RGBA)) + format = G_IM_FMT_CI; + + gDP.tiles[tile].format = format; + gDP.tiles[tile].size = size; + gDP.tiles[tile].line = line; + gDP.tiles[tile].tmem = tmem; + gDP.tiles[tile].palette = palette; + gDP.tiles[tile].cmt = cmt; + gDP.tiles[tile].cms = cms; + gDP.tiles[tile].maskt = maskt; + gDP.tiles[tile].masks = masks; + gDP.tiles[tile].shiftt = shiftt; + gDP.tiles[tile].shifts = shifts; + + if (!gDP.tiles[tile].masks) gDP.tiles[tile].clamps = 1; + if (!gDP.tiles[tile].maskt) gDP.tiles[tile].clampt = 1; +} + +void gDPSetTileSize( u32 tile, u32 uls, u32 ult, u32 lrs, u32 lrt ) +{ + gDP.tiles[tile].uls = _SHIFTR( uls, 2, 10 ); + gDP.tiles[tile].ult = _SHIFTR( ult, 2, 10 ); + gDP.tiles[tile].lrs = _SHIFTR( lrs, 2, 10 ); + gDP.tiles[tile].lrt = _SHIFTR( lrt, 2, 10 ); + + gDP.tiles[tile].fuls = _FIXED2FLOAT( uls, 2 ); + gDP.tiles[tile].fult = _FIXED2FLOAT( ult, 2 ); + gDP.tiles[tile].flrs = _FIXED2FLOAT( lrs, 2 ); + gDP.tiles[tile].flrt = _FIXED2FLOAT( lrt, 2 ); + + gDP.changed |= CHANGED_TILE; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPSetTileSize( %u, %.2f, %.2f, %.2f, %.2f );\n", + tile, + gDP.tiles[tile].fuls, + gDP.tiles[tile].fult, + gDP.tiles[tile].flrs, + gDP.tiles[tile].flrt ); +#endif +} + +void gDPLoadTile( u32 tile, u32 uls, u32 ult, u32 lrs, u32 lrt ) +{ + void (*Interleave)( void *mem, u32 numDWords ); + + u32 address, height, bpl, line, y; + u64 *dest; + u8 *src; + + gDPSetTileSize( tile, uls, ult, lrs, lrt ); + gDP.loadTile = &gDP.tiles[tile]; + + if (gDP.loadTile->line == 0) + return; + + address = gDP.textureImage.address + gDP.loadTile->ult * gDP.textureImage.bpl + (gDP.loadTile->uls << gDP.textureImage.size >> 1); + dest = &TMEM[gDP.loadTile->tmem]; + bpl = (gDP.loadTile->lrs - gDP.loadTile->uls + 1) << gDP.loadTile->size >> 1; + height = gDP.loadTile->lrt - gDP.loadTile->ult + 1; + src = &RDRAM[address]; + + if (((address + height * bpl) > RDRAMSize) || + (((gDP.loadTile->tmem << 3) + bpl * height) > 4096)) // Stay within TMEM + { +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_ERROR | DEBUG_TEXTURE, "// Attempting to load texture tile out of range\n" ); + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPLoadTile( %u, %i, %i, %i, %i );\n", + tile, gDP.loadTile->uls, gDP.loadTile->ult, gDP.loadTile->lrs, gDP.loadTile->lrt ); +#endif + return; + } + + // Line given for 32-bit is half what it seems it should since they split the + // high and low words. I'm cheating by putting them together. + if (gDP.loadTile->size == G_IM_SIZ_32b) + { + line = gDP.loadTile->line << 1; + Interleave = QWordInterleave; + } + else + { + line = gDP.loadTile->line; + Interleave = DWordInterleave; + } + + for (y = 0; y < height; y++) + { + UnswapCopy( src, dest, bpl ); + if (y & 1) Interleave( dest, line ); + + src += gDP.textureImage.bpl; + dest += line; + } + + gDP.textureMode = TEXTUREMODE_NORMAL; + gDP.loadType = LOADTYPE_TILE; + gDP.changed |= CHANGED_TMEM; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPLoadTile( %u, %i, %i, %i, %i );\n", + tile, gDP.loadTile->uls, gDP.loadTile->ult, gDP.loadTile->lrs, gDP.loadTile->lrt ); +#endif +} + +void gDPLoadBlock( u32 tile, u32 uls, u32 ult, u32 lrs, u32 dxt ) +{ + gDPSetTileSize( tile, uls, ult, lrs, dxt ); + gDP.loadTile = &gDP.tiles[tile]; + + u32 bytes = (lrs + 1) << gDP.loadTile->size >> 1; + u32 address = gDP.textureImage.address + ult * gDP.textureImage.bpl + (uls << gDP.textureImage.size >> 1); + + if ((bytes == 0) || + ((address + bytes) > RDRAMSize) || + (((gDP.loadTile->tmem << 3) + bytes) > 4096)) + { +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_ERROR | DEBUG_TEXTURE, "// Attempting to load texture block out of range\n" ); + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPLoadBlock( %u, %u, %u, %u, %u );\n", + tile, uls, ult, lrs, dxt ); +#endif +// bytes = min( bytes, min( RDRAMSize - gDP.textureImage.address, 4096 - (gDP.loadTile->tmem << 3) ) ); + return; + } + + u64* src = (u64*)&RDRAM[address]; + u64* dest = &TMEM[gDP.loadTile->tmem]; + + if (dxt > 0) + { + u32 line = (2047 + dxt) / dxt; + u32 bpl = line << 3; + u32 height = bytes / bpl; + + if (gDP.loadTile->size == G_IM_SIZ_32b) + { + for (u32 y = 0; y < height; y++) + { + UnswapCopy( src, dest, bpl ); + if (y & 1) QWordInterleave( dest, line ); + src += line; + dest += line; + } + } + else + { + for (u32 y = 0; y < height; y++) + { + UnswapCopy( src, dest, bpl ); + if (y & 1) DWordInterleave( dest, line ); + src += line; + dest += line; + } + + } + + } + else + UnswapCopy( src, dest, bytes ); + + gDP.textureMode = TEXTUREMODE_NORMAL; + gDP.loadType = LOADTYPE_BLOCK; + gDP.changed |= CHANGED_TMEM; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPLoadBlock( %u, %u, %u, %u, %u );\n", + tile, uls, ult, lrs, dxt ); +#endif +} + +void gDPLoadTLUT( u32 tile, u32 uls, u32 ult, u32 lrs, u32 lrt ) +{ + gDPSetTileSize( tile, uls, ult, lrs, lrt ); + + u16 count = (gDP.tiles[tile].lrs - gDP.tiles[tile].uls + 1) * (gDP.tiles[tile].lrt - gDP.tiles[tile].ult + 1); + u32 address = gDP.textureImage.address + gDP.tiles[tile].ult * gDP.textureImage.bpl + (gDP.tiles[tile].uls << gDP.textureImage.size >> 1); + + u16 *dest = (u16*)&TMEM[gDP.tiles[tile].tmem]; + u16 *src = (u16*)&RDRAM[address]; + + u16 pal = (gDP.tiles[tile].tmem - 256) >> 4; + + int i = 0; + while (i < count) + { + for (u16 j = 0; (j < 16) && (i < count); j++, i++) + { + u16 color = swapword( src[i^1] ); + + *dest = color; + //dest[1] = color; + //dest[2] = color; + //dest[3] = color; + + dest += 4; + } + + gDP.paletteCRC16[pal] = CRC_CalculatePalette( 0xFFFFFFFF, &TMEM[256 + (pal << 4)], 16 ); + pal++; + } + + gDP.paletteCRC256 = CRC_Calculate( 0xFFFFFFFF, gDP.paletteCRC16, 64 ); + + gDP.changed |= CHANGED_TMEM; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED | DEBUG_TEXTURE, "gDPLoadTLUT( %u, %i, %i, %i, %i );\n", + tile, gDP.tiles[tile].uls, gDP.tiles[tile].ult, gDP.tiles[tile].lrs, gDP.tiles[tile].lrt ); +#endif +} + +void gDPSetScissor( u32 mode, f32 ulx, f32 uly, f32 lrx, f32 lry ) +{ + gDP.scissor.mode = mode; + gDP.scissor.ulx = ulx; + gDP.scissor.uly = uly; + gDP.scissor.lrx = lrx; + gDP.scissor.lry = lry; + gDP.changed |= CHANGED_SCISSOR; + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_IGNORED, "gDPSetScissor( %s, %.2f, %.2f, %.2f, %.2f );\n", + ScissorModeText[gDP.scissor.mode], + gDP.scissor.ulx, + gDP.scissor.uly, + gDP.scissor.lrx, + gDP.scissor.lry ); +#endif +} + +void gDPFillRectangle( s32 ulx, s32 uly, s32 lrx, s32 lry ) +{ + DepthBuffer *buffer = DepthBuffer_FindBuffer( gDP.colorImage.address ); + + if (buffer) + buffer->cleared = TRUE; + + if (gDP.depthImageAddress == gDP.colorImage.address) + { + OGL_ClearDepthBuffer(); + return; + } + + if (gDP.otherMode.cycleType == G_CYC_FILL) + { + lrx++; + lry++; + + if ((ulx == 0) && (uly == 0) && ((unsigned int)lrx == VI.width) && ((unsigned int)lry == VI.height)) + { + OGL_ClearColorBuffer( &gDP.fillColor.r ); + return; + } + } + + //shouldn't this be primitive color? + //OGL_DrawRect( ulx, uly, lrx, lry, (gDP.otherMode.cycleType == G_CYC_FILL) ? &gDP.fillColor.r : &gDP.blendColor.r ); + //OGL_DrawRect( ulx, uly, lrx, lry, (gDP.otherMode.cycleType == G_CYC_FILL) ? &gDP.fillColor.r : &gDP.primColor.r); + + float black[] = {0,0,0,0}; + OGL_DrawRect( ulx, uly, lrx, lry, (gDP.otherMode.cycleType == G_CYC_FILL) ? &gDP.fillColor.r : black); + + if (depthBuffer.current) depthBuffer.current->cleared = FALSE; + gDP.colorImage.changed = TRUE; + gDP.colorImage.height = max( gDP.colorImage.height, (unsigned int)lry ); + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPFillRectangle( %i, %i, %i, %i );\n", + ulx, uly, lrx, lry ); +#endif +} + +void gDPSetConvert( s32 k0, s32 k1, s32 k2, s32 k3, s32 k4, s32 k5 ) +{ + gDP.convert.k0 = k0 * 0.0039215689f; + gDP.convert.k1 = k1 * 0.0039215689f; + gDP.convert.k2 = k2 * 0.0039215689f; + gDP.convert.k3 = k3 * 0.0039215689f; + gDP.convert.k4 = k4 * 0.0039215689f; + gDP.convert.k5 = k5 * 0.0039215689f; + gDP.changed |= CHANGED_CONVERT; +} + +void gDPSetKeyR( u32 cR, u32 sR, u32 wR ) +{ + gDP.key.center.r = cR * 0.0039215689f;; + gDP.key.scale.r = sR * 0.0039215689f;; + gDP.key.width.r = wR * 0.0039215689f;; +} + +void gDPSetKeyGB(u32 cG, u32 sG, u32 wG, u32 cB, u32 sB, u32 wB ) +{ + gDP.key.center.g = cG * 0.0039215689f;; + gDP.key.scale.g = sG * 0.0039215689f;; + gDP.key.width.g = wG * 0.0039215689f;; + gDP.key.center.b = cB * 0.0039215689f;; + gDP.key.scale.b = sB * 0.0039215689f;; + gDP.key.width.b = wB * 0.0039215689f;; +} + +void gDPTextureRectangle( f32 ulx, f32 uly, f32 lrx, f32 lry, s32 tile, f32 s, f32 t, f32 dsdx, f32 dtdy ) +{ + if (gDP.colorImage.address == gDP.depthImageAddress) + { + return; + } + + if (gDP.otherMode.cycleType == G_CYC_COPY) + { + dsdx = 1.0f; + lrx += 1.0f; + lry += 1.0f; + } + + gSP.textureTile[0] = &gDP.tiles[tile]; + gSP.textureTile[1] = &gDP.tiles[(tile < 7) ? (tile + 1) : tile]; + + + f32 lrs; + f32 lrt; + if (RSP.cmd == G_TEXRECTFLIP) + { + lrs = s + (lry - uly - 1) * dtdy; + lrt = t + (lrx - ulx - 1) * dsdx; + } + else + { + lrs = s + (lrx - ulx - 1) * dsdx; + lrt = t + (lry - uly - 1) * dtdy; + } + + if (gDP.textureMode == TEXTUREMODE_NORMAL) + gDP.textureMode = TEXTUREMODE_TEXRECT; + + gDP.texRect.width = (unsigned int)(max( lrs, s ) + dsdx); + gDP.texRect.height = (unsigned int)(max( lrt, t ) + dtdy); + + float tmp; + if (lrs < s) + { + tmp = ulx; ulx = lrx; lrx = tmp; + tmp = s; s = lrs; lrs = tmp; + } + if (lrt < t) + { + tmp = uly; uly = lry; lry = tmp; + tmp = t; t = lrt; lrt = tmp; + } + + OGL_DrawTexturedRect( ulx, uly, lrx, lry, s, t, lrs, lrt, (RSP.cmd == G_TEXRECTFLIP)); + + gSP.textureTile[0] = &gDP.tiles[gSP.texture.tile]; + gSP.textureTile[1] = &gDP.tiles[(gSP.texture.tile < 7) ? (gSP.texture.tile + 1) : gSP.texture.tile]; + + if (depthBuffer.current) depthBuffer.current->cleared = FALSE; + gDP.colorImage.changed = TRUE; + gDP.colorImage.height = (unsigned int)(max( gDP.colorImage.height, gDP.scissor.lry )); + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPTextureRectangle( %f, %f, %f, %f, %i, %f, %f, %f, %f );\n", + ulx, uly, lrx, lry, tile, s, t, dsdx, dtdy ); +#endif +} + +void gDPTextureRectangleFlip( f32 ulx, f32 uly, f32 lrx, f32 lry, s32 tile, f32 s, f32 t, f32 dsdx, f32 dtdy ) +{ + //gDPTextureRectangle( ulx, uly, lrx, lry, tile, s + (lrx - ulx) * dsdx, t + (lry - uly) * dtdy, -dsdx, -dtdy ); + + gDPTextureRectangle( ulx, uly, lrx, lry, tile, s, t, dsdx, dtdy ); +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPTextureRectangleFlip( %f, %f, %f, %f, %i, %f, %f, %f, %f);\n", + ulx, uly, lrx, lry, tile, s, t, dsdx, dtdy ); +#endif +} + +void gDPFullSync() +{ + *REG.MI_INTR |= MI_INTR_DP; + + CheckInterrupts(); + +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPFullSync();\n" ); +#endif +} + +void gDPTileSync() +{ +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_IGNORED | DEBUG_TEXTURE, "gDPTileSync();\n" ); +#endif +} + +void gDPPipeSync() +{ +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_IGNORED, "gDPPipeSync();\n" ); +#endif +} + +void gDPLoadSync() +{ +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_IGNORED, "gDPLoadSync();\n" ); +#endif +} + +void gDPNoOp() +{ +#ifdef DEBUG + DebugMsg( DEBUG_HIGH | DEBUG_IGNORED, "gDPNoOp();\n" ); +#endif +} +