mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2025-04-10 19:15:14 +00:00
Legacy engine: fixed texture offsets (VON2 was broken by last commit). Texture coordinates are wrapped within the bank first and then the bank can be swapped. This also allows the full range of texture coordinate bits to be used as specified in the Pro-1000 SDK.
This commit is contained in:
parent
36074d9fd5
commit
9a49fefe12
|
@ -583,8 +583,7 @@ static bool IsDynamicModel(const UINT32 *data)
|
||||||
* made to salvage the situation if this occurs, so if DrawModel() returns
|
* made to salvage the situation if this occurs, so if DrawModel() returns
|
||||||
* FAIL, it is a serious matter and rendering should be aborted for the frame.
|
* FAIL, it is a serious matter and rendering should be aborted for the frame.
|
||||||
*
|
*
|
||||||
* The current texture offset state, texOffset, is also used. Models are cached
|
* Models are cached for each unique culling node texture offset state.
|
||||||
* for each unique texOffset.
|
|
||||||
*/
|
*/
|
||||||
bool CLegacy3D::DrawModel(UINT32 modelAddr)
|
bool CLegacy3D::DrawModel(UINT32 modelAddr)
|
||||||
{
|
{
|
||||||
|
@ -599,12 +598,12 @@ bool CLegacy3D::DrawModel(UINT32 modelAddr)
|
||||||
|
|
||||||
// Look up the model in the LUT and cache it if necessary
|
// Look up the model in the LUT and cache it if necessary
|
||||||
int lutIdx = modelAddr&0xFFFFFF;
|
int lutIdx = modelAddr&0xFFFFFF;
|
||||||
struct VBORef *ModelRef = LookUpModel(Cache, lutIdx, texOffset);
|
struct VBORef *ModelRef = LookUpModel(Cache, lutIdx, m_textureOffset.state);
|
||||||
if (NULL == ModelRef && Cache == &VROMCache)
|
if (NULL == ModelRef && Cache == &VROMCache)
|
||||||
{
|
{
|
||||||
// If the model was a VROM model, it may be dynamic, so we need to try
|
// If the model was a VROM model, it may be dynamic, so we need to try
|
||||||
// another lookup in the dynamic cache
|
// another lookup in the dynamic cache
|
||||||
ModelRef = LookUpModel(&PolyCache, lutIdx, texOffset);
|
ModelRef = LookUpModel(&PolyCache, lutIdx, m_textureOffset.state);
|
||||||
if (ModelRef != NULL)
|
if (ModelRef != NULL)
|
||||||
Cache = &PolyCache;
|
Cache = &PolyCache;
|
||||||
}
|
}
|
||||||
|
@ -617,7 +616,7 @@ bool CLegacy3D::DrawModel(UINT32 modelAddr)
|
||||||
// afterwards)
|
// afterwards)
|
||||||
if (Cache == &VROMCache && IsDynamicModel(model))
|
if (Cache == &VROMCache && IsDynamicModel(model))
|
||||||
Cache = &PolyCache;
|
Cache = &PolyCache;
|
||||||
ModelRef = CacheModel(Cache, lutIdx, texOffset, model);
|
ModelRef = CacheModel(Cache, lutIdx, m_textureOffset.state, model);
|
||||||
if (NULL == ModelRef)
|
if (NULL == ModelRef)
|
||||||
{
|
{
|
||||||
// Model could not be cached. Render what we have so far and try again.
|
// Model could not be cached. Render what we have so far and try again.
|
||||||
|
@ -629,7 +628,7 @@ bool CLegacy3D::DrawModel(UINT32 modelAddr)
|
||||||
ClearModelCache(&PolyCache);
|
ClearModelCache(&PolyCache);
|
||||||
|
|
||||||
// Try caching again...
|
// Try caching again...
|
||||||
ModelRef = CacheModel(Cache, lutIdx, texOffset, model);
|
ModelRef = CacheModel(Cache, lutIdx, m_textureOffset.state, model);
|
||||||
if (NULL == ModelRef)
|
if (NULL == ModelRef)
|
||||||
return ErrorUnableToCacheModel(modelAddr); // nothing we can do :(
|
return ErrorUnableToCacheModel(modelAddr); // nothing we can do :(
|
||||||
}
|
}
|
||||||
|
@ -686,20 +685,11 @@ void CLegacy3D::DescendCullingNode(UINT32 addr)
|
||||||
const float z = *(float *) &node[0x06-offset];
|
const float z = *(float *) &node[0x06-offset];
|
||||||
|
|
||||||
// Texture offset?
|
// Texture offset?
|
||||||
const float oldTexOffsetX = texOffsetXY[0]; // save old offsets
|
TextureOffset oldTextureOffset = m_textureOffset; // save old offsets
|
||||||
const float oldTexOffsetY = texOffsetXY[1];
|
|
||||||
const UINT16 oldTexOffset = texOffset;
|
|
||||||
if (!offset) // Step 1.5+
|
if (!offset) // Step 1.5+
|
||||||
{
|
{
|
||||||
int tx = 32*((node[0x02]>>7)&0x3F);
|
if ((node[0x02] & 0x8000)) // apply texture offset, else retain current ones
|
||||||
int ty = 32*(node[0x02]&0x1F) + ((node[0x02]&0x4000)?1024:0); // 5 bits for Y coordinate, else Sega Rally 2 initials decal breaks
|
m_textureOffset = TextureOffset(node[0x02]);
|
||||||
if ((node[0x02]&0x8000)) // apply texture offsets, else retain current ones
|
|
||||||
{
|
|
||||||
texOffsetXY[0] = (GLfloat) tx;
|
|
||||||
texOffsetXY[1] = (GLfloat) ty;
|
|
||||||
texOffset = node[0x02]&0x7FFF;
|
|
||||||
//printf("Tex Offset: %d, %d (%08X %08X)\n", tx, ty, node[0x02], node1Ptr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply matrix and translation
|
// Apply matrix and translation
|
||||||
|
@ -731,9 +721,7 @@ void CLegacy3D::DescendCullingNode(UINT32 addr)
|
||||||
--stackDepth;
|
--stackDepth;
|
||||||
|
|
||||||
// Restore old texture offsets
|
// Restore old texture offsets
|
||||||
texOffsetXY[0] = oldTexOffsetX;
|
m_textureOffset = oldTextureOffset;
|
||||||
texOffsetXY[1] = oldTexOffsetY;
|
|
||||||
texOffset = oldTexOffset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A list of pointers. MAME assumes that these may only point to culling nodes.
|
// A list of pointers. MAME assumes that these may only point to culling nodes.
|
||||||
|
@ -929,9 +917,7 @@ void CLegacy3D::RenderViewport(UINT32 addr, int pri)
|
||||||
//printf("Fog: R=%02X G=%02X B=%02X density=%g (%X) %d start=%g\n", ((vpnode[0x22]>>16)&0xFF), ((vpnode[0x22]>>8)&0xFF), ((vpnode[0x22]>>0)&0xFF), fogParams[3], vpnode[0x23], (fogParams[3]==fogParams[3]), fogParams[4]);
|
//printf("Fog: R=%02X G=%02X B=%02X density=%g (%X) %d start=%g\n", ((vpnode[0x22]>>16)&0xFF), ((vpnode[0x22]>>8)&0xFF), ((vpnode[0x22]>>0)&0xFF), fogParams[3], vpnode[0x23], (fogParams[3]==fogParams[3]), fogParams[4]);
|
||||||
|
|
||||||
// Clear texture offsets before proceeding
|
// Clear texture offsets before proceeding
|
||||||
texOffsetXY[0] = 0.0;
|
m_textureOffset = TextureOffset();
|
||||||
texOffsetXY[1] = 0.0;
|
|
||||||
texOffset = 0x0000;
|
|
||||||
|
|
||||||
// Set up coordinate system and base matrix
|
// Set up coordinate system and base matrix
|
||||||
UINT32 matrixBase = vpnode[0x16] & 0xFFFFFF;
|
UINT32 matrixBase = vpnode[0x16] & 0xFFFFFF;
|
||||||
|
|
|
@ -83,9 +83,9 @@ struct VBORef
|
||||||
unsigned numVerts[2]; // number of vertices
|
unsigned numVerts[2]; // number of vertices
|
||||||
unsigned lutIdx; // LUT index associated with this model (for fast LUT clearing)
|
unsigned lutIdx; // LUT index associated with this model (for fast LUT clearing)
|
||||||
|
|
||||||
struct VBORef *nextTexOffset; // linked list of models with different texture offset states
|
VBORef *nextTextureOffsetState; // linked list of models with different texture offset states
|
||||||
UINT16 texOffset; // texture offset data for this model
|
uint16_t textureOffsetState; // texture offset data for this model
|
||||||
bool useStencil; // whether to draw with stencil mask ("layered" polygons)
|
bool useStencil; // whether to draw with stencil mask ("layered" polygons)
|
||||||
|
|
||||||
CTextureRefs texRefs; // unique texture references contained in this model
|
CTextureRefs texRefs; // unique texture references contained in this model
|
||||||
|
|
||||||
|
@ -99,8 +99,8 @@ struct VBORef
|
||||||
{
|
{
|
||||||
texRefs.Clear();
|
texRefs.Clear();
|
||||||
lutIdx = 0;
|
lutIdx = 0;
|
||||||
texOffset = 0;
|
textureOffsetState = 0;
|
||||||
nextTexOffset = NULL;
|
nextTextureOffsetState = NULL;
|
||||||
useStencil = false;
|
useStencil = false;
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
|
@ -378,9 +378,9 @@ private:
|
||||||
bool InsertPolygon(ModelCache *cache, const Poly *p);
|
bool InsertPolygon(ModelCache *cache, const Poly *p);
|
||||||
void InsertVertex(ModelCache *cache, const Vertex *v, const Poly *p, float normFlip);
|
void InsertVertex(ModelCache *cache, const Vertex *v, const Poly *p, float normFlip);
|
||||||
struct VBORef *BeginModel(ModelCache *cache);
|
struct VBORef *BeginModel(ModelCache *cache);
|
||||||
void EndModel(ModelCache *cache, struct VBORef *Model, int lutIdx, UINT16 texOffset, bool useStencil);
|
void EndModel(ModelCache *cache, struct VBORef *Model, int lutIdx, UINT16 textureOffsetState, bool useStencil);
|
||||||
struct VBORef *CacheModel(ModelCache *cache, int lutIdx, UINT16 texOffset, const UINT32 *data);
|
struct VBORef *CacheModel(ModelCache *cache, int lutIdx, UINT16 textureOffsetState, const UINT32 *data);
|
||||||
struct VBORef *LookUpModel(ModelCache *cache, int lutIdx, UINT16 texOffset);
|
struct VBORef *LookUpModel(ModelCache *cache, int lutIdx, UINT16 textureOffsetState);
|
||||||
void ClearModelCache(ModelCache *cache);
|
void ClearModelCache(ModelCache *cache);
|
||||||
bool CreateModelCache(ModelCache *cache, unsigned vboMaxVerts, unsigned localMaxVerts, unsigned maxNumModels, unsigned numLUTEntries, unsigned displayListSize, bool isDynamic);
|
bool CreateModelCache(ModelCache *cache, unsigned vboMaxVerts, unsigned localMaxVerts, unsigned maxNumModels, unsigned numLUTEntries, unsigned displayListSize, bool isDynamic);
|
||||||
void DestroyModelCache(ModelCache *cache);
|
void DestroyModelCache(ModelCache *cache);
|
||||||
|
@ -438,8 +438,25 @@ private:
|
||||||
// Scene graph processing
|
// Scene graph processing
|
||||||
int listDepth; // how many lists have we recursed into
|
int listDepth; // how many lists have we recursed into
|
||||||
int stackDepth; // for debugging and error handling purposes
|
int stackDepth; // for debugging and error handling purposes
|
||||||
GLfloat texOffsetXY[2]; // decoded texture X, Y offsets
|
struct TextureOffset
|
||||||
UINT16 texOffset; // raw texture offset data as it appears in culling node
|
{
|
||||||
|
int x; // x offset
|
||||||
|
int y; // y offset (wraps within 2048x1023 texel bank)
|
||||||
|
int switchBank; // 0: use bank from polygon header, 1024: swap banks
|
||||||
|
uint16_t state; // x, y, and bank states compromise a unique key
|
||||||
|
TextureOffset(uint32_t data)
|
||||||
|
: x(32 * ((data >> 7) & 0x7F)),
|
||||||
|
y(32 * (data & 0x7F)),
|
||||||
|
switchBank((data & 0x4000) >> 4),
|
||||||
|
state(data & 0x7FFF)
|
||||||
|
{}
|
||||||
|
TextureOffset()
|
||||||
|
: x(0),
|
||||||
|
y(0),
|
||||||
|
switchBank(false),
|
||||||
|
state(0)
|
||||||
|
{}
|
||||||
|
} m_textureOffset;
|
||||||
UINT32 m_colorTableAddr = 0x400; // address of color table in polygon RAM
|
UINT32 m_colorTableAddr = 0x400; // address of color table in polygon RAM
|
||||||
|
|
||||||
// Resolution and scaling factors (to support resolutions higher than 496x384) and offsets
|
// Resolution and scaling factors (to support resolutions higher than 496x384) and offsets
|
||||||
|
|
|
@ -453,15 +453,15 @@ void CLegacy3D::ClearDisplayList(ModelCache *Cache)
|
||||||
|
|
||||||
int CLegacy3D::GetTextureBaseX(const Poly *P) const
|
int CLegacy3D::GetTextureBaseX(const Poly *P) const
|
||||||
{
|
{
|
||||||
int x = ((P->header[4] & 0x1F) << 1) | ((P->header[5] >> 7) & 1);
|
int x = 32 * (((P->header[4] & 0x7F) << 1) | ((P->header[5] >> 7) & 1));
|
||||||
return (32 * x + int(texOffsetXY[0])) & 2047;
|
return (x + m_textureOffset.x) & 2047;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CLegacy3D::GetTextureBaseY(const Poly *P) const
|
int CLegacy3D::GetTextureBaseY(const Poly *P) const
|
||||||
{
|
{
|
||||||
int texPage = (P->header[4] & 0x40) << 4; // 1024 or 0
|
int y = 32 * (P->header[5] & 0x7F);
|
||||||
int y = P->header[5] & 0x1F;
|
int bank = (P->header[4] & 0x40) << 4;
|
||||||
return (32 * y + texPage + int(texOffsetXY[1])) & 2047;
|
return ((y + m_textureOffset.y) & 1023) + (bank ^ m_textureOffset.switchBank);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inserts a vertex into the local vertex buffer, incrementing both the local and VBO pointers. The normal is scaled by normFlip.
|
// Inserts a vertex into the local vertex buffer, incrementing both the local and VBO pointers. The normal is scaled by normFlip.
|
||||||
|
@ -942,7 +942,7 @@ struct VBORef *CLegacy3D::BeginModel(ModelCache *Cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uploads all vertices from the local vertex buffer to the VBO, sets up the VBO reference, updates the LUT
|
// Uploads all vertices from the local vertex buffer to the VBO, sets up the VBO reference, updates the LUT
|
||||||
void CLegacy3D::EndModel(ModelCache *Cache, struct VBORef *Model, int lutIdx, UINT16 texOffset, bool useStencil)
|
void CLegacy3D::EndModel(ModelCache *Cache, struct VBORef *Model, int lutIdx, UINT16 textureOffsetState, bool useStencil)
|
||||||
{
|
{
|
||||||
int m = Cache->numModels++;
|
int m = Cache->numModels++;
|
||||||
|
|
||||||
|
@ -964,14 +964,14 @@ void CLegacy3D::EndModel(ModelCache *Cache, struct VBORef *Model, int lutIdx, UI
|
||||||
Model->lutIdx = lutIdx;
|
Model->lutIdx = lutIdx;
|
||||||
|
|
||||||
// Texture offset of this model state
|
// Texture offset of this model state
|
||||||
Model->texOffset = texOffset;
|
Model->textureOffsetState = textureOffsetState;
|
||||||
|
|
||||||
// Should we use stencil?
|
// Should we use stencil?
|
||||||
Model->useStencil = useStencil;
|
Model->useStencil = useStencil;
|
||||||
|
|
||||||
// Update the LUT and link up to any existing model that already exists here
|
// Update the LUT and link up to any existing model that already exists here
|
||||||
if (Cache->lut[lutIdx] >= 0) // another texture offset state already cached
|
if (Cache->lut[lutIdx] >= 0) // another texture offset state already cached
|
||||||
Model->nextTexOffset = &(Cache->Models[Cache->lut[lutIdx]]);
|
Model->nextTextureOffsetState = &(Cache->Models[Cache->lut[lutIdx]]);
|
||||||
Cache->lut[lutIdx] = m;
|
Cache->lut[lutIdx] = m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -987,7 +987,7 @@ void CLegacy3D::EndModel(ModelCache *Cache, struct VBORef *Model, int lutIdx, UI
|
||||||
* successful.
|
* successful.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct VBORef *CLegacy3D::CacheModel(ModelCache *Cache, int lutIdx, UINT16 texOffset, const UINT32 *data)
|
struct VBORef *CLegacy3D::CacheModel(ModelCache *Cache, int lutIdx, UINT16 textureOffsetState, const UINT32 *data)
|
||||||
{
|
{
|
||||||
if (data == NULL)
|
if (data == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1140,7 +1140,7 @@ struct VBORef *CLegacy3D::CacheModel(ModelCache *Cache, int lutIdx, UINT16 texOf
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finish model and enter it into the LUT
|
// Finish model and enter it into the LUT
|
||||||
EndModel(Cache, Model, lutIdx, texOffset, useStencil);
|
EndModel(Cache, Model, lutIdx, textureOffsetState, useStencil);
|
||||||
return Model;
|
return Model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1153,7 +1153,7 @@ struct VBORef *CLegacy3D::CacheModel(ModelCache *Cache, int lutIdx, UINT16 texOf
|
||||||
* Look up a model. Use this to determine if a model needs to be cached
|
* Look up a model. Use this to determine if a model needs to be cached
|
||||||
* (returns NULL if so).
|
* (returns NULL if so).
|
||||||
*/
|
*/
|
||||||
struct VBORef *CLegacy3D::LookUpModel(ModelCache *Cache, int lutIdx, UINT16 texOffset)
|
struct VBORef *CLegacy3D::LookUpModel(ModelCache *Cache, int lutIdx, UINT16 textureOffsetState)
|
||||||
{
|
{
|
||||||
int m = Cache->lut[lutIdx];
|
int m = Cache->lut[lutIdx];
|
||||||
|
|
||||||
|
@ -1162,9 +1162,9 @@ struct VBORef *CLegacy3D::LookUpModel(ModelCache *Cache, int lutIdx, UINT16 texO
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
// Has the specified texture offset been cached?
|
// Has the specified texture offset been cached?
|
||||||
for (struct VBORef *Model = &(Cache->Models[m]); Model != NULL; Model = Model->nextTexOffset)
|
for (struct VBORef *Model = &(Cache->Models[m]); Model != NULL; Model = Model->nextTextureOffsetState)
|
||||||
{
|
{
|
||||||
if (Model->texOffset == texOffset)
|
if (Model->textureOffsetState == textureOffsetState)
|
||||||
return Model;
|
return Model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue