2013-04-21 14:28:50 +00:00
|
|
|
#include "GLideN64.h"
|
2014-09-30 15:17:03 +00:00
|
|
|
#include <math.h>
|
2013-04-05 06:13:26 +00:00
|
|
|
#include "Types.h"
|
|
|
|
#include "VI.h"
|
|
|
|
#include "OpenGL.h"
|
|
|
|
#include "N64.h"
|
|
|
|
#include "gSP.h"
|
|
|
|
#include "gDP.h"
|
|
|
|
#include "RSP.h"
|
|
|
|
#include "FrameBuffer.h"
|
2014-09-28 06:10:26 +00:00
|
|
|
#include "DepthBuffer.h"
|
2014-04-05 02:57:00 +00:00
|
|
|
#include "Config.h"
|
2013-04-05 06:13:26 +00:00
|
|
|
#include "Debug.h"
|
|
|
|
|
2014-10-07 05:28:18 +00:00
|
|
|
using namespace std;
|
|
|
|
|
2013-04-05 06:13:26 +00:00
|
|
|
VIInfo VI;
|
|
|
|
|
|
|
|
void VI_UpdateSize()
|
|
|
|
{
|
2014-09-26 12:28:15 +00:00
|
|
|
const f32 xScale = _FIXED2FLOAT( _SHIFTR( *REG.VI_X_SCALE, 0, 12 ), 10 );
|
|
|
|
// f32 xOffset = _FIXED2FLOAT( _SHIFTR( *REG.VI_X_SCALE, 16, 12 ), 10 );
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2014-09-27 15:27:32 +00:00
|
|
|
const u32 vScale = _SHIFTR(*REG.VI_Y_SCALE, 0, 12);
|
2014-09-26 12:28:15 +00:00
|
|
|
// f32 yOffset = _FIXED2FLOAT( _SHIFTR( *REG.VI_Y_SCALE, 16, 12 ), 10 );
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2014-09-26 12:28:15 +00:00
|
|
|
const u32 hEnd = _SHIFTR( *REG.VI_H_START, 0, 10 );
|
|
|
|
const u32 hStart = _SHIFTR( *REG.VI_H_START, 16, 10 );
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2014-09-26 12:28:15 +00:00
|
|
|
// These are in half-lines, so shift an extra bit
|
2014-10-03 08:43:35 +00:00
|
|
|
const u32 vEnd = _SHIFTR( *REG.VI_V_START, 0, 10 );
|
|
|
|
const u32 vStart = _SHIFTR( *REG.VI_V_START, 16, 10 );
|
2014-09-28 06:10:26 +00:00
|
|
|
const bool interlacedPrev = VI.interlaced;
|
2015-04-02 09:47:05 +00:00
|
|
|
if (VI.width > 0)
|
|
|
|
VI.widthPrev = VI.width;
|
2014-09-29 08:52:12 +00:00
|
|
|
|
2014-12-26 08:31:24 +00:00
|
|
|
VI.real_height = vEnd > vStart ? (((vEnd - vStart) >> 1) * vScale) >> 10 : 0;
|
2015-03-05 11:01:57 +00:00
|
|
|
VI.width = *REG.VI_WIDTH;
|
|
|
|
VI.interlaced = (*REG.VI_STATUS & 0x40) != 0;
|
2014-12-22 07:48:45 +00:00
|
|
|
if (VI.interlaced) {
|
2015-03-19 13:35:30 +00:00
|
|
|
f32 fullWidth = 640.0f*xScale;
|
2015-03-05 11:01:57 +00:00
|
|
|
if (*REG.VI_WIDTH > fullWidth) {
|
2015-03-19 13:35:30 +00:00
|
|
|
const u32 scale = (u32)floorf(*REG.VI_WIDTH / fullWidth + 0.5f);
|
2015-03-05 11:01:57 +00:00
|
|
|
VI.width /= scale;
|
|
|
|
VI.real_height *= scale;
|
|
|
|
}
|
|
|
|
if (VI.real_height % 2 == 1)
|
|
|
|
--VI.real_height;
|
|
|
|
} else if (hEnd != 0 && *REG.VI_WIDTH != 0)
|
2015-03-13 10:42:36 +00:00
|
|
|
VI.width = min((u32)floorf((hEnd - hStart)*xScale + 0.5f), *REG.VI_WIDTH);
|
2014-11-29 12:45:27 +00:00
|
|
|
|
2015-04-27 10:40:32 +00:00
|
|
|
VI.PAL = (*REG.VI_V_SYNC & 0x3ff) > 550;
|
|
|
|
if (VI.PAL && (vEnd - vStart) > 478) {
|
2014-12-24 10:09:04 +00:00
|
|
|
VI.height = (u32)(VI.real_height*1.0041841f);
|
2015-03-06 12:25:29 +00:00
|
|
|
if (VI.height > 576)
|
|
|
|
VI.height = VI.real_height = 576;
|
|
|
|
}
|
|
|
|
else {
|
2014-12-24 10:09:04 +00:00
|
|
|
VI.height = (u32)(VI.real_height*1.0126582f);
|
2015-03-06 12:25:29 +00:00
|
|
|
if (VI.height > 480)
|
|
|
|
VI.height = VI.real_height = 480;
|
|
|
|
}
|
2015-02-19 09:47:18 +00:00
|
|
|
if (VI.height % 2 == 1)
|
|
|
|
--VI.height;
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2014-10-03 08:43:35 +00:00
|
|
|
// const int fsaa = ((*REG.VI_STATUS) >> 8) & 3;
|
|
|
|
// const int divot = ((*REG.VI_STATUS) >> 4) & 1;
|
2015-04-11 10:17:44 +00:00
|
|
|
FrameBufferList & fbList = frameBufferList();
|
|
|
|
FrameBuffer * pBuffer = fbList.findBuffer(VI.lastOrigin);
|
|
|
|
DepthBuffer * pDepthBuffer = pBuffer != NULL ? pBuffer->m_pDepthBuffer : NULL;
|
2015-04-11 16:48:43 +00:00
|
|
|
if (config.frameBufferEmulation.enable &&
|
|
|
|
((interlacedPrev != VI.interlaced) ||
|
|
|
|
(VI.width > 0 && VI.width != VI.widthPrev) ||
|
2015-04-12 17:19:18 +00:00
|
|
|
(!VI.interlaced && pDepthBuffer != NULL && pDepthBuffer->m_width != VI.width) ||
|
2015-04-11 16:48:43 +00:00
|
|
|
(pBuffer != NULL && pBuffer->m_height != VI.height))
|
|
|
|
) {
|
2015-04-02 09:47:05 +00:00
|
|
|
fbList.removeBuffers(VI.widthPrev);
|
2015-03-21 08:18:55 +00:00
|
|
|
fbList.removeBuffers(VI.width);
|
2014-09-29 08:52:12 +00:00
|
|
|
depthBufferList().destroy();
|
|
|
|
depthBufferList().init();
|
|
|
|
}
|
|
|
|
|
2014-10-19 06:34:10 +00:00
|
|
|
VI.rwidth = VI.width != 0 ? 1.0f / VI.width : 0.0f;
|
|
|
|
VI.rheight = VI.height != 0 ? 1.0f / VI.height : 0.0f;
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void VI_UpdateScreen()
|
|
|
|
{
|
2013-09-15 14:40:16 +00:00
|
|
|
static u32 uNumCurFrameIsShown = 0;
|
2015-02-11 09:32:59 +00:00
|
|
|
|
|
|
|
if (VI.lastOrigin == -1) // Workaround for Mupen64Plus issue with initialization
|
|
|
|
isGLError();
|
|
|
|
|
2015-05-01 11:08:51 +00:00
|
|
|
if (ConfigOpen)
|
|
|
|
return;
|
|
|
|
|
2014-09-21 12:15:22 +00:00
|
|
|
OGLVideo & ogl = video();
|
|
|
|
if (ogl.changeWindow())
|
|
|
|
return;
|
2014-10-01 09:04:15 +00:00
|
|
|
if (ogl.resizeWindow())
|
|
|
|
return;
|
2014-09-21 12:15:22 +00:00
|
|
|
ogl.saveScreenshot();
|
2013-08-03 09:56:18 +00:00
|
|
|
|
2014-12-24 10:10:02 +00:00
|
|
|
bool bVIUpdated = false;
|
2014-11-28 10:24:58 +00:00
|
|
|
if (*REG.VI_ORIGIN != VI.lastOrigin) {
|
2014-11-24 17:10:33 +00:00
|
|
|
VI_UpdateSize();
|
2014-12-24 10:10:02 +00:00
|
|
|
bVIUpdated = true;
|
2014-12-24 09:58:42 +00:00
|
|
|
ogl.updateScale();
|
2014-11-24 17:10:33 +00:00
|
|
|
}
|
|
|
|
|
2014-04-05 15:36:20 +00:00
|
|
|
if (config.frameBufferEmulation.enable) {
|
2015-03-21 15:14:10 +00:00
|
|
|
const bool bCFB = config.frameBufferEmulation.detectCFB != 0 && (gSP.changed&CHANGED_CPU_FB_WRITE) == CHANGED_CPU_FB_WRITE;
|
2015-02-20 11:31:58 +00:00
|
|
|
const bool bNeedUpdate = gDP.colorImage.changed != 0 || (bCFB ? true : (*REG.VI_ORIGIN != VI.lastOrigin));
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2013-09-07 16:31:04 +00:00
|
|
|
if (bNeedUpdate) {
|
2014-09-29 08:52:12 +00:00
|
|
|
if ((gSP.changed&CHANGED_CPU_FB_WRITE) == CHANGED_CPU_FB_WRITE) {
|
|
|
|
FrameBuffer * pBuffer = frameBufferList().findBuffer(*REG.VI_ORIGIN);
|
|
|
|
if (pBuffer == NULL || pBuffer->m_width != VI.width) {
|
2014-12-24 10:10:02 +00:00
|
|
|
if (!bVIUpdated) {
|
|
|
|
VI_UpdateSize();
|
|
|
|
ogl.updateScale();
|
|
|
|
bVIUpdated = true;
|
|
|
|
}
|
2014-09-29 08:52:12 +00:00
|
|
|
const u32 size = *REG.VI_STATUS & 3;
|
2014-10-03 09:51:12 +00:00
|
|
|
if (VI.height > 0 && size > G_IM_SIZ_8b && VI.width > 0)
|
2014-09-29 08:52:12 +00:00
|
|
|
frameBufferList().saveBuffer(*REG.VI_ORIGIN, G_IM_FMT_RGBA, size, VI.width, VI.height, true);
|
|
|
|
}
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
2015-02-21 05:52:01 +00:00
|
|
|
if ((((*REG.VI_STATUS) & 3) > 0) && ((config.frameBufferEmulation.copyFromRDRAM && gDP.colorImage.changed) || bCFB)) {
|
2014-12-24 10:10:02 +00:00
|
|
|
if (!bVIUpdated) {
|
|
|
|
VI_UpdateSize();
|
|
|
|
bVIUpdated = true;
|
|
|
|
}
|
|
|
|
FrameBuffer_CopyFromRDRAM(*REG.VI_ORIGIN, config.frameBufferEmulation.copyFromRDRAM && !bCFB);
|
2013-09-26 10:28:07 +00:00
|
|
|
}
|
2014-09-08 11:01:22 +00:00
|
|
|
frameBufferList().renderBuffer(*REG.VI_ORIGIN);
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2015-02-18 05:08:42 +00:00
|
|
|
if (gDP.colorImage.changed)
|
|
|
|
uNumCurFrameIsShown = 0;
|
|
|
|
else {
|
|
|
|
uNumCurFrameIsShown++;
|
|
|
|
if (uNumCurFrameIsShown > 25)
|
|
|
|
gSP.changed |= CHANGED_CPU_FB_WRITE;
|
|
|
|
}
|
2015-03-01 11:52:59 +00:00
|
|
|
frameBufferList().clearBuffersChanged();
|
2013-04-05 06:13:26 +00:00
|
|
|
VI.lastOrigin = *REG.VI_ORIGIN;
|
|
|
|
#ifdef DEBUG
|
|
|
|
while (Debug.paused && !Debug.step);
|
|
|
|
Debug.step = FALSE;
|
|
|
|
#endif
|
2013-09-15 14:40:16 +00:00
|
|
|
} else {
|
|
|
|
uNumCurFrameIsShown++;
|
2013-09-29 14:59:20 +00:00
|
|
|
if (uNumCurFrameIsShown > 25)
|
2013-09-15 14:40:16 +00:00
|
|
|
gSP.changed |= CHANGED_CPU_FB_WRITE;
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
}
|
2013-09-07 16:31:04 +00:00
|
|
|
else {
|
2015-05-18 06:35:48 +00:00
|
|
|
if (gDP.changed & CHANGED_COLORBUFFER) {
|
2014-09-21 12:15:22 +00:00
|
|
|
ogl.swapBuffers();
|
2015-05-18 06:35:48 +00:00
|
|
|
gDP.changed &= ~CHANGED_COLORBUFFER;
|
2013-04-05 06:13:26 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
while (Debug.paused && !Debug.step);
|
|
|
|
Debug.step = FALSE;
|
|
|
|
#endif
|
2014-11-28 10:24:58 +00:00
|
|
|
VI.lastOrigin = *REG.VI_ORIGIN;
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
}
|
2014-11-24 17:08:03 +00:00
|
|
|
|
2014-12-24 10:16:36 +00:00
|
|
|
if (VI.lastOrigin == -1) { // Workaround for Mupen64Plus issue with initialization
|
2014-11-24 17:08:03 +00:00
|
|
|
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
|
|
}
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|