mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-23 06:15:37 +00:00
183dca563d
- Added 'crosshairs' command line and config option. - Added 'vsync' command line and config option (so far only tested on NVidia cards on Windows 7 - other graphics drivers, O/Ss or driver settings may simply chose to ignore this). - Added fullscreen toggle within game using Alt+Enter key combination. - Added framework for lamp outputs and 'outputs' command line and config option. So far only the lamps for driving games are hooked up in the emulator (others to be added later). - Added an initial outputs implementation for Windows that sends MAMEHooker compatible messages (-outputs=win to enable) - Fixed fps calculation in Main.cpp that was producing incorrect results and so giving the impression that frame throttling wasn't working properly when in fact it was. - Fixed palette indexed colours as the index was always off by one, causing incorrect colours in various games, eg drivers' suits and flashing Start sign in Daytona 2. - Altered caching of models so that models with palette indexed colours use the dynamic cache rather than the static one. This is so that changes in palette indexed colours appear on screen, eg the flashing Start sign on the advanced course of Daytona 2 (although currently the START message itself is not visible due to other problems with texture decoding). - Fixed small bug in TileGen.cpp which meant both palettes were being completely recomputed pretty much with every frame. This was a significant performance hit, particularly as palette recomputation is currently being done in SyncSnapshots (it should be moved out of here at some point, although for now it's no big deal). - Made sure all OpenGL objects and resources are deleted in Render2D/3D destructors, in particular the deleting of the VBO buffer in DestroyModelCache. - Made sure that GLSL uniforms are always checked to see if they are bound before using them in order to stop unecessary (but harmless) GL errors. - Altered the default texture sheet handling to use a single large GL texture holding multiple Model3 texture sheets rather than multiple GL textures as before (if required, the old behaviour can still be selected with the mulisheet fragment shader). I believe this fixes the disappearing crosshairs/corrupt GL state problem which the multisheet fragment shader seemed to be triggering somehow. - Fixed a bug in debugger which meant memory watches were not triggering properly
481 lines
16 KiB
C++
481 lines
16 KiB
C++
/**
|
|
** Supermodel
|
|
** A Sega Model 3 Arcade Emulator.
|
|
** Copyright 2011 Bart Trzynadlowski, Nik Henson
|
|
**
|
|
** This file is part of Supermodel.
|
|
**
|
|
** Supermodel is free software: you can redistribute it and/or modify it under
|
|
** the terms of the GNU General Public License as published by the Free
|
|
** Software Foundation, either version 3 of the License, or (at your option)
|
|
** any later version.
|
|
**
|
|
** Supermodel is distributed in the hope that it will be useful, but WITHOUT
|
|
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
** more details.
|
|
**
|
|
** You should have received a copy of the GNU General Public License along
|
|
** with Supermodel. If not, see <http://www.gnu.org/licenses/>.
|
|
**/
|
|
|
|
/*
|
|
* Render3D.h
|
|
*
|
|
* Header file defining the CRender3D class: OpenGL Real3D graphics engine.
|
|
*/
|
|
|
|
#ifndef INCLUDED_RENDER3D_H
|
|
#define INCLUDED_RENDER3D_H
|
|
|
|
#include "Pkgs/glew.h"
|
|
|
|
/******************************************************************************
|
|
Internal Definitions and Data Structures
|
|
|
|
NOTE: These should probably be moved inside the Render3D namespace at some
|
|
point.
|
|
******************************************************************************/
|
|
|
|
// Model caches sort models by alpha (translucency) state
|
|
enum POLY_STATE
|
|
{
|
|
POLY_STATE_NORMAL = 0,
|
|
POLY_STATE_ALPHA
|
|
};
|
|
|
|
struct Vertex
|
|
{
|
|
GLfloat x,y,z; // vertex
|
|
GLfloat n[3]; // normal X, Y, Z
|
|
GLfloat u,v; // texture U, V coordinates (in texels, relative to selected texture)
|
|
};
|
|
|
|
struct Poly
|
|
{
|
|
Vertex Vert[4];
|
|
GLfloat n[3]; // polygon normal (used for backface culling)
|
|
POLY_STATE state; // alpha or normal?
|
|
unsigned numVerts; // triangle (3) or quad (4)
|
|
const UINT32 *header; // pointer to Real3D 7-word polygon header
|
|
};
|
|
|
|
/*
|
|
* VBORef:
|
|
*
|
|
* Reference to model polygons stored in a VBO. Each reference has two sets of
|
|
* vertices: normal and alpha. Copies of the model with different texture
|
|
* offsets applied are searchable via the linked list of texture offset states.
|
|
*/
|
|
|
|
struct VBORef
|
|
{
|
|
unsigned index[2]; // index of model polygons in VBO
|
|
unsigned numVerts[2]; // number of vertices
|
|
unsigned lutIdx; // LUT index associated with this model (for fast LUT clearing)
|
|
|
|
struct VBORef *nextTexOffset; // linked list of models with different texture offset states
|
|
UINT16 texOffset; // texture offset data for this model
|
|
|
|
CTextureRefs texRefs; // unique texture references contained in this model
|
|
|
|
/*
|
|
* Clear():
|
|
*
|
|
* Clears the VBORef by setting all fields to 0 and clearing the texture
|
|
* references.
|
|
*/
|
|
inline void Clear(void)
|
|
{
|
|
texRefs.Clear();
|
|
lutIdx = 0;
|
|
texOffset = 0;
|
|
nextTexOffset = NULL;
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
index[i] = 0;
|
|
numVerts[i] = 0;
|
|
}
|
|
}
|
|
};
|
|
|
|
// Display list items: model instances and viewport settings
|
|
struct DisplayList
|
|
{
|
|
bool isViewport; // if true, this is a viewport node
|
|
|
|
union
|
|
{
|
|
// Viewport data
|
|
struct
|
|
{
|
|
GLfloat projectionMatrix[4*4]; // projection matrix
|
|
GLfloat lightingParams[6]; // lighting parameters (see RenderViewport() and vertex shader)
|
|
GLfloat spotEllipse[4]; // spotlight ellipse (see RenderViewport())
|
|
GLfloat spotRange[2]; // Z range
|
|
GLfloat spotColor[3]; // color
|
|
GLfloat fogParams[5]; // fog parameters (...)
|
|
GLint x, y; // viewport coordinates (scaled and in OpenGL format)
|
|
GLint width, height; // viewport dimensions (scaled for display surface size)
|
|
} Viewport;
|
|
|
|
// Model data
|
|
struct
|
|
{
|
|
GLfloat modelViewMatrix[4*4]; // model-view matrix
|
|
unsigned index; // index in VBO
|
|
unsigned numVerts; // number of vertices
|
|
GLint frontFace; // GL_CW (default), GL_CCW, or -GL_CW to indicate no culling
|
|
} Model;
|
|
} Data;
|
|
|
|
DisplayList *next; // next display list item with the same state (alpha or non-alpha)
|
|
};
|
|
|
|
/*
|
|
* ModelCache:
|
|
*
|
|
* A model cache tracks all models in a particular region (ie., VROM or polygon
|
|
* RAM). It contains a look-up table to quickly obtain VBO indices. Be careful
|
|
* when accessing the LUT, there are some special cases.
|
|
*
|
|
* If the model cache is marked dynamic, cached models may not necessarily be
|
|
* retained. Clearing the model cache is also much faster. The LUT entry for
|
|
* the last model cached will be valid, but because the LUT may not be
|
|
* cleared, one cannot assume a model exists because there is a LUT entry
|
|
* pointing to it. Always use NeedToCache() to determine whether caching is
|
|
* necessary before reading the LUT!
|
|
*/
|
|
struct ModelCache
|
|
{
|
|
// Cache type
|
|
bool dynamic;
|
|
|
|
// Vertex buffer object
|
|
unsigned vboMaxOffset; // size of VBO (in bytes)
|
|
unsigned vboCurOffset; // current offset in VBO (in bytes)
|
|
GLuint vboID; // OpenGL VBO handle
|
|
|
|
// Local vertex buffers (enough for a single model)
|
|
unsigned maxVertIdx; // size of each local vertex buffer (in vertices)
|
|
unsigned curVertIdx[2]; // current vertex index (in vertices)
|
|
GLfloat *verts[2];
|
|
|
|
// Array of cached models
|
|
unsigned maxModels; // maximum number of models
|
|
unsigned numModels; // current number stored
|
|
VBORef *Models;
|
|
|
|
/*
|
|
* Look-Up Table:
|
|
*
|
|
* Can be accessed directly with a LUT index to determine the model index.
|
|
* However, it should not be used to determine whether a model needs to be
|
|
* cached. Use NeedToCache() instead. A valid index, for example, may still
|
|
* have to be re-cached if the model cache is dynamic (polygon RAM).
|
|
*/
|
|
unsigned lutSize; // number of elements in LUT
|
|
INT16 *lut; // stores indices into Models[] or -1 if not yet cached
|
|
|
|
// Display list
|
|
unsigned maxListSize; // maximum number of display list items
|
|
unsigned listSize; // number of items in display list
|
|
DisplayList *List; // holds all display list items
|
|
DisplayList *ListHead[2]; // heads of linked lists for each state
|
|
DisplayList *ListTail[2]; // current tail node for each state
|
|
};
|
|
|
|
struct TexSheet
|
|
{
|
|
unsigned sheetNum;
|
|
unsigned mapNum;
|
|
unsigned xOffset;
|
|
unsigned yOffset;
|
|
|
|
/*
|
|
* Texture Format Buffer
|
|
*
|
|
* Records the format that a texture (at a given location within the
|
|
* texture sheet) is currently stored in. A negative value indicates the
|
|
* texture has not been accessed and converted yet and non-negative values
|
|
* correspond to the texture format bits in the polygon headers. They can
|
|
* be used to determine whether a texture needs to be updated.
|
|
*/
|
|
int texWidth[2048/32][2048/32];
|
|
int texHeight[2048/32][2048/32];
|
|
INT8 texFormat[2048/32][2048/32];
|
|
};
|
|
|
|
/******************************************************************************
|
|
CRender3D Classes
|
|
******************************************************************************/
|
|
|
|
/*
|
|
* CRender3DConfig:
|
|
*
|
|
* Settings used by CRender3D.
|
|
*/
|
|
class CRender3DConfig
|
|
{
|
|
public:
|
|
string vertexShaderFile; // path to vertex shader or "" to use internal shader
|
|
string fragmentShaderFile; // fragment shader
|
|
unsigned maxTexMaps; // maximum number of texture maps to use (1-9)
|
|
unsigned maxTexMapExtent; // maximum extent of texture maps (where num of tex sheets per map = extent ^ 2)
|
|
bool multiTexture; // if enabled and no external fragment shader, select internal shader w/ multiple texture sheet support
|
|
|
|
// Defaults
|
|
CRender3DConfig(void)
|
|
{
|
|
// strings will be clear to begin with
|
|
maxTexMaps = 9;
|
|
maxTexMapExtent = 4;
|
|
multiTexture = false;
|
|
}
|
|
};
|
|
|
|
/*
|
|
* CRender3D:
|
|
*
|
|
* 3D renderer. Lots of work to do here :)
|
|
*/
|
|
class CRender3D
|
|
{
|
|
friend class CTextureRefs;
|
|
|
|
public:
|
|
/*
|
|
* RenderFrame(void):
|
|
*
|
|
* Renders the complete scene database. Must be called between BeginFrame() and
|
|
* EndFrame(). This function traverses the scene database and builds up display
|
|
* lists.
|
|
*/
|
|
void RenderFrame(void);
|
|
|
|
/*
|
|
* BeginFrame(void):
|
|
*
|
|
* Prepare to render a new frame. Must be called once per frame prior to
|
|
* drawing anything.
|
|
*/
|
|
void BeginFrame(void);
|
|
|
|
/*
|
|
* EndFrame(void):
|
|
*
|
|
* Signals the end of rendering for this frame. Must be called last during
|
|
* the frame.
|
|
*/
|
|
void EndFrame(void);
|
|
|
|
/*
|
|
* UploadTextures(x, y, width, height):
|
|
*
|
|
* Signals that a portion of texture RAM has been updated.
|
|
*
|
|
* Parameters:
|
|
* x X position within texture RAM.
|
|
* y Y position within texture RAM.
|
|
* width Width of texture data in texels.
|
|
* height Height.
|
|
*/
|
|
void UploadTextures(unsigned x, unsigned y, unsigned width, unsigned height);
|
|
|
|
/*
|
|
* AttachMemory(cullingRAMLoPtr, cullingRAMHiPtr, polyRAMPtr, vromPtr,
|
|
* textureRAMPtr):
|
|
*
|
|
* Attaches RAM and ROM areas. This must be done prior to any rendering
|
|
* otherwise the program may crash with an access violation.
|
|
*
|
|
* Parameters:
|
|
* cullingRAMLoPtr Pointer to low culling RAM (4 MB).
|
|
* cullingRAMHiPtr Pointer to high culling RAM (1 MB).
|
|
* polyRAMPtr Pointer to polygon RAM (4 MB).
|
|
* vromPtr Pointer to video ROM (64 MB).
|
|
* textureRAMPtr Pointer to texture RAM (8 MB).
|
|
*/
|
|
void AttachMemory(const UINT32 *cullingRAMLoPtr,
|
|
const UINT32 *cullingRAMHiPtr, const UINT32 *polyRAMPtr,
|
|
const UINT32 *vromPtr, const UINT16 *textureRAMPtr);
|
|
|
|
/*
|
|
* SetStep(stepID):
|
|
*
|
|
* Sets the Model 3 hardware stepping, which also determines the Real3D
|
|
* functionality. The default is Step 1.0. This should be called prior to
|
|
* any other emulation functions and after Init().
|
|
*
|
|
* Parameters:
|
|
* stepID 0x10 for Step 1.0, 0x15 for Step 1.5, 0x20 for Step 2.0,
|
|
* or 0x21 for Step 2.1. Anything else defaults to 1.0.
|
|
*/
|
|
void SetStep(int stepID);
|
|
|
|
/*
|
|
* Init(xOffset, yOffset, xRes, yRes, totalXRes, totalYRes):
|
|
*
|
|
* One-time initialization of the context. Must be called before any other
|
|
* members (meaning it should be called even before being attached to any
|
|
* other objects that want to use it).
|
|
*
|
|
* External shader files are loaded according to configuration settings.
|
|
*
|
|
* Parameters:
|
|
* xOffset X offset of the viewable area within OpenGL display
|
|
* surface, in pixels.
|
|
* yOffset Y offset.
|
|
* xRes Horizontal resolution of the viewable area.
|
|
* yRes Vertical resolution.
|
|
* totalXRes Horizontal resolution of the complete display area.
|
|
* totalYRes Vertical resolution.
|
|
*
|
|
* Returns:
|
|
* OKAY is successful, otherwise FAILED if a non-recoverable error
|
|
* occurred. Any allocated memory will not be freed until the
|
|
* destructor is called. Prints own error messages.
|
|
*/
|
|
bool Init(unsigned xOffset, unsigned yOffset, unsigned xRes, unsigned yRes, unsigned totalXRes, unsigned totalYRes);
|
|
|
|
/*
|
|
* CRender3D(void):
|
|
* ~CRender3D(void):
|
|
*
|
|
* Constructor and destructor.
|
|
*/
|
|
CRender3D(void);
|
|
~CRender3D(void);
|
|
|
|
private:
|
|
/*
|
|
* Private Members
|
|
*/
|
|
|
|
// Real3D address translation
|
|
const UINT32 *TranslateCullingAddress(UINT32 addr);
|
|
const UINT32 *TranslateModelAddress(UINT32 addr);
|
|
|
|
// Model caching and display list management
|
|
void DrawDisplayList(ModelCache *Cache, POLY_STATE state);
|
|
bool AppendDisplayList(ModelCache *Cache, bool isViewport, const struct VBORef *Model);
|
|
void ClearDisplayList(ModelCache *Cache);
|
|
bool InsertPolygon(ModelCache *cache, const Poly *p);
|
|
void InsertVertex(ModelCache *cache, const Vertex *v, const Poly *p, float normFlip);
|
|
struct VBORef *BeginModel(ModelCache *cache);
|
|
void EndModel(ModelCache *cache, struct VBORef *Model, int lutIdx, UINT16 texOffset);
|
|
struct VBORef *CacheModel(ModelCache *cache, int lutIdx, UINT16 texOffset, const UINT32 *data);
|
|
struct VBORef *LookUpModel(ModelCache *cache, int lutIdx, UINT16 texOffset);
|
|
void ClearModelCache(ModelCache *cache);
|
|
bool CreateModelCache(ModelCache *cache, unsigned vboMaxVerts, unsigned localMaxVerts, unsigned maxNumModels, unsigned numLUTEntries, unsigned displayListSize, bool isDynamic);
|
|
void DestroyModelCache(ModelCache *cache);
|
|
|
|
// Texture management
|
|
void DecodeTexture(int format, int x, int y, int width, int height);
|
|
|
|
// Matrix stack
|
|
void MultMatrix(UINT32 matrixOffset);
|
|
void InitMatrixStack(UINT32 matrixBaseAddr);
|
|
|
|
// Scene database traversal
|
|
bool DrawModel(UINT32 modelAddr);
|
|
void DescendCullingNode(UINT32 addr);
|
|
void DescendPointerList(UINT32 addr);
|
|
void DescendNodePtr(UINT32 nodeAddr);
|
|
void RenderViewport(UINT32 addr, int pri);
|
|
|
|
// In-frame error reporting
|
|
bool ErrorLocalVertexOverflow(void);
|
|
bool ErrorUnableToCacheModel(UINT32 modelAddr);
|
|
void ClearErrors(void);
|
|
|
|
/*
|
|
* Data
|
|
*/
|
|
|
|
// Stepping
|
|
int step;
|
|
int offset; // offset to subtract for words 3 and higher of culling nodes
|
|
GLfloat vertexFactor; // fixed-point conversion factor for vertices
|
|
|
|
// Memory (passed from outside)
|
|
const UINT32 *cullingRAMLo; // 4 MB
|
|
const UINT32 *cullingRAMHi; // 1 MB
|
|
const UINT32 *polyRAM; // 4 MB
|
|
const UINT32 *vrom; // 64 MB
|
|
const UINT16 *textureRAM; // 8 MB
|
|
|
|
// Error reporting
|
|
unsigned errorMsgFlags; // tracks which errors have been printed this frame
|
|
|
|
// Real3D Base Matrix Pointer
|
|
const float *matrixBasePtr;
|
|
|
|
// Current viewport parameters (updated as viewports are traversed)
|
|
GLfloat lightingParams[6];
|
|
GLfloat fogParams[5];
|
|
GLfloat spotEllipse[4];
|
|
GLfloat spotRange[2];
|
|
GLfloat spotColor[3];
|
|
GLint viewportX, viewportY;
|
|
GLint viewportWidth, viewportHeight;
|
|
|
|
// Scene graph stack
|
|
int listDepth; // how many lists have we recursed into
|
|
int stackDepth; // for debugging and error handling purposes
|
|
|
|
// Texture offset (during scene graph processing)
|
|
GLfloat texOffsetXY[2]; // decoded X, Y offsets
|
|
UINT16 texOffset; // raw texture offset data as it appears in culling node
|
|
|
|
// Resolution and scaling factors (to support resolutions higher than 496x384) and offsets
|
|
GLfloat xRatio, yRatio;
|
|
unsigned xOffs, yOffs;
|
|
unsigned totalXRes, totalYRes;
|
|
|
|
// Texture details
|
|
static int defaultFmtToTexSheetNum[8]; // default mapping from Model3 texture format to texture sheet
|
|
unsigned numTexMaps; // total number of texture maps
|
|
GLuint texMapIDs[9]; // GL texture IDs of texture maps
|
|
unsigned numTexSheets; // total number of texture sheets
|
|
TexSheet *texSheets; // texture sheet objects
|
|
TexSheet *fmtToTexSheet[8]; // final mapping from Model3 texture format to texture sheet
|
|
|
|
// Shader programs and input data locations
|
|
GLuint shaderProgram; // shader program object
|
|
GLuint vertexShader; // vertex shader handle
|
|
GLuint fragmentShader; // fragment shader
|
|
GLint textureMapLoc; // location of "textureMap" uniform (if available)
|
|
GLint textureMapLocs[8]; // location of "textureMap[0-7]" uniforms (if available)
|
|
GLint modelViewMatrixLoc; // uniform
|
|
GLint projectionMatrixLoc; // uniform
|
|
GLint lightingLoc; // uniform
|
|
GLint mapSizeLoc; // uniform
|
|
GLint spotEllipseLoc; // uniform
|
|
GLint spotRangeLoc; // uniform
|
|
GLint spotColorLoc; // uniform
|
|
GLint subTextureLoc; // attribute
|
|
GLint texParamsLoc; // attribute
|
|
GLint texFormatLoc; // attribute
|
|
GLint texMapLoc; // attribute
|
|
GLint transLevelLoc; // attribute
|
|
GLint lightEnableLoc; // attribute
|
|
GLint shininessLoc; // attribute
|
|
GLint fogIntensityLoc; // attribute
|
|
|
|
// Model caching
|
|
ModelCache VROMCache; // VROM (static) models
|
|
ModelCache PolyCache; // polygon RAM (dynamic) models
|
|
|
|
/*
|
|
* Texture Decode Buffer
|
|
*
|
|
* Textures are decoded and copied from texture RAM into this temporary buffer
|
|
* before being uploaded. Dimensions are 512x512.
|
|
*/
|
|
GLfloat *textureBuffer; // RGBA8 format
|
|
};
|
|
|
|
|
|
#endif // INCLUDED_RENDER3D_H
|