DOOM64-RE

DOOM 64 Reverse Engineering
Log | Files | Refs | README | LICENSE

r_phase3.c (40563B)


      1 
      2 //Renderer phase 3 - World Rendering Routines
      3 
      4 #include "doomdef.h"
      5 #include "r_local.h"
      6 
      7 //-----------------------------------//
      8 void R_RenderWorld(subsector_t *sub);
      9 
     10 void R_WallPrep(seg_t *seg);
     11 void R_RenderWall(seg_t *seg, int flags, int texture, int topHeight, int bottomHeight, int topOffset, int bottomOffset, int topColor, int bottomColor);
     12 void R_RenderSwitch(seg_t *seg, int texture, int topOffset, int color);
     13 
     14 void R_RenderPlane(leaf_t *leaf, int numverts, int zpos, int texture, int xpos, int ypos, int color);
     15 
     16 void R_RenderThings(subsector_t *sub);
     17 void R_RenderLaser(mobj_t *thing);
     18 void R_RenderPSprites(void);
     19 //-----------------------------------//
     20 
     21 void R_RenderAll(void) // 80026590
     22 {
     23     subsector_t *sub;
     24 
     25     while (endsubsector--, (endsubsector >= solidsubsectors))
     26     {
     27         sub = *endsubsector;
     28         frontsector = sub->sector;
     29         R_RenderWorld(sub);
     30 
     31         sub->drawindex = 0x7fff;
     32     }
     33 }
     34 
     35 void R_RenderWorld(subsector_t *sub) // 80026638
     36 {
     37     leaf_t *lf;
     38     seg_t *seg;
     39 
     40     fixed_t xoffset;
     41     fixed_t yoffset;
     42     int numverts;
     43     int i;
     44 
     45     I_CheckGFX();
     46 
     47     gDPSetPrimColor(GFX1++, 0, frontsector->lightlevel, 0, 0, 0, 255);
     48 
     49     numverts = sub->numverts;
     50 
     51     /* */
     52     /* Render Walls */
     53     /* */
     54     lf = &leafs[sub->leaf];
     55     for (i = 0; i < numverts; i++)
     56     {
     57         seg = lf->seg;
     58 
     59         if (seg && (seg->flags & 1))
     60         {
     61             R_WallPrep(seg);
     62         }
     63 
     64         lf++;
     65     }
     66 
     67     /* */
     68     /* Render Ceilings */
     69     /* */
     70     if ((frontsector->ceilingpic != -1) && (viewz < frontsector->ceilingheight))
     71     {
     72         if (frontsector->flags & MS_SCROLLCEILING)
     73         {
     74             xoffset = frontsector->xoffset;
     75             yoffset = frontsector->yoffset;
     76         }
     77         else
     78         {
     79             xoffset = 0;
     80             yoffset = 0;
     81         }
     82 
     83         lf = &leafs[sub->leaf];
     84         R_RenderPlane(lf, numverts, frontsector->ceilingheight >> FRACBITS,
     85                         textures[frontsector->ceilingpic],
     86                         xoffset, yoffset,
     87                         lights[frontsector->colors[0]].rgba);
     88     }
     89 
     90     /* */
     91     /* Render Floors */
     92     /* */
     93     if ((frontsector->floorpic != -1) && (frontsector->floorheight < viewz))
     94     {
     95         if (!(frontsector->flags & MS_LIQUIDFLOOR))
     96         {
     97             if (frontsector->flags & MS_SCROLLFLOOR)
     98             {
     99                 xoffset = frontsector->xoffset;
    100                 yoffset = frontsector->yoffset;
    101             }
    102             else
    103             {
    104                 xoffset = 0;
    105                 yoffset = 0;
    106             }
    107 
    108             lf = &leafs[sub->leaf];
    109             R_RenderPlane(lf, numverts, frontsector->floorheight >> FRACBITS,
    110                             textures[frontsector->floorpic],
    111                             xoffset, yoffset,
    112                             lights[frontsector->colors[1]].rgba);
    113         }
    114         else
    115         {
    116             gDPPipeSync(GFX1++);
    117             gDPSetRenderMode(GFX1++, G_RM_FOG_SHADE_A, G_RM_XLU_SURF2);
    118 
    119             if (frontsector->flags & MS_SCROLLFLOOR)
    120             {
    121                 xoffset = frontsector->xoffset;
    122                 yoffset = frontsector->yoffset;
    123             }
    124             else
    125             {
    126                 xoffset = scrollfrac;
    127                 yoffset = 0;
    128             }
    129 
    130             //--------------------------------------------------------------
    131             lf = &leafs[sub->leaf];
    132             R_RenderPlane(lf, numverts, frontsector->floorheight >> FRACBITS,
    133                             textures[frontsector->floorpic + 1],
    134                             xoffset, yoffset,
    135                             lights[frontsector->colors[1]].rgba);
    136 
    137             //--------------------------------------------------------------
    138             gDPSetPrimColor(GFX1++, 0, frontsector->lightlevel, 0, 0, 0, 160);
    139 
    140             lf = &leafs[sub->leaf];
    141             R_RenderPlane(lf, numverts, frontsector->floorheight >> FRACBITS,
    142                             textures[frontsector->floorpic],
    143                             -yoffset, xoffset,
    144                             lights[frontsector->colors[1]].rgba);
    145 
    146             gDPPipeSync(GFX1++);
    147             gDPSetRenderMode(GFX1++, G_RM_FOG_SHADE_A, G_RM_TEX_EDGE2);
    148         }
    149     }
    150 
    151     /* */
    152     /* Render Things */
    153     /* */
    154     R_RenderThings(sub);
    155 }
    156 
    157 void R_WallPrep(seg_t *seg) // 80026A44
    158 {
    159     sector_t *backsector;
    160 	line_t *li;
    161 	side_t *side;
    162 	fixed_t f_ceilingheight;
    163 	fixed_t f_floorheight;
    164 	fixed_t b_ceilingheight;
    165 	fixed_t b_floorheight;
    166 	fixed_t m_top;
    167 	fixed_t m_bottom;
    168 	fixed_t height;
    169 	fixed_t rowoffs;
    170 	int pic;
    171 
    172 	unsigned int height2;
    173 	unsigned int r1, g1, b1;
    174 	unsigned int r2, g2, b2;
    175 	unsigned int thingcolor;
    176 	unsigned int upcolor;
    177 	unsigned int lowcolor;
    178 	unsigned int topcolor;
    179 	unsigned int bottomcolor;
    180 	unsigned int tmp_upcolor;
    181 	unsigned int tmp_lowcolor;
    182 	int curRowoffset;
    183 
    184     li = seg->linedef;
    185     side = seg->sidedef;
    186 
    187     // [GEC] Prevents errors in textures in T coordinates, but is not applied to switches
    188     curRowoffset = side->rowoffset & (127 << FRACBITS);
    189 
    190     f_ceilingheight = frontsector->ceilingheight >> 16;
    191     f_floorheight = frontsector->floorheight >> 16;
    192 
    193     thingcolor = lights[frontsector->colors[2]].rgba;
    194     upcolor = lights[frontsector->colors[3]].rgba;
    195     lowcolor = lights[frontsector->colors[4]].rgba;
    196 
    197     if (li->flags & ML_BLENDING)
    198     {
    199         r1 = upcolor  >> 24;
    200         g1 = upcolor  >> 16 & 0xff;
    201         b1 = upcolor  >> 8 & 0xff;
    202         r2 = lowcolor >> 24;
    203         g2 = lowcolor >> 16 & 0xff;
    204         b2 = lowcolor >> 8 & 0xff;
    205 
    206         tmp_upcolor = upcolor;
    207         tmp_lowcolor = lowcolor;
    208     }
    209     else
    210     {
    211         topcolor = thingcolor;
    212         bottomcolor = thingcolor;
    213     }
    214 
    215     m_bottom = f_floorheight; // set middle bottom
    216     m_top = f_ceilingheight;  // set middle top
    217 
    218     backsector = seg->backsector;
    219     if (backsector)
    220     {
    221         b_floorheight = backsector->floorheight >> 16;
    222         b_ceilingheight = backsector->ceilingheight >> 16;
    223 
    224         if ((backsector->ceilingheight < frontsector->ceilingheight) && (backsector->ceilingpic != -1))
    225         {
    226             if (li->flags & ML_DONTPEGTOP)
    227             {
    228                 height = (f_ceilingheight - b_ceilingheight);
    229                 rowoffs = (curRowoffset >> 16) + height;
    230             }
    231             else
    232             {
    233                 height = (f_ceilingheight - b_ceilingheight);
    234                 rowoffs = (height + 127 & -128) + (curRowoffset >> 16);
    235             }
    236 
    237             if (li->flags & ML_BLENDING)
    238             {
    239                 if (!(li->flags & ML_BLENDFULLTOP))
    240                 {
    241                     if (f_floorheight < f_ceilingheight)
    242                     {
    243                         height2 = ((height << 16) / (f_ceilingheight - f_floorheight));
    244                     }
    245                     else
    246                     {
    247                         height2 = 0;
    248                     }
    249 
    250                     tmp_lowcolor = (((((r2 - r1) * height2) >> 16) + r1) << 24) |
    251                                    (((((g2 - g1) * height2) >> 16) + g1) << 16) |
    252                                    (((((b2 - b1) * height2) >> 16) + b1) << 8)  | 0xff;
    253                 }
    254 
    255                 if (li->flags & ML_INVERSEBLEND)
    256                 {
    257                     bottomcolor = tmp_upcolor;
    258                     topcolor = tmp_lowcolor;
    259                 }
    260                 else
    261                 {
    262                     topcolor = tmp_upcolor;
    263                     bottomcolor = tmp_lowcolor;
    264                 }
    265 
    266                 // clip middle color upper
    267                 upcolor = tmp_lowcolor;
    268             }
    269 
    270             R_RenderWall(seg, li->flags, textures[side->toptexture],
    271                          f_ceilingheight, b_ceilingheight,
    272                          rowoffs - height, rowoffs,
    273                          topcolor, bottomcolor);
    274 
    275             m_top = b_ceilingheight; // clip middle top height
    276             if ((li->flags & (ML_CHECKFLOORHEIGHT|ML_SWITCHX08)) == ML_SWITCHX08)
    277             {
    278                 if (SWITCHMASK(li->flags) == ML_SWITCHX04)
    279                 {
    280                     pic = side->bottomtexture;
    281                     rowoffs = side->rowoffset >> 16;
    282                 }
    283                 else
    284                 {
    285                     pic = side->midtexture;
    286                     rowoffs = side->rowoffset >> 16;
    287                 }
    288 
    289                 R_RenderSwitch(seg, pic, b_ceilingheight + rowoffs + 48, thingcolor);
    290             }
    291         }
    292 
    293         if (frontsector->floorheight < backsector->floorheight)
    294         {
    295             height = (f_ceilingheight - b_floorheight);
    296 
    297             if ((li->flags & ML_DONTPEGBOTTOM) == 0)
    298             {
    299                 rowoffs = curRowoffset >> 16;
    300             }
    301             else
    302             {
    303                 rowoffs = height + (curRowoffset >> 16);
    304             }
    305 
    306             if (li->flags & ML_BLENDING)
    307             {
    308                 if (!(li->flags & ML_BLENDFULLBOTTOM))
    309                 {
    310                     if (f_floorheight < f_ceilingheight)
    311                     {
    312                         height2 = ((height << 16) / (f_ceilingheight - f_floorheight));
    313                     }
    314                     else
    315                     {
    316                         height2 = 0;
    317                     }
    318 
    319                     tmp_upcolor = (((((r2 - r1) * height2) >> 16) + r1) << 24) |
    320                                   (((((g2 - g1) * height2) >> 16) + g1) << 16) |
    321                                   (((((b2 - b1) * height2) >> 16) + b1) << 8)  | 0xff;
    322                 }
    323 
    324                 topcolor = tmp_upcolor;
    325                 bottomcolor = lowcolor;
    326 
    327                 // clip middle color lower
    328                 lowcolor = tmp_upcolor;
    329             }
    330 
    331             R_RenderWall(seg, li->flags, textures[side->bottomtexture],
    332                          b_floorheight, f_floorheight,
    333                          rowoffs, rowoffs + (b_floorheight - f_floorheight),
    334                          topcolor, bottomcolor);
    335 
    336             m_bottom = b_floorheight; // clip middle bottom height
    337             if ((li->flags & (ML_CHECKFLOORHEIGHT|ML_SWITCHX08)) == ML_CHECKFLOORHEIGHT)
    338             {
    339                 if (SWITCHMASK(li->flags) == ML_SWITCHX02)
    340                 {
    341                     pic = side->toptexture;
    342                     rowoffs = side->rowoffset >> 16;
    343                 }
    344                 else
    345                 {
    346                     pic = side->midtexture;
    347                     rowoffs = side->rowoffset >> 16;
    348                 }
    349 
    350                 R_RenderSwitch(seg, pic, b_floorheight + rowoffs - 16, thingcolor);
    351             }
    352         }
    353 
    354         if (!(li->flags & ML_DRAWMASKED))
    355         {
    356             return;
    357         }
    358     }
    359 
    360     if (li->flags & ML_DONTPEGBOTTOM)
    361     {
    362         height = m_top - m_bottom;
    363         rowoffs = (height + 127 & -128) + (curRowoffset >> 16);
    364     }
    365     else if (li->flags & ML_DONTPEGTOP)
    366     {
    367         rowoffs = (curRowoffset >> 16) - m_bottom;
    368         height = m_top - m_bottom;
    369     }
    370     else
    371     {
    372         height = m_top - m_bottom;
    373         rowoffs = (curRowoffset >> 16) + height;
    374     }
    375 
    376     if (li->flags & ML_BLENDING)
    377     {
    378         topcolor = upcolor;
    379         bottomcolor = lowcolor;
    380     }
    381 
    382     R_RenderWall(seg, li->flags, textures[side->midtexture],
    383                  m_top, m_bottom,
    384                  rowoffs - height, rowoffs,
    385                  topcolor, bottomcolor);
    386 
    387     if ((li->flags & (ML_CHECKFLOORHEIGHT|ML_SWITCHX08)) == (ML_CHECKFLOORHEIGHT|ML_SWITCHX08))
    388     {
    389         if (SWITCHMASK(li->flags) == ML_SWITCHX02)
    390         {
    391             pic = side->toptexture;
    392             rowoffs = side->rowoffset >> 16;
    393         }
    394         else
    395         {
    396             pic = side->bottomtexture;
    397             rowoffs = side->rowoffset >> 16;
    398         }
    399 
    400         R_RenderSwitch(seg, pic, m_bottom + rowoffs + 48, thingcolor);
    401     }
    402 }
    403 
    404 void R_RenderWall(seg_t *seg, int flags, int texture, int topHeight, int bottomHeight,
    405                   int topOffset, int bottomOffset, int topColor, int bottomColor) // 80027138
    406 {
    407     byte *data;
    408     byte *src;
    409     vertex_t *v1;
    410     vertex_t *v2;
    411     int cms, cmt;
    412     int wshift, hshift;
    413 
    414     // [GEC] Prevents errors in textures in S coordinates
    415     int curTextureoffset = (seg->sidedef->textureoffset + seg->offset) & (127 << FRACBITS);
    416 
    417     if (texture != 16)
    418     {
    419         if (flags & ML_HMIRROR) {
    420             cms = G_TX_MIRROR;
    421         }
    422         else {
    423             cms = G_TX_NOMIRROR;
    424         }
    425 
    426         if (flags & ML_VMIRROR) {
    427             cmt = G_TX_MIRROR;
    428         }
    429         else {
    430             cmt = G_TX_NOMIRROR;
    431         }
    432 
    433         if ((texture != globallump) || (globalcm != (cms | cmt)))
    434         {
    435             /*
    436             In Doom 64 all textures are compressed with the second method (dec_d64),
    437             in the original line it was declared that if a texture was not stored,
    438             it would be stored from the DOOM64.WAD and decompressed with the Jaguar Doom
    439             method (dec_jag) which is wrong since all the textures are previously
    440             loaded from the P_Init function with the second decompression method (dec_d64)
    441             */
    442             //data = W_CacheLumpNum(texture >> 4, PU_CACHE, dec_jag); // error decomp mode
    443             data = W_CacheLumpNum(texture >> 4, PU_CACHE, dec_d64); /* [GEC] FIXED */
    444 
    445             wshift = ((textureN64_t*)data)->wshift;
    446             hshift = ((textureN64_t*)data)->hshift;
    447 
    448             src = data + sizeof(textureN64_t);
    449 
    450             // Load Image Data
    451             gDPSetTextureImage(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b , 1, src);
    452             gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0);
    453 
    454             gDPLoadSync(GFX1++);
    455             gDPLoadBlock(GFX1++, G_TX_LOADTILE, 0, 0,
    456                          (((1 << wshift) * (1 << hshift)) >> 2) - 1, 0);
    457 
    458             gDPPipeSync(GFX1++);
    459             gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_4b,
    460                        (((1 << wshift) >> 1) + 7) >> 3, 0, G_TX_RENDERTILE, 0,
    461                        cmt, hshift, 0,
    462                        cms, wshift, 0);
    463 
    464             gDPSetTileSize(GFX1++, G_TX_RENDERTILE, 0, 0,
    465                            ((1 << wshift) - 1) << 2,
    466                            ((1 << hshift) - 1) << 2);
    467 
    468             // Load Palette Data
    469             gDPSetTextureImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_16b , 1,
    470                                src + (1 << ((wshift + hshift + 31) & 31)) + ((texture & 15) << 5));
    471 
    472             gDPTileSync(GFX1++);
    473             gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_4b, 0, 256, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0);
    474 
    475             gDPLoadSync(GFX1++);
    476             gDPLoadTLUTCmd(GFX1++, G_TX_LOADTILE, 15);
    477 
    478             gDPPipeSync(GFX1++);
    479 
    480             globallump = texture;
    481             globalcm = (cms | cmt);
    482         }
    483 
    484         gSPTexture(GFX1++, (1024 << 6)-1, (1024 << 6)-1, 0, G_TX_RENDERTILE, G_ON);
    485 
    486         gSPVertex(GFX1++, VTX1, 4, 0);
    487         gSP1Quadrangle(GFX1++, 0, 1, 2, 3, 1);
    488 
    489         v1 = seg->v1;
    490         v2 = seg->v2;
    491 
    492         // x coordinates
    493         VTX1[0].v.ob[0] = VTX1[3].v.ob[0] = (signed short)(v1->x >> 16);
    494         VTX1[1].v.ob[0] = VTX1[2].v.ob[0] = (signed short)(v2->x >> 16);
    495 
    496         // y coordinates
    497         VTX1[0].v.ob[1] = VTX1[1].v.ob[1] = topHeight;
    498         VTX1[3].v.ob[1] = VTX1[2].v.ob[1] = bottomHeight;
    499 
    500         // z coordinates
    501         VTX1[0].v.ob[2] = VTX1[3].v.ob[2] = (signed short)-(v1->y >> 16);
    502         VTX1[1].v.ob[2] = VTX1[2].v.ob[2] = (signed short)-(v2->y >> 16);
    503 
    504         // texture s coordinates
    505         VTX1[0].v.tc[0] = VTX1[3].v.tc[0] = (curTextureoffset >> 11);
    506         VTX1[1].v.tc[0] = VTX1[2].v.tc[0] = VTX1[0].v.tc[0] + (seg->length << 1);
    507 
    508         // texture t coordinates
    509         VTX1[0].v.tc[1] = VTX1[1].v.tc[1] = (topOffset << 5);
    510         VTX1[2].v.tc[1] = VTX1[3].v.tc[1] = (bottomOffset << 5);
    511 
    512         // vertex color
    513         *(int*)VTX1[0].v.cn = *(int*)VTX1[1].v.cn = topColor;
    514         *(int*)VTX1[2].v.cn = *(int*)VTX1[3].v.cn = bottomColor;
    515 
    516         VTX1 += 4;
    517     }
    518 }
    519 
    520 void R_RenderSwitch(seg_t *seg, int texture, int topOffset, int color) // 80027654
    521 {
    522     byte *data;
    523     byte *src;
    524     vertex_t *v1;
    525     vertex_t *v2;
    526     fixed_t x, y;
    527     fixed_t sin, cos;
    528     int wshift, hshift;
    529 
    530     if (texture != globallump)
    531     {
    532         /*
    533         In Doom 64 all textures are compressed with the second method (dec_d64),
    534         in the original line it was declared that if a texture was not stored,
    535         it would be stored from the DOOM64.WAD and decompressed with the Jaguar Doom
    536         method (dec_jag) which is wrong since all the textures are previously
    537         loaded from the P_Init function with the second decompression method (dec_d64)
    538         */
    539         //data = W_CacheLumpNum(firsttex + texture, PU_CACHE, dec_jag); // error decomp mode
    540         data = W_CacheLumpNum(firsttex + texture, PU_CACHE, dec_d64); /* [GEC] FIXED */
    541 
    542         wshift = ((textureN64_t*)data)->wshift;
    543         hshift = ((textureN64_t*)data)->hshift;
    544 
    545         src = data + sizeof(textureN64_t);
    546 
    547         // Load Image Data
    548         gDPSetTextureImage(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b , 1, src);
    549         gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0);
    550 
    551         gDPLoadSync(GFX1++);
    552         gDPLoadBlock(GFX1++, G_TX_LOADTILE, 0, 0,
    553                          (((1 << wshift) * (1 << hshift)) >> 2) - 1, 0);
    554 
    555         gDPPipeSync(GFX1++);
    556         gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_4b,
    557                        (((1 << wshift) >> 1) + 7) >> 3, 0, G_TX_RENDERTILE, 0,
    558                        0, 0, 0,
    559                        0, 0, 0);
    560 
    561         gDPSetTileSize(GFX1++, G_TX_RENDERTILE, 0, 0,
    562                            ((1 << wshift) - 1) << 2,
    563                            ((1 << hshift) - 1) << 2);
    564 
    565         // Load Palette Data
    566         gDPSetTextureImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_16b , 1,
    567                             src + (1 << ((wshift + hshift + 31) & 31)));
    568 
    569         gDPTileSync(GFX1++);
    570         gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_4b, 0, 256, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0);
    571 
    572         gDPLoadSync(GFX1++);
    573         gDPLoadTLUTCmd(GFX1++, G_TX_LOADTILE, 15);
    574 
    575         gDPPipeSync(GFX1++);
    576 
    577         globallump = texture;
    578     }
    579 
    580     gSPTexture(GFX1++, (512 << 6), (512 << 6), 0, 0, 1);
    581 
    582     gSPVertex(GFX1++, VTX1, 4, 0);
    583     gSP1Quadrangle(GFX1++, 0, 1, 2, 3, 1);
    584 
    585     v1 = seg->linedef->v1;
    586     v2 = seg->linedef->v2;
    587 
    588     x = (v1->x + v2->x);
    589     if (x < 0) {x = x + 1;}
    590 
    591     y = (v1->y + v2->y);
    592     if (y < 0) {y = y + 1;}
    593 
    594     x >>= 1;
    595     y >>= 1;
    596 
    597     cos = finecosine[seg->angle >> ANGLETOFINESHIFT] << 1;
    598     sin = finesine  [seg->angle >> ANGLETOFINESHIFT] << 1;
    599 
    600     // x coordinates
    601     VTX1[0].v.ob[0] = VTX1[3].v.ob[0] = ((x) - (cos << 3) + sin) >> 16;
    602     VTX1[1].v.ob[0] = VTX1[2].v.ob[0] = ((x) + (cos << 3) + sin) >> 16;
    603 
    604     // y coordinates
    605     VTX1[0].v.ob[1] = VTX1[1].v.ob[1] = topOffset;
    606     VTX1[3].v.ob[1] = VTX1[2].v.ob[1] = topOffset - 32;
    607 
    608     // z coordinates
    609     VTX1[0].v.ob[2] = VTX1[3].v.ob[2] = ((-y) + (sin << 3) + cos) >> 16;
    610     VTX1[1].v.ob[2] = VTX1[2].v.ob[2] = ((-y) - (sin << 3) + cos) >> 16;
    611 
    612     // texture s coordinates
    613     VTX1[0].v.tc[0] = VTX1[3].v.tc[0] = (0 << 6);
    614     VTX1[1].v.tc[0] = VTX1[2].v.tc[0] = (32 << 6);
    615 
    616     // texture t coordinates
    617     VTX1[0].v.tc[1] = VTX1[1].v.tc[1] = (0 << 6);
    618     VTX1[2].v.tc[1] = VTX1[3].v.tc[1] = (32 << 6);
    619 
    620     // vertex color
    621     *(int*)VTX1[0].v.cn = *(int*)VTX1[1].v.cn = *(int*)VTX1[2].v.cn = *(int*)VTX1[3].v.cn = color;
    622 
    623     VTX1 += 4;
    624 }
    625 
    626 void R_RenderPlane(leaf_t *leaf, int numverts, int zpos, int texture, int xpos, int ypos, int color) // 80027B68
    627 {
    628     byte *data;
    629     byte *src;
    630     vertex_t *vrt;
    631     fixed_t x;
    632     fixed_t y;
    633     int idx, i;
    634     int v00, v01, v02;
    635 
    636     if (texture != globallump)
    637     {
    638         /*
    639         In Doom 64 all textures are compressed with the second method (dec_d64),
    640         in the original line it was declared that if a texture was not stored,
    641         it would be stored from the DOOM64.WAD and decompressed with the Jaguar Doom
    642         method (dec_jag) which is wrong since all the textures are previously
    643         loaded from the P_Init function with the second decompression method (dec_d64)
    644         */
    645         //data = W_CacheLumpNum(texture >> 4, PU_CACHE, dec_jag); // error decomp mode
    646         data = W_CacheLumpNum(texture >> 4, PU_CACHE, dec_d64); /* [GEC] FIXED */
    647 
    648         src = data + sizeof(textureN64_t);
    649 
    650         // Load Image Data
    651         gDPSetTextureImage(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b , 1, src);
    652         gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0);
    653 
    654         gDPLoadSync(GFX1++);
    655         gDPLoadBlock(GFX1++, G_TX_LOADTILE, 0, 0,
    656                          (((1 << 6) * (1 << 6)) >> 2) - 1, 0);
    657 
    658         gDPPipeSync(GFX1++);
    659         gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_4b,
    660                        (((1 << 6) >> 1) + 7) >> 3, 0, G_TX_RENDERTILE, 0,
    661                        0, 6, 0,
    662                        0, 6, 0);
    663 
    664         gDPSetTileSize(GFX1++, G_TX_RENDERTILE, 0, 0,
    665                            ((1 << 6) - 1) << 2,
    666                            ((1 << 6) - 1) << 2);
    667 
    668         // Load Palette Data
    669         gDPSetTextureImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_16b , 1,
    670                                src + (1 << (6 + 6 - 1)) + ((texture & 15) << 5));
    671 
    672         gDPTileSync(GFX1++);
    673         gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_4b, 0, 256, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0);
    674 
    675         gDPLoadSync(GFX1++);
    676         gDPLoadTLUTCmd(GFX1++, G_TX_LOADTILE, 15);
    677 
    678         gDPPipeSync(GFX1++);
    679 
    680         globallump = texture;
    681     }
    682 
    683     vrt = leaf->vertex;
    684     VTX1[0].v.ob[0] = (vrt->x >> 16);
    685     VTX1[0].v.ob[1] = zpos;
    686     VTX1[0].v.ob[2] =-(vrt->y >> 16);
    687     VTX1[0].v.tc[0] = (((vrt->x + xpos & 0x3f0000U) >> 16) << 5);
    688     VTX1[0].v.tc[1] =-(((vrt->y + ypos & 0x3f0000U) >> 16) << 5);
    689     *(int *)VTX1[0].v.cn = color;
    690 
    691     x = ((vrt->x + xpos) >> 16) & -64;
    692     y = ((vrt->y + ypos) >> 16) & -64;
    693 
    694     gSPTexture(GFX1++, (1024 << 6)-1, (1024 << 6)-1, 0, G_TX_RENDERTILE, G_ON);
    695 
    696     if (numverts >= 32)
    697         numverts = 32;
    698 
    699     gSPVertex(GFX1++, VTX1, numverts, 0);
    700     VTX1++;
    701 
    702     if (numverts & 1)
    703     {
    704         idx = 2;
    705         gSP1Triangle(GFX1++, 0, 1, 2, 0);
    706     }
    707     else
    708     {
    709         idx = 1;
    710     }
    711 
    712     leaf++;
    713     numverts--;
    714 
    715     if (idx < numverts)
    716     {
    717         v00 = idx + 0;
    718         v01 = idx + 1;
    719         v02 = idx + 2;
    720         do
    721         {
    722             gSP2Triangles(GFX1++,
    723                           v00, v01, v02, 0, // 0, 1, 2
    724                           v00, v02, 0, 0);  // 0, 2, 0
    725 
    726             v00 += 2;
    727             v01 += 2;
    728             v02 += 2;
    729         } while (v02 < (numverts + 2));
    730     }
    731 
    732     /*i = 0;
    733     if (numverts > 0)
    734     {
    735         if ((numverts & 3))
    736         {
    737             while(i != (numverts & 3))
    738             {
    739                 vrt = leaf->vertex;
    740                 VTX1[0].v.ob[0] = (vrt->x >> 16);
    741                 VTX1[0].v.ob[1] = zpos;
    742                 VTX1[0].v.ob[2] =-(vrt->y >> 16);
    743                 VTX1[0].v.tc[0] = ((((vrt->x + xpos) >> 16) - x) << 5);
    744                 VTX1[0].v.tc[1] =-((((vrt->y + ypos) >> 16) - y) << 5);
    745                 *(int *)VTX1[0].v.cn = color;
    746                 VTX1++;
    747                 leaf++;
    748                 i++;
    749             }
    750         }
    751 
    752         while(i != numverts)
    753         {
    754             vrt = leaf->vertex;
    755             VTX1[0].v.ob[0] = (vrt->x >> 16);
    756             VTX1[0].v.ob[1] = zpos;
    757             VTX1[0].v.ob[2] =-(vrt->y >> 16);
    758             VTX1[0].v.tc[0] = ((((vrt->x + xpos) >> 16) - x) << 5);
    759             VTX1[0].v.tc[1] =-((((vrt->y + ypos) >> 16) - y) << 5);
    760             *(int *)VTX1[0].v.cn = color;
    761             VTX1++;
    762             leaf++;
    763 
    764             vrt = leaf->vertex;
    765             VTX1[0].v.ob[0] = (vrt->x >> 16);
    766             VTX1[0].v.ob[1] = zpos;
    767             VTX1[0].v.ob[2] =-(vrt->y >> 16);
    768             VTX1[0].v.tc[0] = ((((vrt->x + xpos) >> 16) - x) << 5);
    769             VTX1[0].v.tc[1] =-((((vrt->y + ypos) >> 16) - y) << 5);
    770             *(int *)VTX1[0].v.cn = color;
    771             VTX1++;
    772             leaf++;
    773 
    774             vrt = leaf->vertex;
    775             VTX1[0].v.ob[0] = (vrt->x >> 16);
    776             VTX1[0].v.ob[1] = zpos;
    777             VTX1[0].v.ob[2] =-(vrt->y >> 16);
    778             VTX1[0].v.tc[0] = ((((vrt->x + xpos) >> 16) - x) << 5);
    779             VTX1[0].v.tc[1] =-((((vrt->y + ypos) >> 16) - y) << 5);
    780             *(int *)VTX1[0].v.cn = color;
    781             VTX1++;
    782             leaf++;
    783 
    784             vrt = leaf->vertex;
    785             VTX1[0].v.ob[0] = (vrt->x >> 16);
    786             VTX1[0].v.ob[1] = zpos;
    787             VTX1[0].v.ob[2] =-(vrt->y >> 16);
    788             VTX1[0].v.tc[0] = ((((vrt->x + xpos) >> 16) - x) << 5);
    789             VTX1[0].v.tc[1] =-((((vrt->y + ypos) >> 16) - y) << 5);
    790             *(int *)VTX1[0].v.cn = color;
    791             VTX1++;
    792             leaf++;
    793 
    794             i += 4;
    795         }
    796     }*/
    797 
    798     for(i = 0; i < numverts; i++)
    799     {
    800         vrt = leaf->vertex;
    801         VTX1[0].v.ob[0] = (vrt->x >> 16);
    802         VTX1[0].v.ob[1] = zpos;
    803         VTX1[0].v.ob[2] =-(vrt->y >> 16);
    804         VTX1[0].v.tc[0] = ((((vrt->x + xpos) >> 16) - x) << 5);
    805         VTX1[0].v.tc[1] =-((((vrt->y + ypos) >> 16) - y) << 5);
    806         *(int *)VTX1[0].v.cn = color;
    807         VTX1++;
    808         leaf++;
    809     }
    810 }
    811 
    812 void R_RenderThings(subsector_t *sub) // 80028248
    813 {
    814     byte *data;
    815     byte *src;
    816     byte *paldata;
    817     vissprite_t *vissprite_p;
    818 
    819     mobj_t *thing;
    820     boolean flip;
    821     int lump;
    822 
    823     int compressed;
    824     int tileh;
    825     int tilew;
    826     int height;
    827     int width;
    828     int tiles;
    829     int color;
    830 
    831     fixed_t xx, yy;
    832     int xpos1, xpos2;
    833     int ypos;
    834     int zpos1, zpos2;
    835     int spos, tpos;
    836     int v00, v01, v02, v03;
    837 
    838     vissprite_p = sub->vissprite;
    839     if (vissprite_p)
    840     {
    841         gDPPipeSync(GFX1++);
    842 
    843         if (vissprite_p->thing->flags & MF_RENDERLASER)
    844         {
    845             gDPSetRenderMode(GFX1++, G_RM_FOG_SHADE_A, G_RM_RA_OPA_SURF2);
    846             gDPSetCombineMode(GFX1++, G_CC_D64COMB15, G_CC_D64COMB16);
    847 
    848             do
    849             {
    850                 I_CheckGFX();
    851                 R_RenderLaser(vissprite_p->thing);
    852 
    853                 vissprite_p = vissprite_p->next;
    854                 if(vissprite_p == NULL) {
    855                     break;
    856                 }
    857 
    858             } while(vissprite_p->thing->flags & MF_RENDERLASER);
    859 
    860             gDPPipeSync(GFX1++);
    861             gDPSetCombineMode(GFX1++, G_CC_D64COMB07, G_CC_D64COMB08);
    862 
    863             if (vissprite_p == NULL)
    864             {
    865                 gDPSetRenderMode(GFX1++, G_RM_FOG_SHADE_A, G_RM_TEX_EDGE2);
    866                 return;
    867             }
    868         }
    869 
    870         gDPSetRenderMode(GFX1++, G_RM_FOG_SHADE_A, G_RM_XLU_SURF2_CLAMP);
    871 
    872         while (vissprite_p)
    873         {
    874             I_CheckGFX();
    875 
    876             thing = vissprite_p->thing;
    877             lump = vissprite_p->lump;
    878             flip = vissprite_p->flip;
    879 
    880             if (thing->frame & FF_FULLBRIGHT)
    881             {
    882                 color = PACKRGBA(255, 255, 255, 255);//0xffffffff;
    883             }
    884             else
    885             {
    886                 color = lights[vissprite_p->sector->colors[2]].rgba;
    887             }
    888 
    889             gDPSetPrimColorD64(GFX1++, 0, vissprite_p->sector->lightlevel, thing->alpha);
    890 
    891             data = W_CacheLumpNum(lump, PU_CACHE, dec_jag);
    892 
    893             compressed = ((spriteN64_t*)data)->compressed;
    894             tileh = ((spriteN64_t*)data)->tileheight;
    895             width = ((spriteN64_t*)data)->width;
    896             height = ((spriteN64_t*)data)->height;
    897             tiles = ((spriteN64_t*)data)->tiles << 1;
    898 
    899             spos = width;
    900             tpos = 0;
    901 
    902             src = data + sizeof(spriteN64_t);
    903 
    904             if (flip)
    905             {
    906                 xx = thing->x + (((spriteN64_t*)data)->xoffs * viewsin);
    907                 xpos1 = (xx - (width * viewsin)) >> 16;
    908                 xpos2 = (xx) >> 16;
    909 
    910                 yy = thing->y - (((spriteN64_t*)data)->xoffs * viewcos);
    911                 zpos1 = -(yy + (width * viewcos)) >> 16;
    912                 zpos2 = -(yy) >> 16;
    913             }
    914             else
    915             {
    916                 xx = thing->x - (((spriteN64_t*)data)->xoffs * viewsin);
    917                 xpos2 = (xx + (width * viewsin)) >> 16;
    918                 xpos1 = (xx) >> 16;
    919 
    920                 yy = thing->y + (((spriteN64_t*)data)->xoffs * viewcos);
    921                 zpos2 = -(yy - (width * viewcos)) >> 16;
    922                 zpos1 = -(yy) >> 16;
    923             }
    924 
    925             gSPTexture(GFX1++, (512 << 6), (512 << 6), 0, 0, 1);
    926 
    927             gSPVertex(GFX1++, VTX1, (tiles+2), 0);
    928 
    929             if (compressed < 0)
    930             {
    931                 width = ((spriteN64_t*)data)->width + 7 & ~7;
    932                 tilew = tileh * width;
    933 
    934                 if (((spriteN64_t*)data)->cmpsize & 1)
    935                 {
    936                     paldata = W_CacheLumpNum((lump - (((spriteN64_t*)data)->cmpsize >> 1)) +
    937                                              thing->info->palette, PU_CACHE, dec_jag) + 8;
    938                 }
    939                 else
    940                 {
    941                     paldata = (src + ((spriteN64_t*)data)->cmpsize);
    942                 }
    943 
    944                 // Load Palette Data (256 colors)
    945                 gDPSetTextureImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_16b , 1, paldata);
    946 
    947                 gDPTileSync(GFX1++);
    948                 gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_4b, 0, 256, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0);
    949 
    950                 gDPLoadSync(GFX1++);
    951                 gDPLoadTLUTCmd(GFX1++, G_TX_LOADTILE, 255);
    952 
    953                 gDPPipeSync(GFX1++);
    954             }
    955             else
    956             {
    957                 width = ((spriteN64_t*)data)->width + 15 & ~15;
    958                 tilew = tileh * width;
    959 
    960                 if (tilew < 0) {
    961                     tilew = tilew + 1;
    962                 }
    963 
    964                 tilew >>= 1;
    965 
    966                 // Load Palette Data (16 colors)
    967                 gDPSetTextureImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_16b , 1, (src + ((spriteN64_t*)data)->cmpsize));
    968 
    969                 gDPTileSync(GFX1++);
    970                 gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_4b, 0, 256, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0);
    971 
    972                 gDPLoadSync(GFX1++);
    973                 gDPLoadTLUTCmd(GFX1++, G_TX_LOADTILE, 15);
    974 
    975                 gDPPipeSync(GFX1++);
    976             }
    977 
    978             ypos = (thing->z >> 16) + ((spriteN64_t*)data)->yoffs;
    979 
    980             VTX1[0].v.ob[0] = xpos1;
    981             VTX1[0].v.ob[1] = ypos;
    982             VTX1[0].v.ob[2] = zpos1;
    983 
    984             VTX1[1].v.ob[0] = xpos2;
    985             VTX1[1].v.ob[1] = ypos;
    986             VTX1[1].v.ob[2] = zpos2;
    987 
    988             VTX1[flip].v.tc[0] = 0;
    989             VTX1[flip^1].v.tc[0] = (spos << 6);
    990 
    991             VTX1[0].v.tc[1] = VTX1[1].v.tc[1] = (tpos << 6);
    992 
    993             *(int *)VTX1[0].v.cn = *(int *)VTX1[1].v.cn = color;
    994             VTX1 += 2;
    995 
    996             v03 = 0;
    997             v00 = 1;
    998             v01 = 3;
    999             v02 = 2;
   1000 
   1001             if (tiles > 0)
   1002             {
   1003                 do
   1004                 {
   1005                     if (compressed < 0)
   1006                     {
   1007                         // Load Image Data (8bit)
   1008                         gDPSetTextureImage(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b , 1, src);
   1009                         gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0);
   1010 
   1011                         gDPLoadSync(GFX1++);
   1012                         gDPLoadBlock(GFX1++, G_TX_LOADTILE, 0, 0, (tilew >> 1) - 1, 0);
   1013 
   1014                         gDPPipeSync(GFX1++);
   1015                         gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_8b, (width >> 3), 0,
   1016                                    G_TX_RENDERTILE , 0, 0, 0, 0, 0, 0, 0);
   1017 
   1018                         gDPSetTileSize(GFX1++, G_TX_RENDERTILE, 0, tpos << 2, ((width - 1) << 2), (tpos + tileh - 1) << 2);
   1019                     }
   1020                     else
   1021                     {
   1022                         // Load Image Data (4bit)
   1023                         gDPSetTextureImage(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b , 1, src);
   1024                         gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0);
   1025 
   1026                         gDPLoadSync(GFX1++);
   1027                         gDPLoadBlock(GFX1++, G_TX_LOADTILE, 0, 0, (tilew >> 1) - 1, 0);
   1028 
   1029                         gDPPipeSync(GFX1++);
   1030                         gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_4b, (width >> 4), 0,
   1031                                    G_TX_RENDERTILE , 0, 0, 0, 0, 0, 0, 0);
   1032 
   1033                         gDPSetTileSize(GFX1++, G_TX_RENDERTILE, 0, tpos << 2, ((width - 1) << 2), (tpos + tileh - 1) << 2);
   1034                     }
   1035 
   1036                     tpos += tileh;
   1037                     ypos -= tileh;
   1038 
   1039                     gSP2Triangles(GFX1++, v00, v01, v02, 0, // 1, 3, 2
   1040                                           v00, v02, v03, 0); // 1, 2, 0
   1041 
   1042                     VTX1[0].v.ob[0] = xpos1;
   1043                     VTX1[0].v.ob[1] = ypos;
   1044                     VTX1[0].v.ob[2] = zpos1;
   1045 
   1046                     VTX1[1].v.ob[0] = xpos2;
   1047                     VTX1[1].v.ob[1] = ypos;
   1048                     VTX1[1].v.ob[2] = zpos2;
   1049 
   1050                     VTX1[flip].v.tc[0] = 0;
   1051                     VTX1[flip^1].v.tc[0] = (spos << 6);
   1052 
   1053                     VTX1[0].v.tc[1] = VTX1[1].v.tc[1] = (tpos << 6);
   1054 
   1055                     *(int *)VTX1[0].v.cn = *(int *)VTX1[1].v.cn = color;
   1056                     VTX1 += 2;
   1057 
   1058                     src += tilew;
   1059 
   1060                     height -= tileh;
   1061                     if (height < tileh) {
   1062                         tileh = height;
   1063                     }
   1064 
   1065                     v00 += 2;
   1066                     v01 += 2;
   1067                     v02 += 2;
   1068                     v03 += 2;
   1069                 } while (v02 < (tiles+2));
   1070             }
   1071 
   1072             vissprite_p = vissprite_p->next;
   1073         }
   1074 
   1075         globallump = -1;
   1076 
   1077         gDPPipeSync(GFX1++);
   1078         gDPSetRenderMode(GFX1++, G_RM_FOG_SHADE_A, G_RM_TEX_EDGE2);
   1079     }
   1080 }
   1081 
   1082 void R_RenderLaser(mobj_t *thing) // 80028CCC
   1083 {
   1084     laserdata_t *laserdata;
   1085 
   1086     laserdata = (laserdata_t *)thing->extradata;
   1087 
   1088     gSPVertex(GFX1++, (VTX1), 6, 0);
   1089 
   1090     gSP2Triangles(GFX1++, 0, 2, 3, 1/*flag1*/,
   1091 						  0, 1, 2, 2/*flag2*/);
   1092 
   1093     gSP2Triangles(GFX1++, 0, 3, 5, 2/*flag1*/,
   1094 						  3, 4, 5, 2/*flag2*/);
   1095 
   1096     VTX1[0].v.ob[0] = (laserdata->x1 >> 16);
   1097     VTX1[0].v.ob[1] = (laserdata->z1 >> 16);
   1098     VTX1[0].v.ob[2] = -(laserdata->y1 >> 16);
   1099 
   1100     VTX1[1].v.ob[0] = ((laserdata->x1 - laserdata->slopey) >> 16);
   1101     VTX1[1].v.ob[1] = (laserdata->z1 >> 16);
   1102     VTX1[1].v.ob[2] = (-(laserdata->y1 + laserdata->slopex) >> 16);
   1103 
   1104     VTX1[2].v.ob[0] = ((laserdata->x2 - laserdata->slopey) >> 16);
   1105     VTX1[2].v.ob[1] = (laserdata->z2 >> 16);
   1106     VTX1[2].v.ob[2] = (-(laserdata->y2 + laserdata->slopex) >> 16);
   1107 
   1108     VTX1[3].v.ob[0] = (laserdata->x2 >> 16);
   1109     VTX1[3].v.ob[1] = (laserdata->z2 >> 16);
   1110     VTX1[3].v.ob[2] = -(laserdata->y2 >> 16);
   1111 
   1112     VTX1[4].v.ob[0] = ((laserdata->x2 + laserdata->slopey) >> 16);
   1113     VTX1[4].v.ob[1] = (laserdata->z2 >> 16);
   1114     VTX1[4].v.ob[2] = (-(laserdata->y2 - laserdata->slopex) >> 16);
   1115 
   1116     VTX1[5].v.ob[0] = ((laserdata->x1 + laserdata->slopey) >> 16);
   1117     VTX1[5].v.ob[1] = (laserdata->z1 >> 16);
   1118     VTX1[5].v.ob[2] = (-(laserdata->y1 - laserdata->slopex) >> 16);
   1119 
   1120     *(int *)VTX1[0].v.cn = PACKRGBA(255,0,0,255); // 0xff0000ff;
   1121     *(int *)VTX1[1].v.cn = PACKRGBA(0,0,0,255);   // 0xff;
   1122     *(int *)VTX1[2].v.cn = PACKRGBA(0,0,0,255);   // 0xff;
   1123     *(int *)VTX1[3].v.cn = PACKRGBA(255,0,0,255); // 0xff0000ff;
   1124     *(int *)VTX1[4].v.cn = PACKRGBA(0,0,0,255);   // 0xff;
   1125     *(int *)VTX1[5].v.cn = PACKRGBA(0,0,0,255);   // 0xff;
   1126 
   1127     VTX1 += 6;
   1128 }
   1129 
   1130 void R_RenderPSprites(void) // 80028f20
   1131 {
   1132     int				i;
   1133 	pspdef_t		*psp, *psptmp;
   1134 	state_t			*state;
   1135 	spritedef_t		*sprdef;
   1136 	spriteframe_t	*sprframe;
   1137 	int				lump;
   1138 	int				flagtranslucent;
   1139 
   1140 	boolean         palloaded;
   1141 	byte		    *data;
   1142 	byte		    *paldata;
   1143 	byte		    *src;
   1144 
   1145 	int             tilecnt;
   1146 	int             tiles;
   1147 	int             tileh;
   1148 	int             tilew;
   1149 	int             width;
   1150 	int             height;
   1151 	int             width2;
   1152 	int             yh;
   1153 	int             x, y;
   1154 
   1155 	I_CheckGFX();
   1156 
   1157 	gDPPipeSync(GFX1++);
   1158 	gDPSetTexturePersp(GFX1++, G_TP_NONE);
   1159 	gDPSetCombineMode(GFX1++, G_CC_D64COMB17, G_CC_D64COMB18);
   1160 
   1161     psp = &viewplayer->psprites[0];
   1162 
   1163     flagtranslucent = (viewplayer->mo->flags & MF_SHADOW) != 0;
   1164 
   1165     psptmp = psp;
   1166     for (i = 0; i < NUMPSPRITES; i++, psptmp++)
   1167     {
   1168         if(flagtranslucent || ((psptmp->state != 0) && (psptmp->alpha < 255)))
   1169         {
   1170             gDPSetRenderMode(GFX1++, G_RM_FOG_SHADE_A, G_RM_XLU_SURF2_CLAMP);
   1171             break;
   1172         }
   1173     }
   1174 
   1175     palloaded = false;
   1176 
   1177     for (i = 0; i < NUMPSPRITES; i++, psp++)
   1178 	{
   1179 		if ((state = psp->state) != 0) /* a null state means not active */
   1180 		{
   1181 			sprdef = &sprites[state->sprite];
   1182 			sprframe = &sprdef->spriteframes[state->frame & FF_FRAMEMASK];
   1183 			lump = sprframe->lump[0];
   1184 
   1185             data = W_CacheLumpNum(lump, PU_CACHE, dec_jag);
   1186 
   1187             tilecnt = 0;
   1188             tiles = ((spriteN64_t*)data)->tiles;
   1189             width = ((spriteN64_t*)data)->width;
   1190             tileh = ((spriteN64_t*)data)->tileheight;
   1191             width2 = width + 7 & ~7;
   1192             tilew = tileh * width2;
   1193             height = ((spriteN64_t*)data)->height;
   1194             src = data + sizeof(spriteN64_t);
   1195 
   1196             x = (((psp->sx >> 16) - ((spriteN64_t*)data)->xoffs) + 160) << 2;
   1197             y = (((psp->sy >> 16) - ((spriteN64_t*)data)->yoffs) + 239) << 2;
   1198             if (viewplayer->onground)
   1199             {
   1200                 x += (quakeviewx >> 20);
   1201                 y += (quakeviewy >> 14);
   1202             }
   1203 
   1204 			if (psp->state->frame & FF_FULLBRIGHT)
   1205 			{
   1206 			    gDPSetPrimColorD64(GFX1, 0, 0, PACKRGBA(255,255,255,0));//0xffffff00
   1207 			}
   1208 			else
   1209 			{
   1210 			    gDPSetPrimColorD64(GFX1, 0, frontsector->lightlevel,
   1211                           lights[frontsector->colors[2]].rgba & ~255); // remove alpha value
   1212 			}
   1213 
   1214 			// apply alpha value
   1215 			if (flagtranslucent)
   1216 			{
   1217 				GFX1->words.w1 |= 144;
   1218 			}
   1219 			else
   1220             {
   1221                 GFX1->words.w1 |= psp->alpha;
   1222             }
   1223             GFX1++; // continue to next GFX1
   1224 
   1225             if (!palloaded)
   1226             {
   1227                 palloaded = true;
   1228 
   1229                 if (((spriteN64_t*)data)->cmpsize & 1)
   1230                 {
   1231                 /* Loads the palette from the first frame of the animation,  */
   1232                 /* which uses an odd number to get to the lump */
   1233                     paldata = W_CacheLumpNum((lump - (((spriteN64_t*)data)->cmpsize >> 1)),
   1234                                              PU_CACHE, dec_jag);
   1235 
   1236                     paldata += (((spriteN64_t*)paldata)->cmpsize + sizeof(spriteN64_t));
   1237                 }
   1238                 else
   1239                 {
   1240                 /* Loads the palette if it is included in the image data */
   1241                     paldata = (src + ((spriteN64_t*)data)->cmpsize);
   1242                 }
   1243 
   1244                 /* Load Palette Data (256 colors) */
   1245                 gDPSetTextureImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_16b , 1, paldata);
   1246 
   1247                 gDPTileSync(GFX1++);
   1248                 gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_4b, 0, 256, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0);
   1249 
   1250                 gDPLoadSync(GFX1++);
   1251                 gDPLoadTLUTCmd(GFX1++, G_TX_LOADTILE, 255);
   1252 
   1253                 gDPPipeSync(GFX1++);
   1254             }
   1255 
   1256             if (tiles > 0)
   1257             {
   1258                 do
   1259                 {
   1260                     /* Load Image Data (8bit) */
   1261                     gDPSetTextureImage(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b , 1, src);
   1262                     gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0);
   1263 
   1264                     gDPLoadSync(GFX1++);
   1265                     gDPLoadBlock(GFX1++, G_TX_LOADTILE, 0, 0, ((width2 * tileh + 1) >> 1) - 1, 0);
   1266 
   1267                     gDPPipeSync(GFX1++);
   1268                     gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_8b, ((width2 + 7) >> 3), 0,
   1269                                    G_TX_RENDERTILE , 0, 0, 0, 0, 0, 0, 0);
   1270 
   1271                     gDPSetTileSize(GFX1++, G_TX_RENDERTILE, 0, 0, ((width2 - 1) << 2), (tileh - 1) << 2);
   1272 
   1273                     yh = (tileh << 2) + y;
   1274 
   1275                     gSPTextureRectangle(GFX1++,
   1276                                     x, y,
   1277                                     (width << 2) + x, yh,
   1278                                     0,
   1279                                     0, 0,
   1280                                     (1 << 10), (1 << 10));
   1281 
   1282                     height -= tileh;
   1283                     if (height < tileh) {
   1284                         tileh = height;
   1285                     }
   1286 
   1287                     y = yh;
   1288 
   1289                     src += tilew;
   1290                     tilecnt += 1;
   1291                 } while (tilecnt != (int)tiles);
   1292             }
   1293 		}
   1294 	}
   1295 }