//////////////////////////////////////////////////////////////////////////////
//
// Asura_PS2_VU0.h
//
// By: Mike Healey, based on VU1 equivalent
//
// Copyright (c) 2001 Rebellion. All rights reserved.
//
// Contains types and functionality for VU0 and VIF0.
//
//////////////////////////////////////////////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef __Asura_PS2_VU0_h__
#define __Asura_PS2_VU0_h__

// I N C L U D E S ///////////////////////////////////////////////////////////

#include <eetypes.h>

// F O R W A R D   D E C L A R A T I O N S ///////////////////////////////////

union Asura_PS2_QW;

// G L O B A L S /////////////////////////////////////////////////////////////

// Microprograms.
extern u_int VU0_MathsLib __attribute__((section(".vudata")));
//extern u_int VU0_Skinning __attribute__((section(".vudata")));

// Subroutines.
extern u_int VU0_ArcCos[]                   __attribute__((section(".vudata")));
extern u_int VU0_ArcSin[]                   __attribute__((section(".vudata")));
extern u_int VU0_Asura_Matrix3x3_Multiply[] __attribute__((section(".vudata")));
extern u_int VU0_SinCos[]                   __attribute__((section(".vudata")));

// C L A S S E S /////////////////////////////////////////////////////////////

class Asura_PS2_VU0
{

    public:

        // T Y P E S /////////////////////////////////////////////////////////

        enum VU0_MICROPROGRAM
        {
            VU0_PROG_NONE = -1,
            VU0_PROG_MIN,
            VU0_PROG_MATHS_LIB = VU0_PROG_MIN,
//          VU0_PROG_SKINNING,
            VU0_PROG_NUMPROGS,
        };

        // C L A S S   M E T H O D S /////////////////////////////////////////

        static void Initialise( void );
        static void Shutdown( void );
        static bool IsInitialised() { return s_eCurrentProg != VU0_PROG_NONE; };

        static void LoadMicroprogram( VU0_MICROPROGRAM eMicroprog, bool bBlocking = true );
        
        // LoadDataNonBlocking(), vu_mem_dest is address/16; remember to specify
        // if you want to use double buffered memory.
        static void LoadDataNonBlocking( const u_long128* data, u_int num_quadwords, 
                                         u_int vu_mem_dest, u_int kick_vu = 0 ); // 0 = NOP
        static void InitNonBlockingDataLoading( void );
        static void ShutdownNonBlockingDataLoading( void );
        
        static inline void WaitForIdle( void )
        {
            u_long128 dummy;
            asm( "cfc2.i %0, VI00" : "=r" (dummy) );
        }

    private:

        // C L A S S   S T A T E /////////////////////////////////////////////

        static Asura_PS2_QW* s_pxQuickLoadCmdBfr;
        static VU0_MICROPROGRAM s_eCurrentProg;
};

#endif //__Asura_PS2_VU0_h__
