mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-23 06:15:37 +00:00
6595b9320e
Some games update the tilegen after the ping_ping bit has flipped at 66% of the frame, so we need to split the tilegen drawing up into two stages to get some effects to work. So having the tilegen draw independantly of the 3d chip can make this happen.
319 lines
9.4 KiB
C++
319 lines
9.4 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/>.
|
|
**/
|
|
|
|
/*
|
|
* New3D.h
|
|
*
|
|
* Header file defining the CNew3D class: OpenGL Real3D graphics engine.
|
|
*/
|
|
|
|
#ifndef INCLUDED_NEW3D_H
|
|
#define INCLUDED_NEW3D_H
|
|
|
|
#include <GL/glew.h>
|
|
#include "Types.h"
|
|
#include "Graphics/IRender3D.h"
|
|
#include "Model.h"
|
|
#include "Mat4.h"
|
|
#include "R3DShader.h"
|
|
#include "VBO.h"
|
|
#include "R3DData.h"
|
|
#include "Plane.h"
|
|
#include "Vec.h"
|
|
#include "R3DScrollFog.h"
|
|
#include "PolyHeader.h"
|
|
#include "R3DFrameBuffers.h"
|
|
#include <mutex>
|
|
|
|
namespace New3D {
|
|
|
|
class CNew3D : public IRender3D
|
|
{
|
|
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 level, 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);
|
|
|
|
/*
|
|
* SetStepping(stepping):
|
|
*
|
|
* 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:
|
|
* stepping 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 SetStepping(int stepping);
|
|
|
|
/*
|
|
* 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);
|
|
|
|
/*
|
|
* SetSunClamp(bool enable);
|
|
*
|
|
* Sets or unsets the clamped light model
|
|
*
|
|
* Parameters:
|
|
* enable Set clamp mode
|
|
*/
|
|
void SetSunClamp(bool enable);
|
|
|
|
/*
|
|
* SetSignedShade(bool enable);
|
|
*
|
|
* Sets the sign-ness of fixed shading value
|
|
*
|
|
* Parameters:
|
|
* enable Fixed shading is expressed as signed value
|
|
*/
|
|
void SetSignedShade(bool enable);
|
|
|
|
/*
|
|
* GetLosValue(int layer);
|
|
*
|
|
* Gets the line of sight value for the priority layer
|
|
*
|
|
* Parameters:
|
|
* layer Priority layer to read from
|
|
*/
|
|
float GetLosValue(int layer);
|
|
|
|
/*
|
|
* CRender3D(config):
|
|
* ~CRender3D(void):
|
|
*
|
|
* Constructor and destructor.
|
|
*
|
|
* Parameters:
|
|
* config Run-time configuration.
|
|
*/
|
|
CNew3D(const Util::Config::Node &config, const std::string& gameName);
|
|
~CNew3D(void);
|
|
|
|
private:
|
|
/*
|
|
* Private Members
|
|
*/
|
|
|
|
// Real3D address translation
|
|
const UINT32 *TranslateCullingAddress(UINT32 addr);
|
|
const UINT32 *TranslateModelAddress(UINT32 addr);
|
|
|
|
// Matrix stack
|
|
void MultMatrix(UINT32 matrixOffset, Mat4& mat);
|
|
void InitMatrixStack(UINT32 matrixBaseAddr, Mat4& mat);
|
|
void ResetMatrix(Mat4& mat);
|
|
|
|
// Scene database traversal
|
|
bool DrawModel(UINT32 modelAddr);
|
|
void DescendCullingNode(UINT32 addr);
|
|
void DescendPointerList(UINT32 addr);
|
|
void DescendNodePtr(UINT32 nodeAddr);
|
|
void RenderViewport(UINT32 addr);
|
|
|
|
// building the scene
|
|
int GetTexFormat(int originalFormat, bool contour);
|
|
void SetMeshValues(SortingMesh *currentMesh, PolyHeader &ph);
|
|
void CacheModel(Model *m, const UINT32 *data);
|
|
void CopyVertexData(const R3DPoly& r3dPoly, std::vector<FVertex>& vertexArray);
|
|
void GetCoordinates(int width, int height, UINT16 uIn, UINT16 vIn, float uvScale, float& uOut, float& vOut);
|
|
|
|
bool RenderScene(int priority, bool renderOverlay, Layer layer); // returns if has overlay plane
|
|
bool IsDynamicModel(UINT32 *data); // check if the model has a colour palette
|
|
bool IsVROMModel(UINT32 modelAddr);
|
|
void DrawScrollFog();
|
|
bool SkipLayer(int layer);
|
|
void SetRenderStates();
|
|
void DisableRenderStates();
|
|
void TranslateLosPosition(int inX, int inY, int& outX, int& outY);
|
|
bool ProcessLos(int priority);
|
|
|
|
/*
|
|
* Data
|
|
*/
|
|
|
|
// Misc
|
|
std::string m_gameName;
|
|
int m_numPolyVerts;
|
|
GLenum m_primType;
|
|
|
|
// GPU configuration
|
|
bool m_sunClamp;
|
|
bool m_shadeIsSigned;
|
|
|
|
// Stepping
|
|
int m_step;
|
|
int m_offset; // offset to subtract for words 3 and higher of culling nodes
|
|
float m_vertexFactor; // fixed-point conversion factor for vertices
|
|
|
|
// Memory (passed from outside)
|
|
const UINT32 *m_cullingRAMLo; // 4 MB
|
|
const UINT32 *m_cullingRAMHi; // 1 MB
|
|
const UINT32 *m_polyRAM; // 4 MB
|
|
const UINT32 *m_vrom; // 64 MB
|
|
const UINT16 *m_textureRAM; // 8 MB
|
|
|
|
// Resolution and scaling factors (to support resolutions higher than 496x384) and offsets
|
|
float m_xRatio, m_yRatio;
|
|
unsigned m_xOffs, m_yOffs;
|
|
unsigned m_xRes, m_yRes; // resolution of Model 3's 496x384 display area within the window
|
|
unsigned m_totalXRes, m_totalYRes; // total OpenGL window resolution
|
|
|
|
// Real3D Base Matrix Pointer
|
|
const float *m_matrixBasePtr;
|
|
UINT32 m_colorTableAddr = 0x400; // address of color table in polygon RAM
|
|
LODBlendTable* m_LODBlendTable;
|
|
|
|
GLuint m_textureBuffer;
|
|
NodeAttributes m_nodeAttribs;
|
|
Mat4 m_modelMat; // current modelview matrix
|
|
|
|
struct LOS
|
|
{
|
|
float value[4] = { 0,0,0,0 }; // line of sight value for each priority layer
|
|
} m_los[2];
|
|
|
|
LOS* m_losFront = &m_los[0]; // we need to double buffer this because 3d works in separate thread
|
|
LOS* m_losBack = &m_los[1];
|
|
std::mutex m_losMutex;
|
|
|
|
Vertex m_prev[4]; // these are class variables because sega bass fishing starts meshes with shared vertices from the previous one
|
|
UINT16 m_prevTexCoords[4][2]; // basically relying on undefined behavour
|
|
|
|
std::vector<Node> m_nodes; // this represents the entire render frame
|
|
std::vector<FVertex> m_polyBufferRam; // dynamic polys
|
|
std::vector<FVertex> m_polyBufferRom; // rom polys
|
|
std::unordered_map<UINT32, std::shared_ptr<std::vector<Mesh>>> m_romMap; // a hash table for all the ROM models. The meshes don't have model matrices or tex offsets yet
|
|
|
|
GLuint m_vao;
|
|
VBO m_vbo; // large VBO to hold our poly data, start of VBO is ROM data, ram polys follow
|
|
R3DShader m_r3dShader;
|
|
R3DScrollFog m_r3dScrollFog;
|
|
R3DFrameBuffers m_r3dFrameBuffers;
|
|
|
|
Plane m_planes[5];
|
|
|
|
struct BBox
|
|
{
|
|
V4::Vec4 points[8];
|
|
};
|
|
|
|
struct NFPair
|
|
{
|
|
float zNear;
|
|
float zFar;
|
|
};
|
|
|
|
NFPair m_nfPairs[4];
|
|
int m_currentPriority;
|
|
|
|
void CalcFrustumPlanes (Plane p[5], const float* matrix);
|
|
void CalcBox (float distance, BBox& box);
|
|
void TransformBox (const float *m, BBox& box);
|
|
void MultVec (const float matrix[16], const float in[4], float out[4]);
|
|
Clip ClipBox (const BBox& box, Plane planes[5]);
|
|
void ClipModel (const Model *m);
|
|
void ClipPolygon (ClipPoly& clipPoly, Plane planes[5]);
|
|
void CalcBoxExtents (const BBox& box);
|
|
void CalcViewport (Viewport* vp, float near, float far);
|
|
};
|
|
|
|
} // New3D
|
|
|
|
#endif // INCLUDED_NEW3D_H
|