1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-07-02 09:03:37 +00:00

Implement VI emulation: treat main frame buffer as TV screen and render

FBO buffers on it according to VI registers values.
This commit is contained in:
Sergey Lipskiy 2013-09-29 22:02:50 +07:00
parent 4e39f37a34
commit 5cedc0e6e7
3 changed files with 54 additions and 7 deletions

View File

@ -324,18 +324,53 @@ void FrameBuffer_SaveBuffer( u32 address, u16 format, u16 size, u16 width, u16 h
#if 1
void FrameBuffer_RenderBuffer( u32 address )
{
if (_SHIFTR( *REG.VI_H_START, 0, 10 ) == 0) // H width is zero. Don't draw
return;
FrameBuffer *current = FrameBuffer_FindBuffer(address);
if (current == NULL)
return;
GLint srcY0, srcY1, dstY0, dstY1;
GLint partHeight = 0;
dstY0 = 1;
const u32 vStart = _SHIFTR( *REG.VI_V_START, 17, 9 );
const u32 vEnd = _SHIFTR( *REG.VI_V_START, 1, 9 );
const float viScaleY = OGL.height / (float)VI.vHeight;
if (VI.vStart != vStart)
dstY0 += vStart - VI.vStart;
dstY1 = dstY0 + vEnd - vStart;
srcY0 = ((address - current->startAddress) << 1 >> current->size) / (*REG.VI_WIDTH);
srcY1 = srcY0 + VI.real_height;
if (srcY1 > VI.height) {
partHeight = srcY1 - VI.height;
srcY1 = VI.height;
dstY1 -= partHeight;
}
ogl_glBindFramebuffer(GL_READ_FRAMEBUFFER, current->fbo);
ogl_glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glDrawBuffer( GL_FRONT );
ogl_glBlitFramebuffer(
// 0, 0, current->texture->realWidth, current->texture->realHeight,
0, 0, OGL.width, OGL.height,
0, OGL.heightOffset, OGL.width, OGL.height+OGL.heightOffset,
0, (GLint)(srcY0*OGL.scaleY), OGL.width, (GLint)(srcY1*OGL.scaleY),
0, OGL.heightOffset + (GLint)(dstY0*viScaleY), OGL.width, OGL.heightOffset + (GLint)(dstY1*viScaleY),
GL_COLOR_BUFFER_BIT, GL_LINEAR
);
if (partHeight > 0) {
const u32 size = *REG.VI_STATUS & 3;
current = FrameBuffer_FindBuffer(address + (((*REG.VI_WIDTH)*VI.height)<<size>>1));
if (current != NULL) {
srcY0 = 0;
srcY1 = partHeight;
dstY0 = dstY1;
dstY1 = dstY0 + partHeight;
ogl_glBindFramebuffer(GL_READ_FRAMEBUFFER, current->fbo);
ogl_glBlitFramebuffer(
0, (GLint)(srcY0*OGL.scaleY), OGL.width, (GLint)(srcY1*OGL.scaleY),
0, OGL.heightOffset + (GLint)(dstY0*viScaleY), OGL.width, OGL.heightOffset + (GLint)(dstY1*viScaleY),
GL_COLOR_BUFFER_BIT, GL_LINEAR
);
}
}
glDrawBuffer( GL_BACK );
ogl_glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
ogl_glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBuffer.top->fbo);

15
VI.cpp
View File

@ -27,9 +27,16 @@ void VI_UpdateSize()
u32 vStart = _SHIFTR( *REG.VI_V_START, 17, 9 );
VI.width = (hEnd - hStart) * xScale;
VI.height = (vEnd - vStart) * yScale * 1.0126582f;
VI.real_height = (vEnd - vStart) * yScale;
VI.height = VI.real_height*1.0126582f;
if (VI.width == 0.0f) VI.width = 320.0f;
if (VI.vStart == 0) {
VI.vStart = vStart;
VI.vEnd = vEnd;
VI.vHeight = VI.height;
}
if (VI.width == 0.0f) VI.width = *REG.VI_WIDTH;
if (VI.height == 0.0f) VI.height = 240.0f;
}
@ -42,10 +49,12 @@ void VI_UpdateScreen()
OGL_SaveScreenshot();
OGL.captureScreen = false;
}
if (((*REG.VI_STATUS)&3) == 0)
VI.vStart = VI.vEnd = 0;
if (OGL.frameBufferTextures) {
const bool bCFB = (gSP.changed&CHANGED_CPU_FB_WRITE) == CHANGED_CPU_FB_WRITE;
const bool bNeedUpdate = bCFB ? true : (*REG.VI_ORIGIN != VI.lastOrigin) && gDP.colorImage.changed;
const bool bNeedUpdate = bCFB ? true : (*REG.VI_ORIGIN != VI.lastOrigin);// && gDP.colorImage.changed;
if (bNeedUpdate) {
FrameBuffer * pBuffer = FrameBuffer_FindBuffer(*REG.VI_ORIGIN);

5
VI.h
View File

@ -4,8 +4,11 @@
struct VIInfo
{
u32 width, height;
u32 width, height, real_height;
u32 vStart, vEnd, vHeight;
u32 lastOrigin;
VIInfo() : width(0), height(0), real_height(0), vStart(0), vEnd(0), vHeight(0), lastOrigin(0) {}
};
extern VIInfo VI;