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:
Bart Trzynadlowski 2016-05-30 19:18:11 +00:00
parent 36074d9fd5
commit 9a49fefe12
3 changed files with 50 additions and 47 deletions

View file

@ -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;

View file

@ -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

View file

@ -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;
}