//////////////////////////////////////////////////////////////////////////////
//
// Asura_PS2_SmoothSkinDefines.h
//
// Copyright (c) 2004 Rebellion. All rights reserved.
//
// Notes:
//
//      - Camera flags should be set so that for camera c, bit (7 - 2c) is
//        high iff the mesh is visible to it and bit (6 - 2c) is high iff
//        culling is required. This slightly odd arrangement is just for
//        convenience in the microcode - it's easy to shift up but basically
//        impossible to shift down. Note that this is the same scheme as in
//        the GSM renderer, except that clips rather than just culls.
//
//      - The maximum number of weightings per vertex for each strip should
//        be placed in the w component of the first vert's ST QW. EE-side
//        code can render skins at lower LODs using less bones - eg. just 1
//        weighting per vertex for distant characters - by overriding this
//        using the VU1_SS_SKIN_SET_MAX_WEIGHTINGS_PER_VTX_CLAMP microprogram.
//        The resultant value is used to lookup into a jump table (that needs
//        to be setup by EE-side code during initialisation.)
//
//      - Rendering consists of up to three passes:
//            0 - base pass
//            1 - self-illuminating pass
//            2 - reflective or specular pass
//
// VU memory usage:
//
//      Memory layout:
//      
//             0   /--------------------------\
//                 |         GIF tags         |    5 QWs - geometry setup and draw, specular geometry draw, shadow setup and draw
//             5   |--------------------------|
//                 |         cam data         |   56 QWs - (SCISSOR, XYOFFSET, GBC->S scale and trans, GBC->SC scale, O->GBC mat, O->V mat, O cam pos) * 4
//            61   |--------------------------|
//                 |   constant shadow data   |    1 QW  - RGBAQ
//            62   |--------------------------|
//                 |        renderstate       |   20 QWs - (pass 0 (ALPHA, TEX1, TEX0, MIPTBP1, TEST), pass 1 ALPHA, pass 2 (ALPHA, TEX1, TEX0, MIPTBP1)) * 2
//            82   |--------------------------|
//                 |      texture matrices    |   32 QWs - ((tex mat) * 4) * 2
//           114   |--------------------------|
//                 |        light data        |    4 QWs - SH matrix
//           118   |--------------------------|
//                 |       shadow buffer      |    4 QWs - shadow proj mat
//           122   |--------------------------|
//                 |         <unused>         |    2 QWs - spare
//           124   |--------------------------|
//                 |     RS output buffer     |    8 QWs - (setup GIF tag, up to 7 registers)
//           132   |--------------------------|
//                 |       VI reg store       |    5 QWs
//           137   |--------------------------|
//                 |         jump table       |    4 QWs - only w components are used
//           141   |--------------------------|
//                 |        tex anim QW       |    1 QW  - ST offset in x and y components
//           142   |--------------------------|
//                 |         <unused>         |   17 QWs - spare
//           159   |--------------------------|
//                 | bone/input/clip/etc. bfr |  865 QWs - see below
//          1024   \--------------------------/
//
//
//      Memory layout of additional buffers:
//
//          The maximum number of vertices per strip is dictated by the 
//          number of bones used by the skin. We require:
//
//              bone input buffer:   4(B - 1)     (4x4 matrix per bone - don't need bone 0's)
//              strip input buffers: 2 * 5V       (normal, bone indices, bone weights, XYZ, ST) * 2
//              pass 2 buffer:       V + 3        (ST and/or specular value) plus space for overruning by 3 vertices
//              output buffers:      2 * (1 + 3V) (GIF tag, (ST, RGBAQ, XYZ)) * 2
//              clipper input:       V            (RGB + vtx clip flags)
//
//          (For B bones (1 < B < 64) and V vertices.)
//
//          So then:
//
//                                                864 - 4B        2
//              5 + 18V <= 865 - 4(B - 1) => V <= -------- = 48 - - B
//                                                   18           9
//
//          We then use the following layout:
//
//             159 /--------------------------\
//                 |     bone input buffer    | 4(B - 1) QWs - (4x4 matrix)
//  159 + 4(B - 1) |--------------------------|
//                 |         <unused>         |        ? QWs - could be empty, depending on B
//      1019 - 18V |--------------------------|
//                 |    strip input buffers   |      10V QWs - (normal + ADC, bone indices, bone weights, XYZ, ST) * 2
//       1019 - 8V |--------------------------|
//                 |      output buffers      |   2 + 6V QWs - (GIF tag, (ST, RGBAQ, XYZ)) * 2
//       1021 - 2V |--------------------------|
//                 |   clipper input buffer   |        V QWs - (RGB + vtx clip flags)
//        1021 - V |--------------------------|
//                 |       pass 2 buffer      |    V + 3 QWs - (ST and/or specular value) plus space for overrunning by 3 vertices
//            1024 \--------------------------/
//
//////////////////////////////////////////////////////////////////////////////

