mirror of
https://github.com/DaedalusX64/daedalus.git
synced 2025-04-02 10:21:48 -04:00
209 lines
5.8 KiB
C
209 lines
5.8 KiB
C
/*
|
|
Copyright (C) 2009 StrmnNrmn
|
|
|
|
This program 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 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program 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 this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
#ifndef HLEGRAPHICS_UCODES_UCODE_SPRITE2D_H_
|
|
#define HLEGRAPHICS_UCODES_UCODE_SPRITE2D_H_
|
|
|
|
//*****************************************************************************
|
|
// Needed by Sprite2D
|
|
//*****************************************************************************
|
|
struct Sprite2DStruct
|
|
{
|
|
u32 address;
|
|
u32 tlut;
|
|
|
|
s16 imageW;
|
|
s16 stride;
|
|
|
|
s8 size;
|
|
s8 format;
|
|
s16 imageH;
|
|
|
|
s16 imageY;
|
|
s16 imageX;
|
|
|
|
s8 dummy[4];
|
|
};
|
|
|
|
DAEDALUS_STATIC_ASSERT( sizeof(Sprite2DStruct) == 24 );
|
|
|
|
struct Sprite2DInfo
|
|
{
|
|
f32 scaleX;
|
|
f32 scaleY;
|
|
|
|
u8 flipX;
|
|
u8 flipY;
|
|
};
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
static void DLParser_Sprite2DScaleFlip( MicroCodeCommand command, Sprite2DInfo *info )
|
|
{
|
|
info->scaleX = ((command.inst.cmd1>>16)&0xFFFF) / 1024.0f;
|
|
info->scaleY = (command.inst.cmd1&0xFFFF) / 1024.0f;
|
|
|
|
info->flipX = ((command.inst.cmd0>>8)&0xFF);
|
|
info->flipY = (command.inst.cmd0&0xFF);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
static void Load_Sprite2D( const Sprite2DStruct *sprite, const Sprite2DInfo info )
|
|
{
|
|
TextureInfo ti;
|
|
ti.SetLoadAddress(RDPSegAddr(sprite->address));
|
|
ti.SetFormat(sprite->format);
|
|
ti.SetSize(sprite->size);
|
|
ti.SetSwapped(false);
|
|
ti.SetPalette(0);
|
|
ti.SetTlutAddress(RDPSegAddr(sprite->tlut));
|
|
ti.SetTLutFormat(kTT_RGBA16);
|
|
|
|
u32 width = sprite->stride;
|
|
u32 height = sprite->imageH + sprite->imageY;
|
|
u32 pitch = (sprite->stride << sprite->size) >> 1;
|
|
|
|
if(g_ROM.GameHacks == WCW_NITRO)
|
|
{
|
|
u32 scaleY = (u32)info.scaleY;
|
|
width *= scaleY;
|
|
height /= scaleY;
|
|
pitch *= scaleY;
|
|
}
|
|
|
|
ti.SetWidth(width);
|
|
ti.SetHeight(height);
|
|
ti.SetPitch(pitch);
|
|
|
|
DL_PF( " Sprite2D Texture:[Width:%d, Height:%d] -> Address[0x%08x] Format[%s] TLUT[0x%x] Pitch[%d]",
|
|
ti.GetWidth(), ti.GetHeight(), ti.GetLoadAddress(), ti.GetFormatName(), ti.GetTlutAddress(), ti.GetPitch());
|
|
|
|
gRenderer->LoadTextureDirectly(ti);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
static void Draw_Sprite2D( MicroCodeCommand command, const Sprite2DStruct *sprite, const Sprite2DInfo info )
|
|
{
|
|
f32 frameX = ((s16)((command.inst.cmd1>>16)&0xFFFF)) / 4.0f;
|
|
f32 frameY = ((s16)(command.inst.cmd1&0xFFFF)) / 4.0f;
|
|
f32 frameW = (u16)(sprite->imageW / info.scaleX);
|
|
f32 frameH = (u16)(sprite->imageH / info.scaleY);
|
|
|
|
f32 ulx, lrx, uly, lry;
|
|
if (info.flipX)
|
|
{
|
|
ulx = frameX + frameW;
|
|
lrx = frameX;
|
|
}
|
|
else
|
|
{
|
|
ulx = frameX;
|
|
lrx = frameX + frameW;
|
|
}
|
|
if (info.flipY)
|
|
{
|
|
uly = frameY + frameH;
|
|
lry = frameY;
|
|
}
|
|
else
|
|
{
|
|
uly = frameY;
|
|
lry = frameY + frameH;
|
|
}
|
|
|
|
f32 uls = sprite->imageX; //left
|
|
f32 ult = sprite->imageY; //top
|
|
f32 lrs = sprite->imageX + sprite->imageW; //right
|
|
f32 lrt = sprite->imageY + sprite->imageH; //bottom
|
|
if (g_ROM.GameHacks == WCW_NITRO)
|
|
{
|
|
ult /= info.scaleY;
|
|
lrt /= info.scaleY;
|
|
}
|
|
DL_PF(" Sprite2D Screen(%.1f, %.1f) -> (%.1f, %.1f)", ulx, uly, lrx, lry);
|
|
DL_PF(" Sprite2D Tex:(%.1f, %.1f) -> (%.1f, %.1f)", uls, lrs, ult, lrt);
|
|
|
|
gRenderer->Draw2DTexture( ulx, uly, lrx, lry, uls, ult, lrs, lrt );
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
static void DLParser_Sprite2DDraw( MicroCodeCommand command, const Sprite2DInfo info, const Sprite2DStruct *sprite )
|
|
{
|
|
Load_Sprite2D( sprite, info );
|
|
Draw_Sprite2D( command, sprite, info );
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
// Used by Flying Dragon
|
|
void DLParser_GBI1_Sprite2DBase( MicroCodeCommand command )
|
|
{
|
|
u32 pc = gDlistStack.address[gDlistStackPointer]; // This points to the next instruction
|
|
MicroCodeCommand * pCmdBase = (MicroCodeCommand*)(g_pu8RamBase + pc);
|
|
|
|
// Try to execute as many sprite2d instructions as possible, I seen chains of over 700! in FB
|
|
do
|
|
{
|
|
const Sprite2DStruct *sprite = (const Sprite2DStruct *)(g_pu8RamBase + RDPSegAddr(command.inst.cmd1));
|
|
|
|
// Fetch the next 2 instructions at once (Sprite2D Flip and Sprite2D Draw)
|
|
MicroCodeCommand command2 = *pCmdBase++;
|
|
MicroCodeCommand command3 = *pCmdBase++;
|
|
|
|
// Nothing todo if either next instruction is invalid
|
|
// Glover does this by calling RDP Sync before drawing the sky
|
|
if (command2.inst.cmd == G_GBI1_SPRITE2D_SCALEFLIP)
|
|
{
|
|
if (command3.inst.cmd != G_GBI1_SPRITE2D_DRAW)
|
|
{
|
|
pc += 16;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pc += 8;
|
|
break;
|
|
}
|
|
|
|
// Avoid division by zero
|
|
if (sprite->stride > 0)
|
|
{
|
|
Sprite2DInfo info;
|
|
DLParser_Sprite2DScaleFlip( command2, &info );
|
|
DLParser_Sprite2DDraw( command3, info, sprite );
|
|
}
|
|
|
|
command = *pCmdBase++;
|
|
pc += 24;
|
|
}while(command.inst.cmd == G_GBI1_SPRITE2D_BASE);
|
|
|
|
gDlistStack.address[gDlistStackPointer] = pc-8;
|
|
}
|
|
|
|
#endif // HLEGRAPHICS_UCODES_UCODE_SPRITE2D_H_
|
|
|