Previous "optimization" contained a mistake and made things worse. Removed unnecessary clear of the bottom layer buffer. Now, if there is no bottom layer, it will not be displayed at all and glClear(GL_COLOR_BUFFER_BIT) is used instead.

This commit is contained in:
Bart Trzynadlowski 2012-02-22 01:34:42 +00:00
parent c085be59af
commit fcf1d955a9
2 changed files with 49 additions and 49 deletions

View file

@ -53,14 +53,9 @@
* games use them. * games use them.
* *
* VRAM is comprised of 1 MB for tile data and an additional 128 KB for the * VRAM is comprised of 1 MB for tile data and an additional 128 KB for the
* palette. The four tilemap layers are referred to as: A (0), A' (1), B (2), * palette (each color occupies 32 bits). The four tilemap layers are referred
* and B' (3). Palette RAM may be located on a separate RAM IC. * to as: A (0), A' (1), B (2), and B' (3). Palette RAM may be located on a
* * separate RAM IC.
* NOTE: Supermodel allocates 128 KB for the palette. Either this is incorrect
* (only 64 KB is needed to store 32K colors), the colors are inaccessible, or
* there is a way to access them but no game has done so yet. My suspicion is
* that the palette RAM is in fact only 64 KB but this needs to be verified by
* checking to see if any games write to the high 64 KB.
* *
* Registers * Registers
* --------- * ---------
@ -116,9 +111,8 @@
* Palette * Palette
* ------- * -------
* *
* The palette stores 32768 colors. Each entry is a little endian 16-bit word. * The palette stores 32768 colors. Each entry is a little endian 32-bit word.
* * The upper 16 bits are unused and the lower 16 bits contain the color:
* The format of a palette word is:
* *
* 15 0 * 15 0
* tbbb bbgg gggr rrrr * tbbb bbgg gggr rrrr
@ -386,7 +380,6 @@ void CRender2D::DrawTileLine8BitNoClip(UINT32 *buf, UINT16 tile, int tileLine, c
*/ */
void CRender2D::DrawLine(UINT32 *dest, int layerNum, int y, const UINT16 *nameTableBase, const UINT32 *pal) void CRender2D::DrawLine(UINT32 *dest, int layerNum, int y, const UINT16 *nameTableBase, const UINT32 *pal)
{ {
// Determine the layer color depth (4 or 8-bit pixels) // Determine the layer color depth (4 or 8-bit pixels)
bool is4Bit = regs[0x20/4] & (1<<(12+layerNum)); bool is4Bit = regs[0x20/4] & (1<<(12+layerNum));
@ -530,7 +523,6 @@ static void MixLine(UINT32 *dest, const UINT32 *src, int layerNum, int y, bool i
mask <<= 1; mask <<= 1;
} }
if ((mask&0x8000) == doCopy) if ((mask&0x8000) == doCopy)
{ {
UINT32 p; UINT32 p;
@ -546,7 +538,8 @@ static void MixLine(UINT32 *dest, const UINT32 *src, int layerNum, int y, bool i
} }
} }
void CRender2D::DrawTilemaps(UINT32 *destBottom, UINT32 *destTop) // Returns true if there is no bottom layer (requiring the color buffer to be cleared)
bool CRender2D::DrawTilemaps(UINT32 *destBottom, UINT32 *destTop)
{ {
/* /*
* Precompute data needed for each layer * Precompute data needed for each layer
@ -580,40 +573,40 @@ void CRender2D::DrawTilemaps(UINT32 *destBottom, UINT32 *destTop)
const UINT16 *sortedHScrollTable[4]; const UINT16 *sortedHScrollTable[4];
int sortedHFullScroll[4]; int sortedHFullScroll[4];
bool sortedLineScrollMode[4]; bool sortedLineScrollMode[4];
bool clearBottom; // when true, no layer assigned to bottom surface bool noBottom; // when true, no layer assigned to bottom surface
switch ((regs[0x20/4]>>8)&0xF) switch ((regs[0x20/4]>>8)&0xF)
{ {
case 0x5: // top: A, B, A'? bottom: B' case 0x5: // top: A, B, A'? bottom: B'
clearBottom = false; noBottom = false;
dest[0]=destBottom; src[0]=lineBuffer[3]; sortedLayerNum[0]=3; sortedIsBottom[0]=true; sortedHScrollTable[0] = hScrollTable[3]; sortedHFullScroll[0]=hFullScroll[3]; sortedLineScrollMode[0]=lineScrollMode[3]; dest[0]=destBottom; src[0]=lineBuffer[3]; sortedLayerNum[0]=3; sortedIsBottom[0]=true; sortedHScrollTable[0] = hScrollTable[3]; sortedHFullScroll[0]=hFullScroll[3]; sortedLineScrollMode[0]=lineScrollMode[3];
dest[1]=destTop; src[1]=lineBuffer[2]; sortedLayerNum[1]=2; sortedIsBottom[1]=true; sortedHScrollTable[1] = hScrollTable[2]; sortedHFullScroll[1]=hFullScroll[2]; sortedLineScrollMode[1]=lineScrollMode[2]; dest[1]=destTop; src[1]=lineBuffer[2]; sortedLayerNum[1]=2; sortedIsBottom[1]=true; sortedHScrollTable[1] = hScrollTable[2]; sortedHFullScroll[1]=hFullScroll[2]; sortedLineScrollMode[1]=lineScrollMode[2];
dest[2]=destTop; src[2]=lineBuffer[0]; sortedLayerNum[2]=0; sortedIsBottom[2]=false; sortedHScrollTable[2] = hScrollTable[0]; sortedHFullScroll[2]=hFullScroll[0]; sortedLineScrollMode[2]=lineScrollMode[0]; dest[2]=destTop; src[2]=lineBuffer[0]; sortedLayerNum[2]=0; sortedIsBottom[2]=false; sortedHScrollTable[2] = hScrollTable[0]; sortedHFullScroll[2]=hFullScroll[0]; sortedLineScrollMode[2]=lineScrollMode[0];
dest[3]=destTop; src[3]=lineBuffer[1]; sortedLayerNum[3]=1; sortedIsBottom[3]=false; sortedHScrollTable[3] = hScrollTable[1]; sortedHFullScroll[3]=hFullScroll[1]; sortedLineScrollMode[3]=lineScrollMode[1]; dest[3]=destTop; src[3]=lineBuffer[1]; sortedLayerNum[3]=1; sortedIsBottom[3]=false; sortedHScrollTable[3] = hScrollTable[1]; sortedHFullScroll[3]=hFullScroll[1]; sortedLineScrollMode[3]=lineScrollMode[1];
break; break;
case 0x9: // ? all layers on top but relative order unknown (Spikeout Final Edition, after first boss) case 0x9: // ? all layers on top but relative order unknown (Spikeout Final Edition, after first boss)
clearBottom = true; noBottom = true;
dest[0]=destTop; src[0]=lineBuffer[2]; sortedLayerNum[0]=2; sortedIsBottom[0]=true; sortedHScrollTable[0] = hScrollTable[2]; sortedHFullScroll[0]=hFullScroll[2]; sortedLineScrollMode[0]=lineScrollMode[3]; dest[0]=destTop; src[0]=lineBuffer[2]; sortedLayerNum[0]=2; sortedIsBottom[0]=true; sortedHScrollTable[0] = hScrollTable[2]; sortedHFullScroll[0]=hFullScroll[2]; sortedLineScrollMode[0]=lineScrollMode[3];
dest[1]=destTop; src[1]=lineBuffer[3]; sortedLayerNum[1]=3; sortedIsBottom[1]=false; sortedHScrollTable[1] = hScrollTable[3]; sortedHFullScroll[1]=hFullScroll[3]; sortedLineScrollMode[1]=lineScrollMode[2]; dest[1]=destTop; src[1]=lineBuffer[3]; sortedLayerNum[1]=3; sortedIsBottom[1]=false; sortedHScrollTable[1] = hScrollTable[3]; sortedHFullScroll[1]=hFullScroll[3]; sortedLineScrollMode[1]=lineScrollMode[2];
dest[2]=destTop; src[2]=lineBuffer[1]; sortedLayerNum[2]=1; sortedIsBottom[2]=false; sortedHScrollTable[2] = hScrollTable[1]; sortedHFullScroll[2]=hFullScroll[1]; sortedLineScrollMode[2]=lineScrollMode[1]; dest[2]=destTop; src[2]=lineBuffer[1]; sortedLayerNum[2]=1; sortedIsBottom[2]=false; sortedHScrollTable[2] = hScrollTable[1]; sortedHFullScroll[2]=hFullScroll[1]; sortedLineScrollMode[2]=lineScrollMode[1];
dest[3]=destTop; src[3]=lineBuffer[0]; sortedLayerNum[3]=0; sortedIsBottom[3]=false; sortedHScrollTable[3] = hScrollTable[0]; sortedHFullScroll[3]=hFullScroll[0]; sortedLineScrollMode[3]=lineScrollMode[0]; dest[3]=destTop; src[3]=lineBuffer[0]; sortedLayerNum[3]=0; sortedIsBottom[3]=false; sortedHScrollTable[3] = hScrollTable[0]; sortedHFullScroll[3]=hFullScroll[0]; sortedLineScrollMode[3]=lineScrollMode[0];
break; break;
case 0xF: // all on top case 0xF: // all on top
clearBottom = true; noBottom = true;
dest[0]=destTop; src[0]=lineBuffer[2]; sortedLayerNum[0]=2; sortedIsBottom[0]=true; sortedHScrollTable[0] = hScrollTable[2]; sortedHFullScroll[0]=hFullScroll[2]; sortedLineScrollMode[0]=lineScrollMode[2]; dest[0]=destTop; src[0]=lineBuffer[2]; sortedLayerNum[0]=2; sortedIsBottom[0]=true; sortedHScrollTable[0] = hScrollTable[2]; sortedHFullScroll[0]=hFullScroll[2]; sortedLineScrollMode[0]=lineScrollMode[2];
dest[1]=destTop; src[1]=lineBuffer[3]; sortedLayerNum[1]=3; sortedIsBottom[1]=false; sortedHScrollTable[1] = hScrollTable[3]; sortedHFullScroll[1]=hFullScroll[3]; sortedLineScrollMode[1]=lineScrollMode[3]; dest[1]=destTop; src[1]=lineBuffer[3]; sortedLayerNum[1]=3; sortedIsBottom[1]=false; sortedHScrollTable[1] = hScrollTable[3]; sortedHFullScroll[1]=hFullScroll[3]; sortedLineScrollMode[1]=lineScrollMode[3];
dest[2]=destTop; src[2]=lineBuffer[0]; sortedLayerNum[2]=0; sortedIsBottom[2]=false; sortedHScrollTable[2] = hScrollTable[0]; sortedHFullScroll[2]=hFullScroll[0]; sortedLineScrollMode[2]=lineScrollMode[0]; dest[2]=destTop; src[2]=lineBuffer[0]; sortedLayerNum[2]=0; sortedIsBottom[2]=false; sortedHScrollTable[2] = hScrollTable[0]; sortedHFullScroll[2]=hFullScroll[0]; sortedLineScrollMode[2]=lineScrollMode[0];
dest[3]=destTop; src[3]=lineBuffer[1]; sortedLayerNum[3]=1; sortedIsBottom[3]=false; sortedHScrollTable[3] = hScrollTable[1]; sortedHFullScroll[3]=hFullScroll[1]; sortedLineScrollMode[3]=lineScrollMode[1]; dest[3]=destTop; src[3]=lineBuffer[1]; sortedLayerNum[3]=1; sortedIsBottom[3]=false; sortedHScrollTable[3] = hScrollTable[1]; sortedHFullScroll[3]=hFullScroll[1]; sortedLineScrollMode[3]=lineScrollMode[1];
break; break;
case 0x7: // top: A, B bottom: A'?, B' case 0x7: // top: A, B bottom: A'?, B'
clearBottom = false; noBottom = false;
dest[0]=destBottom; src[0]=lineBuffer[3]; sortedLayerNum[0]=3; sortedIsBottom[0]=true; sortedHScrollTable[0] = hScrollTable[3]; sortedHFullScroll[0]=hFullScroll[3]; sortedLineScrollMode[0]=lineScrollMode[3]; dest[0]=destBottom; src[0]=lineBuffer[3]; sortedLayerNum[0]=3; sortedIsBottom[0]=true; sortedHScrollTable[0] = hScrollTable[3]; sortedHFullScroll[0]=hFullScroll[3]; sortedLineScrollMode[0]=lineScrollMode[3];
dest[1]=destBottom; src[1]=lineBuffer[1]; sortedLayerNum[1]=1; sortedIsBottom[1]=false; sortedHScrollTable[1] = hScrollTable[1]; sortedHFullScroll[1]=hFullScroll[1]; sortedLineScrollMode[1]=lineScrollMode[1]; dest[1]=destBottom; src[1]=lineBuffer[1]; sortedLayerNum[1]=1; sortedIsBottom[1]=false; sortedHScrollTable[1] = hScrollTable[1]; sortedHFullScroll[1]=hFullScroll[1]; sortedLineScrollMode[1]=lineScrollMode[1];
dest[2]=destTop; src[2]=lineBuffer[2]; sortedLayerNum[2]=2; sortedIsBottom[2]=true; sortedHScrollTable[2] = hScrollTable[2]; sortedHFullScroll[2]=hFullScroll[2]; sortedLineScrollMode[2]=lineScrollMode[2]; dest[2]=destTop; src[2]=lineBuffer[2]; sortedLayerNum[2]=2; sortedIsBottom[2]=true; sortedHScrollTable[2] = hScrollTable[2]; sortedHFullScroll[2]=hFullScroll[2]; sortedLineScrollMode[2]=lineScrollMode[2];
dest[3]=destTop; src[3]=lineBuffer[0]; sortedLayerNum[3]=0; sortedIsBottom[3]=false; sortedHScrollTable[3] = hScrollTable[0]; sortedHFullScroll[3]=hFullScroll[0]; sortedLineScrollMode[3]=lineScrollMode[0]; dest[3]=destTop; src[3]=lineBuffer[0]; sortedLayerNum[3]=0; sortedIsBottom[3]=false; sortedHScrollTable[3] = hScrollTable[0]; sortedHFullScroll[3]=hFullScroll[0]; sortedLineScrollMode[3]=lineScrollMode[0];
break; break;
default: // unknown, use A and A' on top, B and B' on the bottom default: // unknown, use A and A' on top, B and B' on the bottom
clearBottom = false; noBottom = false;
dest[0]=destBottom; src[0]=lineBuffer[2]; sortedLayerNum[0]=2; sortedIsBottom[0]=true; sortedHScrollTable[0] = hScrollTable[2]; sortedHFullScroll[0]=hFullScroll[2]; sortedLineScrollMode[0]=lineScrollMode[2]; dest[0]=destBottom; src[0]=lineBuffer[2]; sortedLayerNum[0]=2; sortedIsBottom[0]=true; sortedHScrollTable[0] = hScrollTable[2]; sortedHFullScroll[0]=hFullScroll[2]; sortedLineScrollMode[0]=lineScrollMode[2];
dest[1]=destBottom; src[1]=lineBuffer[3]; sortedLayerNum[1]=3; sortedIsBottom[1]=false; sortedHScrollTable[1] = hScrollTable[3]; sortedHFullScroll[1]=hFullScroll[3]; sortedLineScrollMode[1]=lineScrollMode[3]; dest[1]=destBottom; src[1]=lineBuffer[3]; sortedLayerNum[1]=3; sortedIsBottom[1]=false; sortedHScrollTable[1] = hScrollTable[3]; sortedHFullScroll[1]=hFullScroll[3]; sortedLineScrollMode[1]=lineScrollMode[3];
dest[2]=destTop; src[2]=lineBuffer[0]; sortedLayerNum[2]=0; sortedIsBottom[2]=true; sortedHScrollTable[2] = hScrollTable[0]; sortedHFullScroll[2]=hFullScroll[0]; sortedLineScrollMode[2]=lineScrollMode[0]; dest[2]=destTop; src[2]=lineBuffer[0]; sortedLayerNum[2]=0; sortedIsBottom[2]=true; sortedHScrollTable[2] = hScrollTable[0]; sortedHFullScroll[2]=hFullScroll[0]; sortedLineScrollMode[2]=lineScrollMode[0];
@ -624,9 +617,6 @@ void CRender2D::DrawTilemaps(UINT32 *destBottom, UINT32 *destTop)
/* /*
* Render and mix each line * Render and mix each line
*/ */
if (clearBottom) // no bottom layer
memset(destBottom, 0, 496*384*sizeof(UINT32));
for (int y = 0; y < 384; y++) for (int y = 0; y < 384; y++)
{ {
// Draw one scanline from each layer // Draw one scanline from each layer
@ -645,6 +635,9 @@ void CRender2D::DrawTilemaps(UINT32 *destBottom, UINT32 *destTop)
// Next line in mask table // Next line in mask table
maskTableLine += 2; maskTableLine += 2;
} }
// Indicate whether color buffer must be cleared because no bottom layer
return noBottom;
} }
@ -655,8 +648,40 @@ void CRender2D::DrawTilemaps(UINT32 *destBottom, UINT32 *destTop)
// Draws a surface to the screen (0 is top and 1 is bottom) // Draws a surface to the screen (0 is top and 1 is bottom)
void CRender2D::DisplaySurface(int surface, GLfloat z) void CRender2D::DisplaySurface(int surface, GLfloat z)
{ {
// If bottom surface and wide screen, clear overscan areas // Draw the surface
if (surface && g_Config.wideScreen) glActiveTexture(GL_TEXTURE0); // texture unit 0
glBindTexture(GL_TEXTURE_2D, texID[surface]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f/512.0f, 0.0f); glVertex3f(0.0f, 0.0f, z);
glTexCoord2f(496.0f/512.0f, 0.0f); glVertex3f(1.0f, 0.0f, z);
glTexCoord2f(496.0f/512.0f, 384.0f/512.0f); glVertex3f(1.0f, 1.0f, z);
glTexCoord2f(0.0f/512.0f, 384.0f/512.0f); glVertex3f(0.0f, 1.0f, z);
glEnd();
}
// Set up viewport and OpenGL state for 2D rendering (sets up blending function but disables blending)
void CRender2D::Setup2D(bool isBottom, bool clearAll)
{
// Enable texture mapping and blending
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha of 1.0 is opaque, 0 is transparent
glDisable(GL_BLEND);
// Disable Z-buffering
glDisable(GL_DEPTH_TEST);
// Shader program
glUseProgram(shaderProgram);
// Clear everything if requested or just overscan areas for wide screen mode
if (clearAll)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glViewport(0, 0, totalXPixels, totalYPixels);
glClear(GL_COLOR_BUFFER_BIT);
}
else if (isBottom && g_Config.wideScreen)
{ {
// For now, clear w/ black (may want to use color 0 later) // For now, clear w/ black (may want to use color 0 later)
glClearColor(0.0, 0.0, 0.0, 0.0); glClearColor(0.0, 0.0, 0.0, 0.0);
@ -673,39 +698,13 @@ void CRender2D::DisplaySurface(int surface, GLfloat z)
gluOrtho2D(0.0, 1.0, 1.0, 0.0); gluOrtho2D(0.0, 1.0, 1.0, 0.0);
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); glLoadIdentity();
// Draw the surface
glActiveTexture(GL_TEXTURE0); // texture unit 0
glBindTexture(GL_TEXTURE_2D, texID[surface]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f/512.0f, 0.0f); glVertex3f(0.0f, 0.0f, z);
glTexCoord2f(496.0f/512.0f, 0.0f); glVertex3f(1.0f, 0.0f, z);
glTexCoord2f(496.0f/512.0f, 384.0f/512.0f); glVertex3f(1.0f, 1.0f, z);
glTexCoord2f(0.0f/512.0f, 384.0f/512.0f); glVertex3f(0.0f, 1.0f, z);
glEnd();
}
// Set up viewport and OpenGL state for 2D rendering (sets up blending function but disables blending)
void CRender2D::Setup2D(void)
{
// Enable texture mapping and blending
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // alpha of 1.0 is opaque, 0 is transparent
glDisable(GL_BLEND);
// Disable Z-buffering
glDisable(GL_DEPTH_TEST);
// Shader program
glUseProgram(shaderProgram);
} }
// Bottom layers // Bottom layers
void CRender2D::BeginFrame(void) void CRender2D::BeginFrame(void)
{ {
// Update all layers // Update all layers
DrawTilemaps(surfBottom, surfTop); bool clear = DrawTilemaps(surfBottom, surfTop);
glActiveTexture(GL_TEXTURE0); // texture unit 0 glActiveTexture(GL_TEXTURE0); // texture unit 0
glBindTexture(GL_TEXTURE_2D, texID[0]); glBindTexture(GL_TEXTURE_2D, texID[0]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 496, 384, GL_RGBA, GL_UNSIGNED_BYTE, surfTop); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 496, 384, GL_RGBA, GL_UNSIGNED_BYTE, surfTop);
@ -713,15 +712,16 @@ void CRender2D::BeginFrame(void)
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 496, 384, GL_RGBA, GL_UNSIGNED_BYTE, surfBottom); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 496, 384, GL_RGBA, GL_UNSIGNED_BYTE, surfBottom);
// Display bottom surface // Display bottom surface
Setup2D(); Setup2D(true, clear);
DisplaySurface(1, 0.0); if (!clear)
DisplaySurface(1, 0.0);
} }
// Top layers // Top layers
void CRender2D::EndFrame(void) void CRender2D::EndFrame(void)
{ {
// Display top surface // Display top surface
Setup2D(); Setup2D(false, false);
glEnable(GL_BLEND); glEnable(GL_BLEND);
DisplaySurface(0, -0.5); DisplaySurface(0, -0.5);
} }

View file

@ -147,9 +147,9 @@ private:
void DrawTileLine8BitNoClip(UINT32 *buf, UINT16 tile, int tileLine, const UINT32 *pal); void DrawTileLine8BitNoClip(UINT32 *buf, UINT16 tile, int tileLine, const UINT32 *pal);
void DrawTileLine4BitNoClip(UINT32 *buf, UINT16 tile, int tileLine, const UINT32 *pal); void DrawTileLine4BitNoClip(UINT32 *buf, UINT16 tile, int tileLine, const UINT32 *pal);
void DrawLine(UINT32 *dest, int layerNum, int y, const UINT16 *nameTableBase, const UINT32 *pal); void DrawLine(UINT32 *dest, int layerNum, int y, const UINT16 *nameTableBase, const UINT32 *pal);
void DrawTilemaps(UINT32 *destBottom, UINT32 *destTop); bool DrawTilemaps(UINT32 *destBottom, UINT32 *destTop);
void DisplaySurface(int surface, GLfloat z); void DisplaySurface(int surface, GLfloat z);
void Setup2D(void); void Setup2D(bool isBottom, bool clearAll);
// Data received from tile generator device object // Data received from tile generator device object
const UINT32 *vram; const UINT32 *vram;