// B E G I N   F I L E   W R A P P E R ///////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef ___ASURA_PS2_SMOOTHSKINDEFINES_H___
#define ___ASURA_PS2_SMOOTHSKINDEFINES_H___ 1

// M A C R O S ///////////////////////////////////////////////////////////////

// Configuration.
#define ASURA_PS2_SS__REDUCE_WEIGHTINGS_WITH_DISTANCE  (0) // (MP - 01.07.2004) This is disabled for now. We may not able to do it this
                                                           // arbitrarily. It may be that the models are just messy in Rogue but perhaps
                                                           // a better approach would be for weightings to be removed in tools for the
                                                           // generated lower LODs. It may be possible to use a more intelligent
                                                           // algorithm there and probably allow artist overrides / tweaking / etc.

// Limits.
#define ASURA_PS2_SS__MAX_BONES                        (63)
#define ASURA_PS2_SS__MAX_VERTS_PER_STRIP(num_bones)   (static_cast<int>(48.0f - 2.0f * (num_bones) / 9.0f))
#define ASURA_PS2_SS__MAX_DIRECTIONAL_LIGHTS           (3)
#define ASURA_PS2_SS__MAX_CAMERAS                      (4)

// ITOP data: max vertex count per strip for entire skin and skin flags.
#define ASURA_PS2_SS__MASK__LONGEST_STRIP_VTX_COUNT    (0x03F)
#define ASURA_PS2_SS__FLAG__SHADOW                     (0x040)

// ITOP data: material flags.
#define ASURA_PS2_SS__FLAG__SELFILLUMINATED            (0x001)
#define ASURA_PS2_SS__FLAG__REFLECTIVE                 (0x002)
#define ASURA_PS2_SS__FLAG__SPECULAR_SOFT              (0x004)
#define ASURA_PS2_SS__FLAG__SPECULAR_SHARP             (0x008)
#define ASURA_PS2_SS__FLAG__TEX_ANIM                   (0x010)
#define ASURA_PS2_SS__MASK__PASS_1                     (ASURA_PS2_SS__FLAG__SELFILLUMINATED)
#define ASURA_PS2_SS__MASK__PASS_2                     (ASURA_PS2_SS__FLAG__REFLECTIVE | ASURA_PS2_SS__FLAG__SPECULAR_SOFT | ASURA_PS2_SS__FLAG__SPECULAR_SHARP)
#define ASURA_PS2_SS__MASK__MULTIPASS                  (ASURA_PS2_SS__MASK__PASS_1 | ASURA_PS2_SS__MASK__PASS_2)
#define ASURA_PS2_SS__MASK__ANY_VTX_MANIPULATIONS      (ASURA_PS2_SS__MASK__PASS_2 | ASURA_PS2_SS__FLAG__TEX_ANIM)

// ITOP data: cam flags.
#define ASURA_PS2_SS__FLAG__VIS_FOR_MORE_THAN_ONE_CAM  (0x100)
#define ASURA_PS2_SS__MASK__CAM_VIS_FLAGS              (0x0AA)
#define ASURA_PS2_SS__MASK__CAM_CLIP_FLAGS             (0x055)
#define ASURA_PS2_SS__MASK__CAM_VIS_AND_CLIP_FLAGS     (ASURA_PS2_SS__MASK__CAM_VIS_FLAGS | ASURA_PS2_SS__MASK__CAM_CLIP_FLAGS)

