mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2025-03-06 14:27:44 +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
|
||||
* 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
|
||||
* for each unique texOffset.
|
||||
* Models are cached for each unique culling node texture offset state.
|
||||
*/
|
||||
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
|
||||
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 the model was a VROM model, it may be dynamic, so we need to try
|
||||
// another lookup in the dynamic cache
|
||||
ModelRef = LookUpModel(&PolyCache, lutIdx, texOffset);
|
||||
ModelRef = LookUpModel(&PolyCache, lutIdx, m_textureOffset.state);
|
||||
if (ModelRef != NULL)
|
||||
Cache = &PolyCache;
|
||||
}
|
||||
|
@ -617,7 +616,7 @@ bool CLegacy3D::DrawModel(UINT32 modelAddr)
|
|||
// afterwards)
|
||||
if (Cache == &VROMCache && IsDynamicModel(model))
|
||||
Cache = &PolyCache;
|
||||
ModelRef = CacheModel(Cache, lutIdx, texOffset, model);
|
||||
ModelRef = CacheModel(Cache, lutIdx, m_textureOffset.state, model);
|
||||
if (NULL == ModelRef)
|
||||
{
|
||||
// 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);
|
||||
|
||||
// Try caching again...
|
||||
ModelRef = CacheModel(Cache, lutIdx, texOffset, model);
|
||||
ModelRef = CacheModel(Cache, lutIdx, m_textureOffset.state, model);
|
||||
if (NULL == ModelRef)
|
||||
return ErrorUnableToCacheModel(modelAddr); // nothing we can do :(
|
||||
}
|
||||
|
@ -686,20 +685,11 @@ void CLegacy3D::DescendCullingNode(UINT32 addr)
|
|||
const float z = *(float *) &node[0x06-offset];
|
||||
|
||||
// Texture offset?
|
||||
const float oldTexOffsetX = texOffsetXY[0]; // save old offsets
|
||||
const float oldTexOffsetY = texOffsetXY[1];
|
||||
const UINT16 oldTexOffset = texOffset;
|
||||
TextureOffset oldTextureOffset = m_textureOffset; // save old offsets
|
||||
if (!offset) // Step 1.5+
|
||||
{
|
||||
int tx = 32*((node[0x02]>>7)&0x3F);
|
||||
int ty = 32*(node[0x02]&0x1F) + ((node[0x02]&0x4000)?1024:0); // 5 bits for Y coordinate, else Sega Rally 2 initials decal breaks
|
||||
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);
|
||||
}
|
||||
if ((node[0x02] & 0x8000)) // apply texture offset, else retain current ones
|
||||
m_textureOffset = TextureOffset(node[0x02]);
|
||||
}
|
||||
|
||||
// Apply matrix and translation
|
||||
|
@ -731,9 +721,7 @@ void CLegacy3D::DescendCullingNode(UINT32 addr)
|
|||
--stackDepth;
|
||||
|
||||
// Restore old texture offsets
|
||||
texOffsetXY[0] = oldTexOffsetX;
|
||||
texOffsetXY[1] = oldTexOffsetY;
|
||||
texOffset = oldTexOffset;
|
||||
m_textureOffset = oldTextureOffset;
|
||||
}
|
||||
|
||||
// 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]);
|
||||
|
||||
// Clear texture offsets before proceeding
|
||||
texOffsetXY[0] = 0.0;
|
||||
texOffsetXY[1] = 0.0;
|
||||
texOffset = 0x0000;
|
||||
m_textureOffset = TextureOffset();
|
||||
|
||||
// Set up coordinate system and base matrix
|
||||
UINT32 matrixBase = vpnode[0x16] & 0xFFFFFF;
|
||||
|
|
|
@ -83,9 +83,9 @@ struct VBORef
|
|||
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
|
||||
bool useStencil; // whether to draw with stencil mask ("layered" polygons)
|
||||
VBORef *nextTextureOffsetState; // linked list of models with different texture offset states
|
||||
uint16_t textureOffsetState; // texture offset data for this model
|
||||
bool useStencil; // whether to draw with stencil mask ("layered" polygons)
|
||||
|
||||
CTextureRefs texRefs; // unique texture references contained in this model
|
||||
|
||||
|
@ -99,8 +99,8 @@ struct VBORef
|
|||
{
|
||||
texRefs.Clear();
|
||||
lutIdx = 0;
|
||||
texOffset = 0;
|
||||
nextTexOffset = NULL;
|
||||
textureOffsetState = 0;
|
||||
nextTextureOffsetState = NULL;
|
||||
useStencil = false;
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
|
@ -378,9 +378,9 @@ private:
|
|||
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, bool useStencil);
|
||||
struct VBORef *CacheModel(ModelCache *cache, int lutIdx, UINT16 texOffset, const UINT32 *data);
|
||||
struct VBORef *LookUpModel(ModelCache *cache, int lutIdx, UINT16 texOffset);
|
||||
void EndModel(ModelCache *cache, struct VBORef *Model, int lutIdx, UINT16 textureOffsetState, bool useStencil);
|
||||
struct VBORef *CacheModel(ModelCache *cache, int lutIdx, UINT16 textureOffsetState, const UINT32 *data);
|
||||
struct VBORef *LookUpModel(ModelCache *cache, int lutIdx, UINT16 textureOffsetState);
|
||||
void ClearModelCache(ModelCache *cache);
|
||||
bool CreateModelCache(ModelCache *cache, unsigned vboMaxVerts, unsigned localMaxVerts, unsigned maxNumModels, unsigned numLUTEntries, unsigned displayListSize, bool isDynamic);
|
||||
void DestroyModelCache(ModelCache *cache);
|
||||
|
@ -438,8 +438,25 @@ private:
|
|||
// Scene graph processing
|
||||
int listDepth; // how many lists have we recursed into
|
||||
int stackDepth; // for debugging and error handling purposes
|
||||
GLfloat texOffsetXY[2]; // decoded texture X, Y offsets
|
||||
UINT16 texOffset; // raw texture offset data as it appears in culling node
|
||||
struct TextureOffset
|
||||
{
|
||||
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
|
||||
|
||||
// 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 x = ((P->header[4] & 0x1F) << 1) | ((P->header[5] >> 7) & 1);
|
||||
return (32 * x + int(texOffsetXY[0])) & 2047;
|
||||
int x = 32 * (((P->header[4] & 0x7F) << 1) | ((P->header[5] >> 7) & 1));
|
||||
return (x + m_textureOffset.x) & 2047;
|
||||
}
|
||||
|
||||
int CLegacy3D::GetTextureBaseY(const Poly *P) const
|
||||
{
|
||||
int texPage = (P->header[4] & 0x40) << 4; // 1024 or 0
|
||||
int y = P->header[5] & 0x1F;
|
||||
return (32 * y + texPage + int(texOffsetXY[1])) & 2047;
|
||||
int y = 32 * (P->header[5] & 0x7F);
|
||||
int bank = (P->header[4] & 0x40) << 4;
|
||||
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.
|
||||
|
@ -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
|
||||
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++;
|
||||
|
||||
|
@ -964,14 +964,14 @@ void CLegacy3D::EndModel(ModelCache *Cache, struct VBORef *Model, int lutIdx, UI
|
|||
Model->lutIdx = lutIdx;
|
||||
|
||||
// Texture offset of this model state
|
||||
Model->texOffset = texOffset;
|
||||
Model->textureOffsetState = textureOffsetState;
|
||||
|
||||
// Should we use stencil?
|
||||
Model->useStencil = useStencil;
|
||||
|
||||
// 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
|
||||
Model->nextTexOffset = &(Cache->Models[Cache->lut[lutIdx]]);
|
||||
Model->nextTextureOffsetState = &(Cache->Models[Cache->lut[lutIdx]]);
|
||||
Cache->lut[lutIdx] = m;
|
||||
}
|
||||
|
||||
|
@ -987,7 +987,7 @@ void CLegacy3D::EndModel(ModelCache *Cache, struct VBORef *Model, int lutIdx, UI
|
|||
* 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)
|
||||
return NULL;
|
||||
|
@ -1140,7 +1140,7 @@ struct VBORef *CLegacy3D::CacheModel(ModelCache *Cache, int lutIdx, UINT16 texOf
|
|||
}
|
||||
|
||||
// Finish model and enter it into the LUT
|
||||
EndModel(Cache, Model, lutIdx, texOffset, useStencil);
|
||||
EndModel(Cache, Model, lutIdx, textureOffsetState, useStencil);
|
||||
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
|
||||
* (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];
|
||||
|
||||
|
@ -1162,9 +1162,9 @@ struct VBORef *CLegacy3D::LookUpModel(ModelCache *Cache, int lutIdx, UINT16 texO
|
|||
return NULL;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue