mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2025-02-17 01:45:41 +00:00
Added a wide screen hack that can be enabled with the -'wide-screen' argument or WideScreen in the config file.
This commit is contained in:
parent
40a51287df
commit
1b8740165c
|
@ -22,15 +22,35 @@
|
||||||
/*
|
/*
|
||||||
* Render2D.cpp
|
* Render2D.cpp
|
||||||
*
|
*
|
||||||
|
* To-Do List
|
||||||
|
* ----------
|
||||||
|
* - Fix color offsets: they should probably be applied to layers A/A' and B/B'
|
||||||
|
* rather than to the top and bottom surfaces (an artifact left over from
|
||||||
|
* when layer priorities were fixed as B/B' -> bottom, A/A' -> top). This can
|
||||||
|
* no longer be performed by the shaders, unfortunately, because of arbitrary
|
||||||
|
* layer priorities. Rather, three palettes should be maintained: master (the
|
||||||
|
* actual palette data), A, and B. Color offset writes should recompute
|
||||||
|
* these and the tile renderer should use either A or B palette (depending on
|
||||||
|
* the layer being drawn).
|
||||||
|
* - Is there a better way to handle the overscan regions in wide screen mode
|
||||||
|
* than using palette entry 0 as the fill color? Is clearing two thin
|
||||||
|
* viewports better than one big clear?
|
||||||
|
* - Layer priorities in Spikeout attract mode might not be totally correct.
|
||||||
|
* - Are v-scroll values 9 or 10 bits? (Does it matter?) Lost World seems to
|
||||||
|
* have some scrolling issues.
|
||||||
|
* - A proper shut-down function is needed! OpenGL might not be available when
|
||||||
|
* the destructor for this class is called.
|
||||||
|
*
|
||||||
* Implementation of the CRender2D class: OpenGL tile generator graphics.
|
* Implementation of the CRender2D class: OpenGL tile generator graphics.
|
||||||
*
|
*
|
||||||
* Tile Generator Hardware Overview
|
* Tile Generator Hardware Overview
|
||||||
* --------------------------------
|
* --------------------------------
|
||||||
*
|
*
|
||||||
* Model 3's medium resolution tile generator hardware appears to be derived
|
* Model 3's medium resolution tile generator hardware appears to be derived
|
||||||
* from the Model 2 and System 24 chipset. It consists of four 64x64 tile
|
* from the Model 2 and System 24 chipset, but is much simpler. It consists of
|
||||||
* layers, comprised of 8x8 pixel tiles, with configurable priorities. There
|
* four 64x64 tile layers, comprised of 8x8 pixel tiles, with configurable
|
||||||
* may be additional features but so far, no known Model 3 games use them.
|
* priorities. There may be additional features but so far, no known Model 3
|
||||||
|
* 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. The four tilemap layers are referred to as: A (0), A' (1), B (2),
|
||||||
|
@ -65,8 +85,9 @@
|
||||||
* ???? ???? ???? ???? pqrs tuvw ???? ????
|
* ???? ???? ???? ???? pqrs tuvw ???? ????
|
||||||
*
|
*
|
||||||
* Bits 'pqrs' control the color depth of layers B', B, A', and A,
|
* Bits 'pqrs' control the color depth of layers B', B, A', and A,
|
||||||
* respectively, and 'tuvw' form a 4-bit priority code. The other bits are
|
* respectively. If set, the layer's pattern data is encoded as 4 bits,
|
||||||
* unused or unknown.
|
* otherwise the pixels are 8 bits. Bits 'tuvw' form a 4-bit priority code. The
|
||||||
|
* other bits are unused or unknown.
|
||||||
*
|
*
|
||||||
* The remaining registers are described where appropriate further below.
|
* The remaining registers are described where appropriate further below.
|
||||||
*
|
*
|
||||||
|
@ -257,17 +278,6 @@
|
||||||
* Where 'r', 'g', and 'b' appear to be signed 8-bit color offsets. Because
|
* Where 'r', 'g', and 'b' appear to be signed 8-bit color offsets. Because
|
||||||
* they exceed the color resolution of the palette, they must be scaled
|
* they exceed the color resolution of the palette, they must be scaled
|
||||||
* appropriately.
|
* appropriately.
|
||||||
*
|
|
||||||
* To-Do List
|
|
||||||
* ----------
|
|
||||||
* - Fix color offsets: they should probably be applied to layers A/A' and B/B'
|
|
||||||
* rather than to the top and bottom surfaces (an artifact left over from
|
|
||||||
* when layer priorities were fixed as B/B' -> bottom, A/A' -> top). This can
|
|
||||||
* no longer be performed by the shaders, unfortunately, because of arbitrary
|
|
||||||
* layer priorities.
|
|
||||||
* - Are v-scroll values 9 or 10 bits?
|
|
||||||
* - A proper shut-down function is needed! OpenGL might not be available when
|
|
||||||
* the destructor for this class is called.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -358,8 +368,7 @@ void CRender2D::DrawTileLine8BitNoClip(UINT32 *buf, UINT16 tile, int tileLine)
|
||||||
* scrolling is applied here.
|
* scrolling is applied here.
|
||||||
*
|
*
|
||||||
* Parametes:
|
* Parametes:
|
||||||
* dest Destination of 512-pixel wide output buffer to draw
|
* dest Destination of 512-pixel output buffer to draw to.
|
||||||
* to.
|
|
||||||
* layerNum Layer number:
|
* layerNum Layer number:
|
||||||
* 0 = Layer A (@ 0xF8000)
|
* 0 = Layer A (@ 0xF8000)
|
||||||
* 1 = Layer A' (@ 0xFA000)
|
* 1 = Layer A' (@ 0xFA000)
|
||||||
|
@ -571,6 +580,13 @@ void CRender2D::DrawTilemaps(UINT32 *destBottom, UINT32 *destTop)
|
||||||
MixLine(destTop, lineBuffer[0], 0, y, false);
|
MixLine(destTop, lineBuffer[0], 0, y, false);
|
||||||
MixLine(destTop, lineBuffer[1], 1, y, false);
|
MixLine(destTop, lineBuffer[1], 1, y, false);
|
||||||
break;
|
break;
|
||||||
|
case 0x9: // ? all layers on top but relative order unknown (Spikeout Final Edition, after first boss)
|
||||||
|
memset(destBottom, 0, 496*sizeof(UINT32)); //TODO: use glClear(GL_COLOR_BUFFER_BIT) if there is no bottom layer
|
||||||
|
MixLine(destTop, lineBuffer[2], 2, y, true);
|
||||||
|
MixLine(destTop, lineBuffer[3], 3, y, false);
|
||||||
|
MixLine(destTop, lineBuffer[1], 1, y, false);
|
||||||
|
MixLine(destTop, lineBuffer[0], 0, y, false);
|
||||||
|
break;
|
||||||
case 0xF: // all on top
|
case 0xF: // all on top
|
||||||
memset(destBottom, 0, 496*sizeof(UINT32)); //TODO: use glClear(GL_COLOR_BUFFER_BIT) if there is no bottom layer
|
memset(destBottom, 0, 496*sizeof(UINT32)); //TODO: use glClear(GL_COLOR_BUFFER_BIT) if there is no bottom layer
|
||||||
MixLine(destTop, lineBuffer[2], 2, y, true);
|
MixLine(destTop, lineBuffer[2], 2, y, true);
|
||||||
|
@ -606,6 +622,29 @@ 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
|
||||||
|
if (surface && g_Config.wideScreen)
|
||||||
|
{
|
||||||
|
UINT32 c = pal[0]; // just use palette color 0 for now (not the best solution, it's usually black)
|
||||||
|
GLfloat r = (GLfloat)(c&0xFF) / 255.0f;
|
||||||
|
GLfloat g = (GLfloat)((c>>8)&0xFF) / 255.0f;
|
||||||
|
GLfloat b = (GLfloat)((c>>16)&0xFF) / 255.0f;
|
||||||
|
glClearColor(r, g, b, 0.0);
|
||||||
|
glViewport(0, 0, xOffs, totalYPixels);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
glViewport(xOffs+xPixels, 0, totalXPixels, totalYPixels);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up the viewport and orthogonal projection
|
||||||
|
glViewport(xOffs, yOffs, xPixels, yPixels);
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
gluOrtho2D(0.0, 1.0, 1.0, 0.0);
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
// Draw the surface
|
||||||
glBindTexture(GL_TEXTURE_2D, texID[surface]);
|
glBindTexture(GL_TEXTURE_2D, texID[surface]);
|
||||||
glBegin(GL_QUADS);
|
glBegin(GL_QUADS);
|
||||||
glTexCoord2f(0.0f/512.0f, 0.0f); glVertex3f(0.0f, 0.0f, z);
|
glTexCoord2f(0.0f/512.0f, 0.0f); glVertex3f(0.0f, 0.0f, z);
|
||||||
|
@ -618,14 +657,6 @@ void CRender2D::DisplaySurface(int surface, GLfloat z)
|
||||||
// Set up viewport and OpenGL state for 2D rendering (sets up blending function but disables blending)
|
// Set up viewport and OpenGL state for 2D rendering (sets up blending function but disables blending)
|
||||||
void CRender2D::Setup2D(void)
|
void CRender2D::Setup2D(void)
|
||||||
{
|
{
|
||||||
// Set up the viewport and orthogonal projection
|
|
||||||
glViewport(xOffs, yOffs, xPixels, yPixels);
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
glLoadIdentity();
|
|
||||||
gluOrtho2D(0.0, 1.0, 1.0, 0.0);
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
glLoadIdentity();
|
|
||||||
|
|
||||||
// Enable texture mapping and blending
|
// Enable texture mapping and blending
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
||||||
|
@ -731,7 +762,7 @@ void CRender2D::AttachVRAM(const UINT8 *vramPtr)
|
||||||
#define OFFSET_BOTTOM_SURFACE (512*384*4) // 512*384*4
|
#define OFFSET_BOTTOM_SURFACE (512*384*4) // 512*384*4
|
||||||
#define OFFSET_LINE_BUFFERS (2*512*384*4) // 4*512*4 (4 lines)
|
#define OFFSET_LINE_BUFFERS (2*512*384*4) // 4*512*4 (4 lines)
|
||||||
|
|
||||||
bool CRender2D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes)
|
bool CRender2D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXRes, unsigned totalYRes)
|
||||||
{
|
{
|
||||||
float memSizeMB = (float)MEMORY_POOL_SIZE/(float)0x100000;
|
float memSizeMB = (float)MEMORY_POOL_SIZE/(float)0x100000;
|
||||||
|
|
||||||
|
@ -762,6 +793,8 @@ bool CRender2D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned
|
||||||
yPixels = yRes;
|
yPixels = yRes;
|
||||||
xOffs = xOffset;
|
xOffs = xOffset;
|
||||||
yOffs = yOffset;
|
yOffs = yOffset;
|
||||||
|
totalXPixels = totalXRes;
|
||||||
|
totalYPixels = totalYRes;
|
||||||
|
|
||||||
// Create textures
|
// Create textures
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
|
|
@ -102,23 +102,26 @@ public:
|
||||||
void AttachVRAM(const UINT8 *vramPtr);
|
void AttachVRAM(const UINT8 *vramPtr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Init(xOffset, yOffset, xRes, yRes);
|
* Init(xOffset, yOffset, xRes, yRes, totalXRes, totalYRes);
|
||||||
*
|
*
|
||||||
* One-time initialization of the context. Must be called before any other
|
* One-time initialization of the context. Must be called before any other
|
||||||
* members (meaning it should be called even before being attached to any
|
* members (meaning it should be called even before being attached to any
|
||||||
* other objects that want to use it).
|
* other objects that want to use it).
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* xOffset X offset within OpenGL display surface in pixels.
|
* xOffset X offset of the viewable area within OpenGL display
|
||||||
|
* surface, in pixels.
|
||||||
* yOffset Y offset.
|
* yOffset Y offset.
|
||||||
* xRes Horizontal resolution of display surface in pixels.
|
* xRes Horizontal resolution of the viewable area.
|
||||||
* yRes Vertical resolution.
|
* yRes Vertical resolution.
|
||||||
|
* totalXRes Horizontal resolution of the complete display area.
|
||||||
|
* totalYRes Vertical resolution.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* OKAY is successful, otherwise FAILED if a non-recoverable error
|
* OKAY is successful, otherwise FAILED if a non-recoverable error
|
||||||
* occurred. Prints own error messages.
|
* occurred. Prints own error messages.
|
||||||
*/
|
*/
|
||||||
bool Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes);
|
bool Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXRes, unsigned totalYRes);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CRender2D(void):
|
* CRender2D(void):
|
||||||
|
@ -153,6 +156,7 @@ private:
|
||||||
GLuint texID[2]; // IDs for the 2 layer textures (top and bottom)
|
GLuint texID[2]; // IDs for the 2 layer textures (top and bottom)
|
||||||
unsigned xPixels, yPixels; // display surface resolution
|
unsigned xPixels, yPixels; // display surface resolution
|
||||||
unsigned xOffs, yOffs; // offset
|
unsigned xOffs, yOffs; // offset
|
||||||
|
unsigned totalXPixels, totalYPixels; // totay display surface resolution
|
||||||
|
|
||||||
// Shader programs and input data locations
|
// Shader programs and input data locations
|
||||||
GLuint shaderProgram; // shader program object
|
GLuint shaderProgram; // shader program object
|
||||||
|
|
|
@ -210,7 +210,20 @@ void CRender3D::DecodeTexture(int format, int x, int y, int width, int height)
|
||||||
i = 0;
|
i = 0;
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
default:
|
default: // Unknown
|
||||||
|
|
||||||
|
for (yi = y; yi < (y+height); yi++)
|
||||||
|
{
|
||||||
|
for (xi = x; xi < (x+width); xi++)
|
||||||
|
{
|
||||||
|
textureBuffer[i++] = 0.0; // R
|
||||||
|
textureBuffer[i++] = 0.0; // G
|
||||||
|
textureBuffer[i++] = 1.0f; // B
|
||||||
|
textureBuffer[i++] = 1.0f; // A
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 0: // T1RGB5
|
case 0: // T1RGB5
|
||||||
for (yi = y; yi < (y+height); yi++)
|
for (yi = y; yi < (y+height); yi++)
|
||||||
{
|
{
|
||||||
|
@ -262,7 +275,6 @@ void CRender3D::DecodeTexture(int format, int x, int y, int width, int height)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case 4: // 8-bit, L4A4
|
case 4: // 8-bit, L4A4
|
||||||
|
|
||||||
for (yi = y; yi < (y+height); yi++)
|
for (yi = y; yi < (y+height); yi++)
|
||||||
|
@ -826,13 +838,26 @@ void CRender3D::RenderViewport(UINT32 addr, int pri)
|
||||||
// TO-DO: investigate clipping planes
|
// TO-DO: investigate clipping planes
|
||||||
|
|
||||||
// Set up viewport and projection (TO-DO: near and far clipping)
|
// Set up viewport and projection (TO-DO: near and far clipping)
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
if (g_Config.wideScreen && (vpX==0) && (vpY==0) && (vpWidth>=495) && (vpHeight >= 383))
|
||||||
|
{
|
||||||
|
// Wide screen hack only modifies X axis and not the Y FOV
|
||||||
|
viewportX = 0;
|
||||||
|
viewportY = yOffs + (GLint) ((float)(384-(vpY+vpHeight))*yRatio);
|
||||||
|
viewportWidth = totalXRes;
|
||||||
|
viewportHeight = (GLint) ((float)vpHeight*yRatio);
|
||||||
|
gluPerspective(fovYDegrees,(GLfloat)viewportWidth/(GLfloat)viewportHeight,0.1f,1e5); // use actual full screen ratio to get proper X FOV
|
||||||
|
//printf("viewportX=%d, viewportY=%d, viewportWidth=%d, viewportHeight=%d\tvpY=%d vpHeight=%d\n", viewportX, viewportY, viewportWidth, viewportHeight, vpY,vpHeight);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
viewportX = xOffs + (GLint) ((float)vpX*xRatio);
|
viewportX = xOffs + (GLint) ((float)vpX*xRatio);
|
||||||
viewportY = yOffs + (GLint) ((float)(384-(vpY+vpHeight))*yRatio);
|
viewportY = yOffs + (GLint) ((float)(384-(vpY+vpHeight))*yRatio);
|
||||||
viewportWidth = (GLint) ((float)vpWidth*xRatio);
|
viewportWidth = (GLint) ((float)vpWidth*xRatio);
|
||||||
viewportHeight = (GLint) ((float)vpHeight*yRatio);
|
viewportHeight = (GLint) ((float)vpHeight*yRatio);
|
||||||
glMatrixMode(GL_PROJECTION);
|
gluPerspective(fovYDegrees,(GLfloat)vpWidth/(GLfloat)vpHeight,0.1f,1e5); // use Model 3 viewport ratio
|
||||||
glLoadIdentity();
|
}
|
||||||
gluPerspective(fovYDegrees,(GLfloat)vpWidth/(GLfloat)vpHeight,0.1f,1e5);
|
|
||||||
|
|
||||||
// Lighting (note that sun vector points toward sun -- away from vertex)
|
// Lighting (note that sun vector points toward sun -- away from vertex)
|
||||||
lightingParams[0] = *(float *) &vpnode[0x05]; // sun X
|
lightingParams[0] = *(float *) &vpnode[0x05]; // sun X
|
||||||
|
@ -1034,7 +1059,7 @@ void CRender3D::SetStep(int stepID)
|
||||||
DebugLog("Render3D set to Step %d.%d\n", (step>>4)&0xF, step&0xF);
|
DebugLog("Render3D set to Step %d.%d\n", (step>>4)&0xF, step&0xF);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CRender3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes)
|
bool CRender3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXResParam, unsigned totalYResParam)
|
||||||
{
|
{
|
||||||
// Allocate memory for texture buffer
|
// Allocate memory for texture buffer
|
||||||
textureBuffer = new(std::nothrow) GLfloat[512*512*4];
|
textureBuffer = new(std::nothrow) GLfloat[512*512*4];
|
||||||
|
@ -1074,6 +1099,8 @@ bool CRender3D::Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned
|
||||||
yRatio = (GLfloat) yRes / 384.0f;
|
yRatio = (GLfloat) yRes / 384.0f;
|
||||||
xOffs = xOffset;
|
xOffs = xOffset;
|
||||||
yOffs = yOffset;
|
yOffs = yOffset;
|
||||||
|
totalXRes = totalXResParam;
|
||||||
|
totalYRes = totalYResParam;
|
||||||
|
|
||||||
// Load shaders
|
// Load shaders
|
||||||
const char *vsFile = g_Config.vertexShaderFile.size() ? g_Config.vertexShaderFile.c_str() : NULL;
|
const char *vsFile = g_Config.vertexShaderFile.size() ? g_Config.vertexShaderFile.c_str() : NULL;
|
||||||
|
|
|
@ -263,7 +263,7 @@ public:
|
||||||
void SetStep(int stepID);
|
void SetStep(int stepID);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Init(xOffset, yOffset, xRes, yRes):
|
* Init(xOffset, yOffset, xRes, yRes, totalXRes, totalYRes):
|
||||||
*
|
*
|
||||||
* One-time initialization of the context. Must be called before any other
|
* One-time initialization of the context. Must be called before any other
|
||||||
* members (meaning it should be called even before being attached to any
|
* members (meaning it should be called even before being attached to any
|
||||||
|
@ -272,18 +272,20 @@ public:
|
||||||
* External shader files are loaded according to configuration settings.
|
* External shader files are loaded according to configuration settings.
|
||||||
*
|
*
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* xOffset X offset of display surface in pixels (in case resolution
|
* xOffset X offset of the viewable area within OpenGL display
|
||||||
* is smaller than the true display surface).
|
* surface, in pixels.
|
||||||
* yOffset Y offset.
|
* yOffset Y offset.
|
||||||
* xRes Horizontal resolution of display surface in pixels.
|
* xRes Horizontal resolution of the viewable area.
|
||||||
* yRes Vertical resolution.
|
* yRes Vertical resolution.
|
||||||
|
* totalXRes Horizontal resolution of the complete display area.
|
||||||
|
* totalYRes Vertical resolution.
|
||||||
*
|
*
|
||||||
* Returns:
|
* Returns:
|
||||||
* OKAY is successful, otherwise FAILED if a non-recoverable error
|
* OKAY is successful, otherwise FAILED if a non-recoverable error
|
||||||
* occurred. Any allocated memory will not be freed until the
|
* occurred. Any allocated memory will not be freed until the
|
||||||
* destructor is called. Prints own error messages.
|
* destructor is called. Prints own error messages.
|
||||||
*/
|
*/
|
||||||
bool Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes);
|
bool Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXRes, unsigned totalYRes);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CRender3D(void):
|
* CRender3D(void):
|
||||||
|
@ -375,9 +377,10 @@ private:
|
||||||
GLfloat texOffsetXY[2]; // decoded X, Y offsets
|
GLfloat texOffsetXY[2]; // decoded X, Y offsets
|
||||||
UINT16 texOffset; // raw texture offset data as it appears in culling node
|
UINT16 texOffset; // raw texture offset data as it appears in culling node
|
||||||
|
|
||||||
// Resolution scaling factors (to support resolutions higher than 496x384) and offsets
|
// Resolution and scaling factors (to support resolutions higher than 496x384) and offsets
|
||||||
GLfloat xRatio, yRatio;
|
GLfloat xRatio, yRatio;
|
||||||
unsigned xOffs, yOffs;
|
unsigned xOffs, yOffs;
|
||||||
|
unsigned totalXRes, totalYRes;
|
||||||
|
|
||||||
// Texture ID for complete 2048x2048 texture map
|
// Texture ID for complete 2048x2048 texture map
|
||||||
GLuint texID;
|
GLuint texID;
|
||||||
|
|
|
@ -121,6 +121,7 @@ bool ErrorLog(const char *fmt, ...)
|
||||||
*/
|
*/
|
||||||
unsigned xOffset, yOffset; // offset of renderer output within OpenGL viewport
|
unsigned xOffset, yOffset; // offset of renderer output within OpenGL viewport
|
||||||
unsigned xRes, yRes; // renderer output resolution (can be smaller than GL viewport)
|
unsigned xRes, yRes; // renderer output resolution (can be smaller than GL viewport)
|
||||||
|
unsigned totalXRes, totalYRes; // total resolution (the whole GL viewport)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CreateGLScreen():
|
* CreateGLScreen():
|
||||||
|
@ -128,10 +129,13 @@ unsigned xRes, yRes; // renderer output resolution (can be smaller than GL vi
|
||||||
* Creates an OpenGL display surface of the requested size. xOffset and yOffset
|
* Creates an OpenGL display surface of the requested size. xOffset and yOffset
|
||||||
* are used to return a display surface offset (for OpenGL viewport commands)
|
* are used to return a display surface offset (for OpenGL viewport commands)
|
||||||
* because the actual drawing area may need to be adjusted to preserve the
|
* because the actual drawing area may need to be adjusted to preserve the
|
||||||
* Model 3 aspect ratio. The new resolution will be passed back as well.
|
* Model 3 aspect ratio. The new resolution will be passed back as well -- both
|
||||||
|
* the adjusted viewable area resolution and the total resolution.
|
||||||
|
*
|
||||||
|
* NOTE: keepAspectRatio should always be true. It has not yet been tested with
|
||||||
|
* the wide screen hack.
|
||||||
*/
|
*/
|
||||||
static bool CreateGLScreen(const char *caption, unsigned *xOffsetPtr, unsigned *yOffsetPtr, unsigned *xResPtr, unsigned *yResPtr,
|
static bool CreateGLScreen(const char *caption, unsigned *xOffsetPtr, unsigned *yOffsetPtr, unsigned *xResPtr, unsigned *yResPtr, unsigned *totalXResPtr, unsigned *totalYResPtr, bool keepAspectRatio, bool fullScreen)
|
||||||
bool keepAspectRatio, bool fullScreen)
|
|
||||||
{
|
{
|
||||||
const SDL_VideoInfo *VideoInfo;
|
const SDL_VideoInfo *VideoInfo;
|
||||||
GLenum err;
|
GLenum err;
|
||||||
|
@ -158,6 +162,8 @@ static bool CreateGLScreen(const char *caption, unsigned *xOffsetPtr, unsigned *
|
||||||
|
|
||||||
// What resolution did we actually get?
|
// What resolution did we actually get?
|
||||||
VideoInfo = SDL_GetVideoInfo();
|
VideoInfo = SDL_GetVideoInfo();
|
||||||
|
*totalXResPtr = VideoInfo->current_w;
|
||||||
|
*totalYResPtr = VideoInfo->current_h;
|
||||||
|
|
||||||
// If required, fix the aspect ratio of the resolution that the user passed to match Model 3 ratio
|
// If required, fix the aspect ratio of the resolution that the user passed to match Model 3 ratio
|
||||||
xRes = (float) *xResPtr;
|
xRes = (float) *xResPtr;
|
||||||
|
@ -207,7 +213,7 @@ static bool CreateGLScreen(const char *caption, unsigned *xOffsetPtr, unsigned *
|
||||||
gluPerspective(90.0,(GLfloat)xRes/(GLfloat)yRes,0.1,1e5);
|
gluPerspective(90.0,(GLfloat)xRes/(GLfloat)yRes,0.1,1e5);
|
||||||
glMatrixMode(GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
|
||||||
// Clear the screen to ensure black border
|
// Clear both buffers to ensure a black border
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
|
||||||
|
@ -219,11 +225,14 @@ static bool CreateGLScreen(const char *caption, unsigned *xOffsetPtr, unsigned *
|
||||||
*yResPtr = (unsigned) yRes;
|
*yResPtr = (unsigned) yRes;
|
||||||
|
|
||||||
// Scissor box (to clip visible area)
|
// Scissor box (to clip visible area)
|
||||||
|
if (!g_Config.wideScreen)
|
||||||
|
{
|
||||||
if (VideoInfo->current_w > *xResPtr || VideoInfo->current_h > *yResPtr)
|
if (VideoInfo->current_w > *xResPtr || VideoInfo->current_h > *yResPtr)
|
||||||
{
|
{
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
glScissor(*xOffsetPtr, *yOffsetPtr, *xResPtr, *yResPtr);
|
glScissor(*xOffsetPtr, *yOffsetPtr, *xResPtr, *yResPtr);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -239,11 +248,11 @@ static void PrintGLInfo(bool createScreen, bool infoLog, bool printExtensions)
|
||||||
const GLubyte *str;
|
const GLubyte *str;
|
||||||
char *strLocal;
|
char *strLocal;
|
||||||
GLint value;
|
GLint value;
|
||||||
unsigned xOffset, yOffset, xRes=496, yRes=384;
|
unsigned xOffset, yOffset, xRes=496, yRes=384, totalXRes, totalYRes;
|
||||||
|
|
||||||
if (createScreen)
|
if (createScreen)
|
||||||
{
|
{
|
||||||
if (OKAY != CreateGLScreen("Supermodel - Querying OpenGL Information...",&xOffset,&yOffset,&xRes,&yRes,false,false))
|
if (OKAY != CreateGLScreen("Supermodel - Querying OpenGL Information...",&xOffset,&yOffset,&xRes,&yRes,&totalXRes,&totalYRes,false,false))
|
||||||
{
|
{
|
||||||
ErrorLog("Unable to query OpenGL.\n");
|
ErrorLog("Unable to query OpenGL.\n");
|
||||||
return;
|
return;
|
||||||
|
@ -339,7 +348,7 @@ static bool ConfigureInputs(CInputs *Inputs, bool configure)
|
||||||
{
|
{
|
||||||
// Open an SDL window
|
// Open an SDL window
|
||||||
unsigned xOffset, yOffset, xRes=496, yRes=384;
|
unsigned xOffset, yOffset, xRes=496, yRes=384;
|
||||||
if (OKAY != CreateGLScreen("Supermodel - Configuring Inputs...",&xOffset,&yOffset,&xRes,&yRes,false,false))
|
if (OKAY != CreateGLScreen("Supermodel - Configuring Inputs...",&xOffset,&yOffset,&xRes,&yRes,&totalXRes,&totalYRes,false,false))
|
||||||
return (bool) ErrorLog("Unable to start SDL to configure inputs.\n");
|
return (bool) ErrorLog("Unable to start SDL to configure inputs.\n");
|
||||||
|
|
||||||
// Configure the inputs
|
// Configure the inputs
|
||||||
|
@ -404,6 +413,8 @@ static void ApplySettings(CINIFile *INI, const char *section)
|
||||||
INI->Get(section, "YResolution", g_Config.yRes);
|
INI->Get(section, "YResolution", g_Config.yRes);
|
||||||
if (OKAY == INI->Get(section, "FullScreen", x))
|
if (OKAY == INI->Get(section, "FullScreen", x))
|
||||||
g_Config.fullScreen = x ? true : false;
|
g_Config.fullScreen = x ? true : false;
|
||||||
|
if (OKAY == INI->Get(section, "WideScreen", x))
|
||||||
|
g_Config.wideScreen = x ? true : false;
|
||||||
if (OKAY == INI->Get(section, "Throttle", x))
|
if (OKAY == INI->Get(section, "Throttle", x))
|
||||||
g_Config.throttle = x ? true : false;
|
g_Config.throttle = x ? true : false;
|
||||||
if (OKAY == INI->Get(section, "ShowFrameRate", x))
|
if (OKAY == INI->Get(section, "ShowFrameRate", x))
|
||||||
|
@ -449,6 +460,7 @@ static void LogConfig(void)
|
||||||
InfoLog("\tXResolution = %d", g_Config.xRes);
|
InfoLog("\tXResolution = %d", g_Config.xRes);
|
||||||
InfoLog("\tYResolution = %d", g_Config.yRes);
|
InfoLog("\tYResolution = %d", g_Config.yRes);
|
||||||
InfoLog("\tFullScreen = %d", g_Config.fullScreen);
|
InfoLog("\tFullScreen = %d", g_Config.fullScreen);
|
||||||
|
InfoLog("\tWideScreen = %d", g_Config.wideScreen);
|
||||||
InfoLog("\tThrottle = %d", g_Config.throttle);
|
InfoLog("\tThrottle = %d", g_Config.throttle);
|
||||||
InfoLog("\tShowFrameRate = %d", g_Config.showFPS);
|
InfoLog("\tShowFrameRate = %d", g_Config.showFPS);
|
||||||
#ifdef SUPERMODEL_DEBUGGER
|
#ifdef SUPERMODEL_DEBUGGER
|
||||||
|
@ -745,10 +757,10 @@ int Supermodel(const char *zipFile, CInputs *Inputs, CINIFile *CmdLine)
|
||||||
LoadNVRAM(Model3);
|
LoadNVRAM(Model3);
|
||||||
|
|
||||||
// Start up SDL and open a GL window
|
// Start up SDL and open a GL window
|
||||||
xRes = g_Config.xRes;
|
totalXRes = xRes = g_Config.xRes;
|
||||||
yRes = g_Config.yRes;
|
totalYRes = yRes = g_Config.yRes;
|
||||||
sprintf(baseTitleStr, "Supermodel - %s", Model3->GetGameInfo()->title);
|
sprintf(baseTitleStr, "Supermodel - %s", Model3->GetGameInfo()->title);
|
||||||
if (OKAY != CreateGLScreen(baseTitleStr,&xOffset,&yOffset,&xRes,&yRes,true,g_Config.fullScreen))
|
if (OKAY != CreateGLScreen(baseTitleStr,&xOffset,&yOffset,&xRes,&yRes,&totalXRes,&totalYRes,true,g_Config.fullScreen))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
// Info log GL information and user options
|
// Info log GL information and user options
|
||||||
|
@ -769,9 +781,9 @@ int Supermodel(const char *zipFile, CInputs *Inputs, CINIFile *CmdLine)
|
||||||
Model3->AttachInputs(Inputs);
|
Model3->AttachInputs(Inputs);
|
||||||
|
|
||||||
// Initialize the renderer
|
// Initialize the renderer
|
||||||
if (OKAY != Render2D->Init(xOffset, yOffset, xRes, yRes))
|
if (OKAY != Render2D->Init(xOffset, yOffset, xRes, yRes, totalXRes, totalYRes))
|
||||||
goto QuitError;
|
goto QuitError;
|
||||||
if (OKAY != Render3D->Init(xOffset, yOffset, xRes, yRes))
|
if (OKAY != Render3D->Init(xOffset, yOffset, xRes, yRes, totalXRes, totalYRes))
|
||||||
goto QuitError;
|
goto QuitError;
|
||||||
Model3->AttachRenderers(Render2D,Render3D);
|
Model3->AttachRenderers(Render2D,Render3D);
|
||||||
|
|
||||||
|
@ -1226,6 +1238,7 @@ static void Help(void)
|
||||||
puts("Video Options:");
|
puts("Video Options:");
|
||||||
puts(" -res=<x>,<y> Resolution");
|
puts(" -res=<x>,<y> Resolution");
|
||||||
puts(" -fullscreen Full screen mode");
|
puts(" -fullscreen Full screen mode");
|
||||||
|
puts(" -wide-screen Expand 3D field of view to screen width");
|
||||||
puts(" -no-throttle Disable 60 Hz frame rate lock");
|
puts(" -no-throttle Disable 60 Hz frame rate lock");
|
||||||
puts(" -show-fps Display frame rate in window title bar");
|
puts(" -show-fps Display frame rate in window title bar");
|
||||||
puts(" -vert-shader=<file> Load 3D vertex shader from external file");
|
puts(" -vert-shader=<file> Load 3D vertex shader from external file");
|
||||||
|
@ -1423,6 +1436,11 @@ int main(int argc, char **argv)
|
||||||
n = 1;
|
n = 1;
|
||||||
CmdLine.Set("Global", "FullScreen", n);
|
CmdLine.Set("Global", "FullScreen", n);
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(argv[i],"-wide-screen"))
|
||||||
|
{
|
||||||
|
n = 1;
|
||||||
|
CmdLine.Set("Global", "WideScreen", n);
|
||||||
|
}
|
||||||
else if (!strcmp(argv[i],"-no-throttle"))
|
else if (!strcmp(argv[i],"-no-throttle"))
|
||||||
{
|
{
|
||||||
n = 0;
|
n = 0;
|
||||||
|
|
|
@ -45,6 +45,7 @@ class COSDConfig
|
||||||
public:
|
public:
|
||||||
unsigned xRes, yRes; // X and Y resolution, in pixels
|
unsigned xRes, yRes; // X and Y resolution, in pixels
|
||||||
bool fullScreen; // Full screen mode (if true)
|
bool fullScreen; // Full screen mode (if true)
|
||||||
|
bool wideScreen; // Wide screen hack
|
||||||
bool throttle; // 60 Hz frame limiting
|
bool throttle; // 60 Hz frame limiting
|
||||||
bool showFPS; // Show frame rate
|
bool showFPS; // Show frame rate
|
||||||
bool flipStereo; // Flip stereo channels
|
bool flipStereo; // Flip stereo channels
|
||||||
|
@ -107,6 +108,7 @@ public:
|
||||||
xRes = 496;
|
xRes = 496;
|
||||||
yRes = 384;
|
yRes = 384;
|
||||||
fullScreen = false;
|
fullScreen = false;
|
||||||
|
wideScreen = false;
|
||||||
throttle = true;
|
throttle = true;
|
||||||
showFPS = false;
|
showFPS = false;
|
||||||
flipStereo = false;
|
flipStereo = false;
|
||||||
|
|
Loading…
Reference in a new issue