// Data area addresses.
#define ASURA_PS2_SS__ADDR__GIF_TAGS                   (0)
#define ASURA_PS2_SS__ADDR__CAM_DATA                   (5)
#define ASURA_PS2_SS__ADDR__CONST_SHADOW_DATA          (61)
#define ASURA_PS2_SS__ADDR__RENDERSTATE_BFR_0          (62)
#define ASURA_PS2_SS__ADDR__RENDERSTATE_BFR_1          (72)
#define ASURA_PS2_SS__ADDR__TEX_MAT_BFR_0              (82)
#define ASURA_PS2_SS__ADDR__TEX_MAT_BFR_1              (98)
#define ASURA_PS2_SS__ADDR__LIGHT_DATA_BFR             (114)
#define ASURA_PS2_SS__ADDR__SHADOW_DATA_BFR            (118)
#define ASURA_PS2_SS__ADDR__RS_OUTPUT_BFR              (124)
#define ASURA_PS2_SS__ADDR__VI_REG_STORE               (132)
#define ASURA_PS2_SS__ADDR__SKIN_SUB_LOOKUP_TABLE      (137)
#define ASURA_PS2_SS__ADDR__TEX_ANIM_DATA              (141)
#define ASURA_PS2_SS__ADDR__BONE_MATRIX_BFR            (159)

// Data area sizes.
#define ASURA_PS2_SS__SIZE__GIF_TAGS                   (5)
#define ASURA_PS2_SS__SIZE__CAM_DATA                   (56)
#define ASURA_PS2_SS__SIZE__CONST_SHADOW_DATA          (1)
#define ASURA_PS2_SS__SIZE__RENDERSTATE_BFR            (10)
#define ASURA_PS2_SS__SIZE__TEX_MAT_BFR                (16)
#define ASURA_PS2_SS__SIZE__LIGHT_DATA_BFR             (4)
#define ASURA_PS2_SS__SIZE__SHADOW_DATA_BFR            (4)
#define ASURA_PS2_SS__SIZE__RS_OUTPUT_BFR              (8)
#define ASURA_PS2_SS__SIZE__VI_REG_STORE               (5)
#define ASURA_PS2_SS__SIZE__SKIN_SUB_LOOKUP_TABLE      (4)
#define ASURA_PS2_SS__SIZE__TEX_ANIM_DATA              (1)

// GIF tag buffer details.
#define ASURA_PS2_SS__OFFSET__GIF_TAGS_GEOM_SETUP      (0)
#define ASURA_PS2_SS__OFFSET__GIF_TAGS_GEOM_DRAW       (1)
#define ASURA_PS2_SS__OFFSET__GIF_TAGS_GEOM_DRAW_SPEC  (2)
#define ASURA_PS2_SS__OFFSET__GIF_TAGS_SHADOW_SETUP    (3)
#define ASURA_PS2_SS__OFFSET__GIF_TAGS_SHADOW_DRAW     (4)

// Cam data buffer details.
#define ASURA_PS2_SS__OFFSET__CAM_DATA_SCISSOR         (0)
#define ASURA_PS2_SS__OFFSET__CAM_DATA_XYOFFSET        (1)
#define ASURA_PS2_SS__OFFSET__CAM_DATA_GBC2S_SCALE     (2)
#define ASURA_PS2_SS__OFFSET__CAM_DATA_GBC2S_TRANS     (3)
#define ASURA_PS2_SS__OFFSET__CAM_DATA_GBC2SC_SCALE    (4)
#define ASURA_PS2_SS__OFFSET__CAM_DATA_O2GBC           (5)
#define ASURA_PS2_SS__OFFSET__CAM_DATA_O2V             (9)
#define ASURA_PS2_SS__OFFSET__CAM_DATA_OBJ_SPACE_POS   (13)
#define ASURA_PS2_SS__OFFSET__CAM_DATA_NEXT_CAM        (14)

// Constant shadow data buffer details.
#define ASURA_PS2_SS__OFFSET__CONST_SHADOW_RGBAQ       (0)

// GIF tag and renderstate input buffer details.
#define ASURA_PS2_SS__OFFSET__RS_IN_PASS_0_ALPHA       (0)
#define ASURA_PS2_SS__OFFSET__RS_IN_PASS_0_TEX1        (1)
#define ASURA_PS2_SS__OFFSET__RS_IN_PASS_0_MIPTBP1     (2)
#define ASURA_PS2_SS__OFFSET__RS_IN_PASS_0_TEX0        (3)
#define ASURA_PS2_SS__OFFSET__RS_IN_PASS_0_TEST        (4)
#define ASURA_PS2_SS__OFFSET__RS_IN_PASS_1_ALPHA       (5)
#define ASURA_PS2_SS__OFFSET__RS_IN_PASS_2_ALPHA       (6)
#define ASURA_PS2_SS__OFFSET__RS_IN_PASS_2_TEX1        (7)
#define ASURA_PS2_SS__OFFSET__RS_IN_PASS_2_MIPTBP1     (8)
#define ASURA_PS2_SS__OFFSET__RS_IN_PASS_2_TEX0        (9)

// Tex mat buffer details.
#define ASURA_PS2_SS__OFFSET__TEX_MAT_NEXT_CAM         (4)

// Shadow data buffer details.
#define ASURA_PS2_SS__OFFSET__SHADOW_PROJ_MAT          (0)

// RS output buffer details for pass 0 - base.
#define ASURA_PS2_SS__OFFSET__RS_OUT_0_SETUP_GIF_TAG   (0)
#define ASURA_PS2_SS__OFFSET__RS_OUT_0_SCISSOR         (1)
#define ASURA_PS2_SS__OFFSET__RS_OUT_0_XYOFFSET        (2)
#define ASURA_PS2_SS__OFFSET__RS_OUT_0_ALPHA           (3)
#define ASURA_PS2_SS__OFFSET__RS_OUT_0_TEX1            (4)
#define ASURA_PS2_SS__OFFSET__RS_OUT_0_MIPTBP1         (5)
#define ASURA_PS2_SS__OFFSET__RS_OUT_0_TEX0            (6)
#define ASURA_PS2_SS__OFFSET__RS_OUT_0_TEST            (7)
#define ASURA_PS2_SS__RS_OUT_0_NLOOP                   (7)

// RS output buffer details for pass 1 - self-illuminating.
#define ASURA_PS2_SS__OFFSET__RS_OUT_1_SETUP_GIF_TAG   (0)
#define ASURA_PS2_SS__OFFSET__RS_OUT_1_ALPHA           (1)
#define ASURA_PS2_SS__RS_OUT_1_NLOOP                   (1)

// RS output buffer details for pass 2 - reflective.
#define ASURA_PS2_SS__OFFSET__RS_OUT_2_REFL_GIF_TAG    (0)
#define ASURA_PS2_SS__OFFSET__RS_OUT_2_REFL_ALPHA      (1)
#define ASURA_PS2_SS__OFFSET__RS_OUT_2_REFL_TEX1       (2)
#define ASURA_PS2_SS__OFFSET__RS_OUT_2_REFL_MIPTBP1    (3)
#define ASURA_PS2_SS__OFFSET__RS_OUT_2_REFL_TEX0       (4)
#define ASURA_PS2_SS__RS_OUT_2_REFL_NLOOP              (4)

// RS output buffer details for pass 2 - specular.
#define ASURA_PS2_SS__OFFSET__RS_OUT_2_SPEC_GIF_TAG    (0)
#define ASURA_PS2_SS__OFFSET__RS_OUT_2_SPEC_ALPHA      (1)
#define ASURA_PS2_SS__RS_OUT_2_SPEC_NLOOP              (1)

// Geometry output buffer details for normal geometry.
#define ASURA_PS2_SS__OFFSET__GEOM_OUT_DRAW_GIF_TAG    (0)
#define ASURA_PS2_SS__OFFSET__GEOM_OUT_FIRST_VERTEX    (1)

// Geometry output buffer details for shadow geometry.
#define ASURA_PS2_SS__OFFSET__SHADOW_OUT_SETUP_GIF_TAG (0)
#define ASURA_PS2_SS__OFFSET__SHADOW_OUT_RGBAQ         (1)
#define ASURA_PS2_SS__OFFSET__SHADOW_OUT_DRAW_GIF_TAG  (2)
#define ASURA_PS2_SS__OFFSET__SHADOW_OUT_FIRST_VTX     (3)

// VI register store aliases.
#define ASURA_PS2_SS__ADDR__VI_REG_STORE_0             (ASURA_PS2_SS__ADDR__VI_REG_STORE + 0)
#define ASURA_PS2_SS__ADDR__VI_REG_STORE_1             (ASURA_PS2_SS__ADDR__VI_REG_STORE + 1)
#define ASURA_PS2_SS__ADDR__VI_REG_STORE_2             (ASURA_PS2_SS__ADDR__VI_REG_STORE + 2)
#define ASURA_PS2_SS__ADDR__VI_REG_STORE_3             (ASURA_PS2_SS__ADDR__VI_REG_STORE + 3)
#define ASURA_PS2_SS__ADDR__VI_REG_STORE_4             (ASURA_PS2_SS__ADDR__VI_REG_STORE + 4)

// E N D   F I L E   W R A P P E R ///////////////////////////////////////////

#endif // #ifndef ___ASURA_PS2_SMOOTHSKINDEFINES_H___
