From efd016d031085831596ae9536480eb7cb4ea883b Mon Sep 17 00:00:00 2001 From: jndean Date: Sun, 12 Nov 2023 00:55:05 +0000 Subject: [PATCH] IPU renders skybox --- Makefile | 1 + src/ipu/ipu_interface.h | 1 + src/ipu/ipu_transfer.c | 2 + src/ipu/r_codelets.cpp | 3 + src/ipu/r_draw.c | 6 +- src/ipu/r_main.c | 14 +- src/ipu/r_main.h | 3 +- src/ipu/r_plane.c | 37 +- src/ipu/r_plane.h | 2 + src/ipu/r_segs.c | 6 +- src/ipu/r_sky.c | 3 + src/ipu/r_things.c | 849 ++++++++++++++++++++++++++++++++++++++++ src/ipu_transfer.c | 2 + src/m_menu.c | 19 +- 14 files changed, 905 insertions(+), 43 deletions(-) create mode 100644 src/ipu/r_things.c diff --git a/Makefile b/Makefile index 3ecb23a..e235ca5 100644 --- a/Makefile +++ b/Makefile @@ -27,6 +27,7 @@ IPU_OBJ = $(addprefix build/ipu_obj/, \ r_plane.gp \ r_segs.gp \ r_sky.gp \ + r_things.gp \ tables.gp \ v_video.gp \ w_wad.gp \ diff --git a/src/ipu/ipu_interface.h b/src/ipu/ipu_interface.h index d750c57..ee506f1 100644 --- a/src/ipu/ipu_interface.h +++ b/src/ipu/ipu_interface.h @@ -46,6 +46,7 @@ typedef struct { GameMode_t gamemode; int deathmatch; int skyflatnum; + int skytexture; boolean playeringame[MAXPLAYERS]; } G_LoadLevel_MiscValues_t; diff --git a/src/ipu/ipu_transfer.c b/src/ipu/ipu_transfer.c index b5c8771..d80d6d4 100644 --- a/src/ipu/ipu_transfer.c +++ b/src/ipu/ipu_transfer.c @@ -1,6 +1,7 @@ #include "doomstat.h" #include "r_defs.h" #include "r_state.h" +#include "r_sky.h" // #include "w_wad.h" #include "ipu_interface.h" @@ -22,6 +23,7 @@ void IPU_G_LoadLevel_UnpackMiscValues(G_LoadLevel_MiscValues_t* pack) { gamemode = pack->gamemode; deathmatch = pack->deathmatch; skyflatnum = pack->skyflatnum; + skytexture = pack->skytexture; for (int i = 0; i < MAXPLAYERS; ++i) { playeringame[i] = pack->playeringame[i]; } diff --git a/src/ipu/r_codelets.cpp b/src/ipu/r_codelets.cpp index 1338e12..1a2f4c9 100644 --- a/src/ipu/r_codelets.cpp +++ b/src/ipu/r_codelets.cpp @@ -13,6 +13,7 @@ extern "C" { __SUPER__ void R_InitTextures(int* maptex); + __SUPER__ void R_InitSkyMap(void); __SUPER__ void R_RenderPlayerView(player_t *player); __SUPER__ void R_ExecuteSetViewSize(void); }; @@ -51,6 +52,8 @@ struct R_Init_Vertex: public poplar::SupervisorVertex { R_InitTextures((int*)&lumpBuf[0]); IPU_R_InitColumnRequester(&progBuf[0], progBuf.size()); + R_InitSkyMap(); + *lumpNum = 0; step = 0; } diff --git a/src/ipu/r_draw.c b/src/ipu/r_draw.c index 89fca5c..2272a1c 100644 --- a/src/ipu/r_draw.c +++ b/src/ipu/r_draw.c @@ -494,7 +494,7 @@ void R_InitTranslationTables(void) { } } } - +*/ // // R_DrawSpan // With DOOM style restrictions on view orientation, @@ -527,6 +527,8 @@ int dscount; // // Draws the actual span. void R_DrawSpan(void) { + + /* LATER unsigned int position, step; pixel_t *dest; int count; @@ -565,8 +567,10 @@ void R_DrawSpan(void) { position += step; } while (count--); + */ } +/* // UNUSED. // Loop unrolled by 4. #if 0 diff --git a/src/ipu/r_main.c b/src/ipu/r_main.c index 7847a4c..2040511 100644 --- a/src/ipu/r_main.c +++ b/src/ipu/r_main.c @@ -109,13 +109,7 @@ angle_t xtoviewangle[SCREENWIDTH + 1]; // bumped light from gun blasts int extralight; -// void (*colfunc)(void); // JOSEF - -__SUPER__ -void colfunc() { // JOSEF: Don't call through pointer, explicit call - if (!detailshift) R_DrawColumn(); - // else R_DrawColumnLow(); // LATER -} +// void (*colfunc)(void); // JOSEF: No calling through pointer on IPU, replace with explicit calls void (*basecolfunc)(void); void (*fuzzcolfunc)(void); void (*transcolfunc)(void); @@ -640,18 +634,17 @@ void R_ExecuteSetViewSize(void) { R_InitTextureMapping(); - - /* LATER - // psprite scales pspritescale = FRACUNIT * viewwidth / SCREENWIDTH; pspriteiscale = FRACUNIT * SCREENWIDTH / viewwidth; + /* LATER // thing clipping for (i = 0; i < viewwidth; i++) screenheightarray[i] = viewheight; // planes + */ for (i = 0; i < viewheight; i++) { dy = ((i - viewheight / 2) << FRACBITS) + FRACUNIT / 2; dy = abs(dy); @@ -662,7 +655,6 @@ void R_ExecuteSetViewSize(void) { cosadj = abs(finecosine[xtoviewangle[i] >> ANGLETOFINESHIFT]); distscale[i] = FixedDiv(FRACUNIT, cosadj); } - */ // JOSEF: Texture tiles handle light levels // Calculate the light levels to use diff --git a/src/ipu/r_main.h b/src/ipu/r_main.h index 6eadbee..36c3d83 100644 --- a/src/ipu/r_main.h +++ b/src/ipu/r_main.h @@ -85,8 +85,7 @@ extern int detailshift; // Used to select shadow mode etc. // -// extern void (*colfunc)(void); // JOSEF -__SUPER__ void colfunc(void); // Don't want to call via pointer on IPU +// extern void (*colfunc)(void); // JOSEF: Don't want to call via pointer on IPU extern void (*transcolfunc)(void); extern void (*basecolfunc)(void); extern void (*fuzzcolfunc)(void); diff --git a/src/ipu/r_plane.c b/src/ipu/r_plane.c index 975f0b8..cad5d31 100644 --- a/src/ipu/r_plane.c +++ b/src/ipu/r_plane.c @@ -32,6 +32,7 @@ #include "r_draw.h" #include "r_main.h" #include "r_plane.h" +#include "r_segs.h" #include "r_sky.h" #include "r_state.h" #include "r_things.h" @@ -40,6 +41,7 @@ // #include "z_zone.h" // LATER #include "ipu_interface.h" +#include "ipu_texturetiles.h" #include "print.h" @@ -52,7 +54,7 @@ planefunction_t ceilingfunc; // // Here comes the obnoxious "visplane". -#define MAXVISPLANES 128 +#define MAXVISPLANES 48 // JOSEF: 128 visplane_t visplanes[MAXVISPLANES]; visplane_t *lastvisplane; visplane_t *floorplane; @@ -89,6 +91,7 @@ fixed_t distscale[SCREENWIDTH]; fixed_t basexscale; fixed_t baseyscale; +// JOSEF: Tbh, could forgo these caches and just recompute every time on IPU? fixed_t cachedheight[SCREENHEIGHT]; fixed_t cacheddistance[SCREENHEIGHT]; fixed_t cachedxstep[SCREENHEIGHT]; @@ -107,7 +110,6 @@ void R_InitPlanes(void) { // Doh! } -/* // // R_MapPlane // @@ -121,6 +123,7 @@ void R_InitPlanes(void) { // // BASIC PRIMITIVE // +__SUPER__ void R_MapPlane(int y, int x1, int x2) { angle_t angle; fixed_t distance; @@ -128,7 +131,7 @@ void R_MapPlane(int y, int x1, int x2) { unsigned index; if (x2 < x1 || x1 < 0 || x2 >= viewwidth || y > viewheight) { - I_Error("R_MapPlane: %i, %i at %i", x1, x2, y); + printf("ERROR: R_MapPlane: %d, %d at %d", x1, x2, y); } if (planeheight != cachedheight[y]) { @@ -147,6 +150,7 @@ void R_MapPlane(int y, int x1, int x2) { ds_xfrac = viewx + FixedMul(finecosine[angle], length); ds_yfrac = -viewy - FixedMul(finesine[angle], length); + /* LATER if (fixedcolormap) ds_colormap = fixedcolormap; else { @@ -157,15 +161,15 @@ void R_MapPlane(int y, int x1, int x2) { ds_colormap = planezlight[index]; } + */ ds_y = y; ds_x1 = x1; ds_x2 = x2; // high or low detail - spanfunc(); + // spanfunc(); // LATER } -*/ // // R_ClearPlanes @@ -288,10 +292,10 @@ visplane_t *R_CheckPlane(visplane_t *pl, int start, int stop) { return pl; } -/* // // R_MakeSpans // +__SUPER__ void R_MakeSpans(int x, int t1, int b1, int t2, int b2) { while (t1 < t2 && t1 <= b1) { R_MapPlane(t1, spanstart[t1], x - 1); @@ -311,7 +315,7 @@ void R_MakeSpans(int x, int t1, int b1, int t2, int b2) { b2--; } } -*/ + // // R_DrawPlanes @@ -326,7 +330,6 @@ void R_DrawPlanes(void) { int angle; int lumpnum; - // if (tileID == 0) asm("trap 0"); if (ds_p - drawsegs > MAXDRAWSEGS) printf("R_DrawPlanes: drawsegs overflow (%u)\n", ds_p - drawsegs); // I_Error("R_DrawPlanes: drawsegs overflow (%i)", ds_p - drawsegs); @@ -339,22 +342,21 @@ void R_DrawPlanes(void) { printf("R_DrawPlanes: opening overflow (%u)\n", lastopening - openings); // I_Error("R_DrawPlanes: opening overflow (%i)", lastopening - openings); - // printf("num visplanes = %d\n", lastvisplane - visplanes); - for (pl = visplanes; pl < lastvisplane; pl++) { if (pl->minx > pl->maxx) continue; // sky flat if (pl->picnum == skyflatnum) { - /* LATER dc_iscale = pspriteiscale >> detailshift; // Sky is allways drawn full bright, // i.e. colormaps[0] is used. // Because of this hack, sky is not affected // by INVUL inverse mapping. - dc_colormap = colormaps; + // dc_colormap = colormaps; // JOSEF: IPU sends light params to texture tiles instead + walllightindex = MAXLIGHTSCALE - 1; // JOSEF + lightnum = LIGHTLEVELS - 1; // JOSEF dc_texturemid = skytexturemid; for (x = pl->minx; x <= pl->maxx; x++) { dc_yl = pl->top[x]; @@ -363,11 +365,11 @@ void R_DrawPlanes(void) { if (dc_yl <= dc_yh) { angle = (viewangle + xtoviewangle[x]) >> ANGLETOSKYSHIFT; dc_x = x; - dc_source = R_GetColumn(skytexture, angle); - colfunc(); + // dc_source = R_GetColumn(skytexture, angle); // JOSEF + dc_source = IPU_R_RequestColumn(skytexture, angle); + R_DrawColumn(); // JOSEF: colfunc(); } } - */ continue; } @@ -393,9 +395,8 @@ void R_DrawPlanes(void) { stop = pl->maxx + 1; for (x = pl->minx; x <= stop; x++) { - // LATER - // R_MakeSpans(x, pl->top[x - 1], pl->bottom[x - 1], pl->top[x], - // pl->bottom[x]); + R_MakeSpans(x, pl->top[x - 1], pl->bottom[x - 1], pl->top[x], + pl->bottom[x]); // JOSEF: TMP solid colour visualisation // pixel_t colour = (140 + (pl - visplanes) * 2) % 256; diff --git a/src/ipu/r_plane.h b/src/ipu/r_plane.h index d880513..6e80c4d 100644 --- a/src/ipu/r_plane.h +++ b/src/ipu/r_plane.h @@ -23,6 +23,8 @@ #include "m_fixed.h" #include "r_defs.h" +#include "ipu_utils.h" + // Visplane related. extern short *lastopening; diff --git a/src/ipu/r_segs.c b/src/ipu/r_segs.c index fddfe19..e3c5634 100644 --- a/src/ipu/r_segs.c +++ b/src/ipu/r_segs.c @@ -269,7 +269,7 @@ void R_RenderSegLoop(void) { dc_texturemid = rw_midtexturemid; // dc_source = R_GetColumn(midtexture, texturecolumn); // JOSEF dc_source = IPU_R_RequestColumn(midtexture, texturecolumn); - colfunc(); + R_DrawColumn(); // JOSEF: colfunc(); ceilingclip[rw_x] = viewheight; floorclip[rw_x] = -1; } else { @@ -289,7 +289,7 @@ void R_RenderSegLoop(void) { // dc_source = R_GetColumn(toptexture, texturecolumn); // JOSEF dc_source = IPU_R_RequestColumn(toptexture, texturecolumn); - colfunc(); + R_DrawColumn(); // JOSEF: colfunc(); ceilingclip[rw_x] = mid; } else ceilingclip[rw_x] = yl - 1; @@ -314,7 +314,7 @@ void R_RenderSegLoop(void) { dc_texturemid = rw_bottomtexturemid; // dc_source = R_GetColumn(bottomtexture, texturecolumn); // JOSEF dc_source = IPU_R_RequestColumn(bottomtexture, texturecolumn); - colfunc(); + R_DrawColumn(); // JOSEF: colfunc(); floorclip[rw_x] = mid; } else floorclip[rw_x] = yh + 1; diff --git a/src/ipu/r_sky.c b/src/ipu/r_sky.c index 8cd326a..414e584 100644 --- a/src/ipu/r_sky.c +++ b/src/ipu/r_sky.c @@ -25,6 +25,8 @@ #include "m_fixed.h" #include "r_sky.h" +#include "ipu_utils.h" + // // sky mapping // @@ -36,6 +38,7 @@ int skytexturemid; // R_InitSkyMap // Called whenever the view size changes. // +__SUPER__ void R_InitSkyMap(void) { // skyflatnum = R_FlatNumForName ( SKYFLATNAME ); skytexturemid = SCREENHEIGHT / 2 * FRACUNIT; diff --git a/src/ipu/r_things.c b/src/ipu/r_things.c new file mode 100644 index 0000000..3fafe2b --- /dev/null +++ b/src/ipu/r_things.c @@ -0,0 +1,849 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// 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. +// +// DESCRIPTION: +// Refresh of things, i.e. objects represented by sprites. +// + +// #include +// #include +#include +#include +// #include + +#include "d_player.h" +#include "doomdef.h" +#include "doomstat.h" +#include "doomtype.h" +#include "i_swap.h" +#include "i_system.h" +#include "i_video.h" +#include "info.h" +#include "m_fixed.h" +#include "p_mobj.h" +#include "p_pspr.h" +#include "r_bsp.h" +#include "r_defs.h" +#include "r_draw.h" +#include "r_main.h" +#include "r_segs.h" +#include "r_state.h" +#include "r_things.h" +#include "tables.h" +#include "v_patch.h" +// #include "w_wad.h" +// #include "z_zone.h" + +#define MINZ (FRACUNIT * 4) +#define BASEYCENTER (SCREENHEIGHT / 2) + +// void R_DrawColumn (void); +// void R_DrawFuzzColumn (void); + +typedef struct { + int x1; + int x2; + + int column; + int topclip; + int bottomclip; + +} maskdraw_t; + +// +// Sprite rotation 0 is facing the viewer, +// rotation 1 is one angle turn CLOCKWISE around the axis. +// This is not the same as the angle, +// which increases counter clockwise (protractor). +// There was a lot of stuff grabbed wrong, so I changed it... +// +fixed_t pspritescale; +fixed_t pspriteiscale; + +lighttable_t **spritelights; + +// constant arrays +// used for psprite clipping and initializing clipping +short negonearray[SCREENWIDTH]; +short screenheightarray[SCREENWIDTH]; + +// +// INITIALIZATION FUNCTIONS +// + +// variables used to look up +// and range check thing_t sprites patches +spritedef_t *sprites; +int numsprites; + +spriteframe_t sprtemp[29]; +int maxframe; +char *spritename; + +/* +// +// R_InstallSpriteLump +// Local function for R_InitSprites. +// +void R_InstallSpriteLump(int lump, unsigned frame, unsigned rotation, + boolean flipped) { + int r; + + if (frame >= 29 || rotation > 8) + I_Error("R_InstallSpriteLump: " + "Bad frame characters in lump %i", + lump); + + if ((int)frame > maxframe) + maxframe = frame; + + if (rotation == 0) { + // the lump should be used for all rotations + if (sprtemp[frame].rotate == false) + I_Error("R_InitSprites: Sprite %s frame %c has " + "multip rot=0 lump", + spritename, 'A' + frame); + + if (sprtemp[frame].rotate == true) + I_Error("R_InitSprites: Sprite %s frame %c has rotations " + "and a rot=0 lump", + spritename, 'A' + frame); + + sprtemp[frame].rotate = false; + for (r = 0; r < 8; r++) { + sprtemp[frame].lump[r] = lump - firstspritelump; + sprtemp[frame].flip[r] = (byte)flipped; + } + return; + } + + // the lump is only used for one rotation + if (sprtemp[frame].rotate == false) + I_Error("R_InitSprites: Sprite %s frame %c has rotations " + "and a rot=0 lump", + spritename, 'A' + frame); + + sprtemp[frame].rotate = true; + + // make 0 based + rotation--; + if (sprtemp[frame].lump[rotation] != -1) + I_Error("R_InitSprites: Sprite %s : %c : %c " + "has two lumps mapped to it", + spritename, 'A' + frame, '1' + rotation); + + sprtemp[frame].lump[rotation] = lump - firstspritelump; + sprtemp[frame].flip[rotation] = (byte)flipped; +} + +// +// R_InitSpriteDefs +// Pass a null terminated list of sprite names +// (4 chars exactly) to be used. +// Builds the sprite rotation matrixes to account +// for horizontally flipped sprites. +// Will report an error if the lumps are inconsistant. +// Only called at startup. +// +// Sprite lump names are 4 characters for the actor, +// a letter for the frame, and a number for the rotation. +// A sprite that is flippable will have an additional +// letter/number appended. +// The rotation character can be 0 to signify no rotations. +// +void R_InitSpriteDefs(char **namelist) { + char **check; + int i; + int l; + int frame; + int rotation; + int start; + int end; + int patched; + + // count the number of sprite names + check = namelist; + while (*check != NULL) + check++; + + numsprites = check - namelist; + + if (!numsprites) + return; + + sprites = Z_Malloc(numsprites * sizeof(*sprites), PU_STATIC, NULL); + + start = firstspritelump - 1; + end = lastspritelump + 1; + + // scan all the lump names for each of the names, + // noting the highest frame letter. + // Just compare 4 characters as ints + for (i = 0; i < numsprites; i++) { + spritename = (namelist[i]); + memset(sprtemp, -1, sizeof(sprtemp)); + + maxframe = -1; + + // scan the lumps, + // filling in the frames for whatever is found + for (l = start + 1; l < end; l++) { + if (!strncasecmp(lumpinfo[l]->name, spritename, 4)) { + frame = lumpinfo[l]->name[4] - 'A'; + rotation = lumpinfo[l]->name[5] - '0'; + + if (modifiedgame) + patched = W_GetNumForName(lumpinfo[l]->name); + else + patched = l; + + R_InstallSpriteLump(patched, frame, rotation, false); + + if (lumpinfo[l]->name[6]) { + frame = lumpinfo[l]->name[6] - 'A'; + rotation = lumpinfo[l]->name[7] - '0'; + R_InstallSpriteLump(l, frame, rotation, true); + } + } + } + + // check the frames that were found for completeness + if (maxframe == -1) { + sprites[i].numframes = 0; + continue; + } + + maxframe++; + + for (frame = 0; frame < maxframe; frame++) { + switch ((int)sprtemp[frame].rotate) { + case -1: + // no rotations were found for that frame at all + I_Error("R_InitSprites: No patches found " + "for %s frame %c", + spritename, frame + 'A'); + break; + + case 0: + // only the first rotation is needed + break; + + case 1: + // must have all 8 frames + for (rotation = 0; rotation < 8; rotation++) + if (sprtemp[frame].lump[rotation] == -1) + I_Error("R_InitSprites: Sprite %s frame %c " + "is missing rotations", + spritename, frame + 'A'); + break; + } + } + + // allocate space for the frames present and copy sprtemp to it + sprites[i].numframes = maxframe; + sprites[i].spriteframes = + Z_Malloc(maxframe * sizeof(spriteframe_t), PU_STATIC, NULL); + memcpy(sprites[i].spriteframes, sprtemp, maxframe * sizeof(spriteframe_t)); + } +} + +// +// GAME FUNCTIONS +// +vissprite_t vissprites[MAXVISSPRITES]; +vissprite_t *vissprite_p; +int newvissprite; + +// +// R_InitSprites +// Called at program start. +// +void R_InitSprites(char **namelist) { + int i; + + for (i = 0; i < SCREENWIDTH; i++) { + negonearray[i] = -1; + } + + R_InitSpriteDefs(namelist); +} + +// +// R_ClearSprites +// Called at frame start. +// +void R_ClearSprites(void) { vissprite_p = vissprites; } + +// +// R_NewVisSprite +// +vissprite_t overflowsprite; + +vissprite_t *R_NewVisSprite(void) { + if (vissprite_p == &vissprites[MAXVISSPRITES]) + return &overflowsprite; + + vissprite_p++; + return vissprite_p - 1; +} + +// +// R_DrawMaskedColumn +// Used for sprites and masked mid textures. +// Masked means: partly transparent, i.e. stored +// in posts/runs of opaque pixels. +// +short *mfloorclip; +short *mceilingclip; + +fixed_t spryscale; +fixed_t sprtopscreen; + +void R_DrawMaskedColumn(column_t *column) { + int topscreen; + int bottomscreen; + fixed_t basetexturemid; + + basetexturemid = dc_texturemid; + + for (; column->topdelta != 0xff;) { + // calculate unclipped screen coordinates + // for post + topscreen = sprtopscreen + spryscale * column->topdelta; + bottomscreen = topscreen + spryscale * column->length; + + dc_yl = (topscreen + FRACUNIT - 1) >> FRACBITS; + dc_yh = (bottomscreen - 1) >> FRACBITS; + + if (dc_yh >= mfloorclip[dc_x]) + dc_yh = mfloorclip[dc_x] - 1; + if (dc_yl <= mceilingclip[dc_x]) + dc_yl = mceilingclip[dc_x] + 1; + + if (dc_yl <= dc_yh) { + dc_source = (byte *)column + 3; + dc_texturemid = basetexturemid - (column->topdelta << FRACBITS); + // dc_source = (byte *)column + 3 - column->topdelta; + + // Drawn by either R_DrawColumn + // or (SHADOW) R_DrawFuzzColumn. + colfunc(); + } + column = (column_t *)((byte *)column + column->length + 4); + } + + dc_texturemid = basetexturemid; +} + +// +// R_DrawVisSprite +// mfloorclip and mceilingclip should also be set. +// +void R_DrawVisSprite(vissprite_t *vis, int x1, int x2) { + column_t *column; + int texturecolumn; + fixed_t frac; + patch_t *patch; + + patch = W_CacheLumpNum(vis->patch + firstspritelump, PU_CACHE); + + dc_colormap = vis->colormap; + + if (!dc_colormap) { + // NULL colormap = shadow draw + colfunc = fuzzcolfunc; + } else if (vis->mobjflags & MF_TRANSLATION) { + colfunc = transcolfunc; + dc_translation = translationtables - 256 + + ((vis->mobjflags & MF_TRANSLATION) >> (MF_TRANSSHIFT - 8)); + } + + dc_iscale = abs(vis->xiscale) >> detailshift; + dc_texturemid = vis->texturemid; + frac = vis->startfrac; + spryscale = vis->scale; + sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale); + + for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale) { + texturecolumn = frac >> FRACBITS; + if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) + I_Error("R_DrawSpriteRange: bad texturecolumn"); + column = + (column_t *)((byte *)patch + LONG(patch->columnofs[texturecolumn])); + R_DrawMaskedColumn(column); + } + + colfunc = basecolfunc; +} + +// +// R_ProjectSprite +// Generates a vissprite for a thing +// if it might be visible. +// +void R_ProjectSprite(mobj_t *thing) { + fixed_t tr_x; + fixed_t tr_y; + + fixed_t gxt; + fixed_t gyt; + + fixed_t tx; + fixed_t tz; + + fixed_t xscale; + + int x1; + int x2; + + spritedef_t *sprdef; + spriteframe_t *sprframe; + int lump; + + unsigned rot; + boolean flip; + + int index; + + vissprite_t *vis; + + angle_t ang; + fixed_t iscale; + + // transform the origin point + tr_x = thing->x - viewx; + tr_y = thing->y - viewy; + + gxt = FixedMul(tr_x, viewcos); + gyt = -FixedMul(tr_y, viewsin); + + tz = gxt - gyt; + + // thing is behind view plane? + if (tz < MINZ) + return; + + xscale = FixedDiv(projection, tz); + + gxt = -FixedMul(tr_x, viewsin); + gyt = FixedMul(tr_y, viewcos); + tx = -(gyt + gxt); + + // too far off the side? + if (abs(tx) > (tz << 2)) + return; + + // decide which patch to use for sprite relative to player + if ((unsigned int)thing->sprite >= (unsigned int)numsprites) + I_Error("R_ProjectSprite: invalid sprite number %i ", thing->sprite); + sprdef = &sprites[thing->sprite]; + if ((thing->frame & FF_FRAMEMASK) >= sprdef->numframes) + I_Error("R_ProjectSprite: invalid sprite frame %i : %i ", thing->sprite, + thing->frame); + sprframe = &sprdef->spriteframes[thing->frame & FF_FRAMEMASK]; + + if (sprframe->rotate) { + // choose a different rotation based on player view + ang = R_PointToAngle(thing->x, thing->y); + rot = (ang - thing->angle + (unsigned)(ANG45 / 2) * 9) >> 29; + lump = sprframe->lump[rot]; + flip = (boolean)sprframe->flip[rot]; + } else { + // use single rotation for all views + lump = sprframe->lump[0]; + flip = (boolean)sprframe->flip[0]; + } + + // calculate edges of the shape + tx -= spriteoffset[lump]; + x1 = (centerxfrac + FixedMul(tx, xscale)) >> FRACBITS; + + // off the right side? + if (x1 > viewwidth) + return; + + tx += spritewidth[lump]; + x2 = ((centerxfrac + FixedMul(tx, xscale)) >> FRACBITS) - 1; + + // off the left side + if (x2 < 0) + return; + + // store information in a vissprite + vis = R_NewVisSprite(); + vis->mobjflags = thing->flags; + vis->scale = xscale << detailshift; + vis->gx = thing->x; + vis->gy = thing->y; + vis->gz = thing->z; + vis->gzt = thing->z + spritetopoffset[lump]; + vis->texturemid = vis->gzt - viewz; + vis->x1 = x1 < 0 ? 0 : x1; + vis->x2 = x2 >= viewwidth ? viewwidth - 1 : x2; + iscale = FixedDiv(FRACUNIT, xscale); + + if (flip) { + vis->startfrac = spritewidth[lump] - 1; + vis->xiscale = -iscale; + } else { + vis->startfrac = 0; + vis->xiscale = iscale; + } + + if (vis->x1 > x1) + vis->startfrac += vis->xiscale * (vis->x1 - x1); + vis->patch = lump; + + // get light level + if (thing->flags & MF_SHADOW) { + // shadow draw + vis->colormap = NULL; + } else if (fixedcolormap) { + // fixed map + vis->colormap = fixedcolormap; + } else if (thing->frame & FF_FULLBRIGHT) { + // full bright + vis->colormap = colormaps; + } + + else { + // diminished light + index = xscale >> (LIGHTSCALESHIFT - detailshift); + + if (index >= MAXLIGHTSCALE) + index = MAXLIGHTSCALE - 1; + + vis->colormap = spritelights[index]; + } +} + +// +// R_AddSprites +// During BSP traversal, this adds sprites by sector. +// +void R_AddSprites(sector_t *sec) { + mobj_t *thing; + int lightnum; + + // BSP is traversed by subsector. + // A sector might have been split into several + // subsectors during BSP building. + // Thus we check whether its already added. + if (sec->validcount == validcount) + return; + + // Well, now it will be done. + sec->validcount = validcount; + + lightnum = (sec->lightlevel >> LIGHTSEGSHIFT) + extralight; + + if (lightnum < 0) + spritelights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + spritelights = scalelight[LIGHTLEVELS - 1]; + else + spritelights = scalelight[lightnum]; + + // Handle all things in sector. + for (thing = sec->thinglist; thing; thing = thing->snext) + R_ProjectSprite(thing); +} + +// +// R_DrawPSprite +// +void R_DrawPSprite(pspdef_t *psp) { + fixed_t tx; + int x1; + int x2; + spritedef_t *sprdef; + spriteframe_t *sprframe; + int lump; + boolean flip; + vissprite_t *vis; + vissprite_t avis; + + // decide which patch to use + if ((unsigned)psp->state->sprite >= (unsigned int)numsprites) + I_Error("R_ProjectSprite: invalid sprite number %i ", psp->state->sprite); + sprdef = &sprites[psp->state->sprite]; + if ((psp->state->frame & FF_FRAMEMASK) >= sprdef->numframes) + I_Error("R_ProjectSprite: invalid sprite frame %i : %i ", + psp->state->sprite, psp->state->frame); + sprframe = &sprdef->spriteframes[psp->state->frame & FF_FRAMEMASK]; + + lump = sprframe->lump[0]; + flip = (boolean)sprframe->flip[0]; + + // calculate edges of the shape + tx = psp->sx - (SCREENWIDTH / 2) * FRACUNIT; + + tx -= spriteoffset[lump]; + x1 = (centerxfrac + FixedMul(tx, pspritescale)) >> FRACBITS; + + // off the right side + if (x1 > viewwidth) + return; + + tx += spritewidth[lump]; + x2 = ((centerxfrac + FixedMul(tx, pspritescale)) >> FRACBITS) - 1; + + // off the left side + if (x2 < 0) + return; + + // store information in a vissprite + vis = &avis; + vis->mobjflags = 0; + vis->texturemid = (BASEYCENTER << FRACBITS) + FRACUNIT / 2 - + (psp->sy - spritetopoffset[lump]); + vis->x1 = x1 < 0 ? 0 : x1; + vis->x2 = x2 >= viewwidth ? viewwidth - 1 : x2; + vis->scale = pspritescale << detailshift; + + if (flip) { + vis->xiscale = -pspriteiscale; + vis->startfrac = spritewidth[lump] - 1; + } else { + vis->xiscale = pspriteiscale; + vis->startfrac = 0; + } + + if (vis->x1 > x1) + vis->startfrac += vis->xiscale * (vis->x1 - x1); + + vis->patch = lump; + + if (viewplayer->powers[pw_invisibility] > 4 * 32 || + viewplayer->powers[pw_invisibility] & 8) { + // shadow draw + vis->colormap = NULL; + } else if (fixedcolormap) { + // fixed color + vis->colormap = fixedcolormap; + } else if (psp->state->frame & FF_FULLBRIGHT) { + // full bright + vis->colormap = colormaps; + } else { + // local light + vis->colormap = spritelights[MAXLIGHTSCALE - 1]; + } + + R_DrawVisSprite(vis, vis->x1, vis->x2); +} + +// +// R_DrawPlayerSprites +// +void R_DrawPlayerSprites(void) { + int i; + int lightnum; + pspdef_t *psp; + + // get light level + lightnum = (viewplayer->mo->subsector->sector->lightlevel >> LIGHTSEGSHIFT) + + extralight; + + if (lightnum < 0) + spritelights = scalelight[0]; + else if (lightnum >= LIGHTLEVELS) + spritelights = scalelight[LIGHTLEVELS - 1]; + else + spritelights = scalelight[lightnum]; + + // clip to screen bounds + mfloorclip = screenheightarray; + mceilingclip = negonearray; + + // add all active psprites + for (i = 0, psp = viewplayer->psprites; i < NUMPSPRITES; i++, psp++) { + if (psp->state) + R_DrawPSprite(psp); + } +} + +// +// R_SortVisSprites +// +vissprite_t vsprsortedhead; + +void R_SortVisSprites(void) { + int i; + int count; + vissprite_t *ds; + vissprite_t *best; + vissprite_t unsorted; + fixed_t bestscale; + + count = vissprite_p - vissprites; + + unsorted.next = unsorted.prev = &unsorted; + + if (!count) + return; + + for (ds = vissprites; ds < vissprite_p; ds++) { + ds->next = ds + 1; + ds->prev = ds - 1; + } + + vissprites[0].prev = &unsorted; + unsorted.next = &vissprites[0]; + (vissprite_p - 1)->next = &unsorted; + unsorted.prev = vissprite_p - 1; + + // pull the vissprites out by scale + + vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead; + for (i = 0; i < count; i++) { + bestscale = INT_MAX; + best = unsorted.next; + for (ds = unsorted.next; ds != &unsorted; ds = ds->next) { + if (ds->scale < bestscale) { + bestscale = ds->scale; + best = ds; + } + } + best->next->prev = best->prev; + best->prev->next = best->next; + best->next = &vsprsortedhead; + best->prev = vsprsortedhead.prev; + vsprsortedhead.prev->next = best; + vsprsortedhead.prev = best; + } +} + +// +// R_DrawSprite +// +void R_DrawSprite(vissprite_t *spr) { + drawseg_t *ds; + short clipbot[SCREENWIDTH]; + short cliptop[SCREENWIDTH]; + int x; + int r1; + int r2; + fixed_t scale; + fixed_t lowscale; + int silhouette; + + for (x = spr->x1; x <= spr->x2; x++) + clipbot[x] = cliptop[x] = -2; + + // Scan drawsegs from end to start for obscuring segs. + // The first drawseg that has a greater scale + // is the clip seg. + for (ds = ds_p - 1; ds >= drawsegs; ds--) { + // determine if the drawseg obscures the sprite + if (ds->x1 > spr->x2 || ds->x2 < spr->x1 || + (!ds->silhouette && !ds->maskedtexturecol)) { + // does not cover sprite + continue; + } + + r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1; + r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2; + + if (ds->scale1 > ds->scale2) { + lowscale = ds->scale2; + scale = ds->scale1; + } else { + lowscale = ds->scale1; + scale = ds->scale2; + } + + if (scale < spr->scale || + (lowscale < spr->scale && + !R_PointOnSegSide(spr->gx, spr->gy, ds->curline))) { + // masked mid texture? + if (ds->maskedtexturecol) + R_RenderMaskedSegRange(ds, r1, r2); + // seg is behind sprite + continue; + } + + // clip this piece of the sprite + silhouette = ds->silhouette; + + if (spr->gz >= ds->bsilheight) + silhouette &= ~SIL_BOTTOM; + + if (spr->gzt <= ds->tsilheight) + silhouette &= ~SIL_TOP; + + if (silhouette == 1) { + // bottom sil + for (x = r1; x <= r2; x++) + if (clipbot[x] == -2) + clipbot[x] = ds->sprbottomclip[x]; + } else if (silhouette == 2) { + // top sil + for (x = r1; x <= r2; x++) + if (cliptop[x] == -2) + cliptop[x] = ds->sprtopclip[x]; + } else if (silhouette == 3) { + // both + for (x = r1; x <= r2; x++) { + if (clipbot[x] == -2) + clipbot[x] = ds->sprbottomclip[x]; + if (cliptop[x] == -2) + cliptop[x] = ds->sprtopclip[x]; + } + } + } + + // all clipping has been performed, so draw the sprite + + // check for unclipped columns + for (x = spr->x1; x <= spr->x2; x++) { + if (clipbot[x] == -2) + clipbot[x] = viewheight; + + if (cliptop[x] == -2) + cliptop[x] = -1; + } + + mfloorclip = clipbot; + mceilingclip = cliptop; + R_DrawVisSprite(spr, spr->x1, spr->x2); +} + +// +// R_DrawMasked +// +void R_DrawMasked(void) { + vissprite_t *spr; + drawseg_t *ds; + + R_SortVisSprites(); + + if (vissprite_p > vissprites) { + // draw all vissprites back to front + for (spr = vsprsortedhead.next; spr != &vsprsortedhead; spr = spr->next) { + + R_DrawSprite(spr); + } + } + + // render any remaining masked mid textures + for (ds = ds_p - 1; ds >= drawsegs; ds--) + if (ds->maskedtexturecol) + R_RenderMaskedSegRange(ds, ds->x1, ds->x2); + + // draw the psprites on top of everything + // but does not draw on side views + if (!viewangleoffset) + R_DrawPlayerSprites(); +} +*/ \ No newline at end of file diff --git a/src/ipu_transfer.c b/src/ipu_transfer.c index 44a0176..9ea1564 100644 --- a/src/ipu_transfer.c +++ b/src/ipu_transfer.c @@ -10,6 +10,7 @@ #include "m_misc.h" #include "r_defs.h" #include "r_state.h" +#include "r_sky.h" #include "v_patch.h" #include "w_wad.h" #include "z_zone.h" @@ -30,6 +31,7 @@ void IPU_G_LoadLevel_PackMiscValues(void* buf) { pack.gamemode = gamemode; pack.deathmatch = deathmatch; pack.skyflatnum = skyflatnum; + pack.skytexture = skytexture; for (int i = 0; i < MAXPLAYERS; ++i) pack.playeringame[i] = playeringame[i]; diff --git a/src/m_menu.c b/src/m_menu.c index a961dfd..96baf4b 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -846,6 +846,7 @@ void M_ChangeSensitivity(int choice) { } void M_ChangeDetail(int choice) { + return; // JOSEF: Unsupported on IPU choice = 0; detailLevel = 1 - detailLevel; @@ -1241,17 +1242,19 @@ boolean M_Responder(event_t *ev) { if (!menuactive) { if (key == key_menu_decscreen) // Screen size down { - if (automapactive || chat_on) - return false; - M_SizeDisplay(0); - S_StartSound(NULL, sfx_stnmov); + // JOSEF: Unsupported on IPU + // if (automapactive || chat_on) + // return false; + // M_SizeDisplay(0); + // S_StartSound(NULL, sfx_stnmov); return true; } else if (key == key_menu_incscreen) // Screen size up { - if (automapactive || chat_on) - return false; - M_SizeDisplay(1); - S_StartSound(NULL, sfx_stnmov); + // JOSEF: Unsupported on IPU + // if (automapactive || chat_on) + // return false; + // M_SizeDisplay(1); + // S_StartSound(NULL, sfx_stnmov); return true; } else if (key == key_menu_help) // Help key {