diff --git a/configure.ac b/configure.ac index b77fa22ec..fd97550c7 100644 --- a/configure.ac +++ b/configure.ac @@ -1199,7 +1199,7 @@ dnl ================================================================== AC_ARG_WITH(clients, [ --with-clients= compile clients in ; - 3dfx,fbdev,glx,mgl,sdl,sgl,svga,wgl,x11], + 3dfx,fbdev,glx,mgl,sdl,sdl32,sgl,svga,wgl,x11], clients="$withval", clients="all" ) @@ -1209,6 +1209,7 @@ if test "$clients" = "all"; then ENABLE_GLX=yes ENABLE_MGL=yes ENABLE_SDL=yes + ENABLE_SDL32=yes ENABLE_SGL=yes ENABLE_SVGA=yes ENABLE_WGL=yes @@ -1219,6 +1220,7 @@ else ENABLE_GLX=no ENABLE_MGL=no ENABLE_SDL=no + ENABLE_SDL32=no ENABLE_SGL=no ENABLE_SVGA=no ENABLE_WGL=no @@ -1241,6 +1243,9 @@ else sdl) ENABLE_SDL=yes ;; + sdl32) + ENABLE_SDL32=yes + ;; sgl) ENABLE_SGL=yes ;; @@ -1274,8 +1279,10 @@ VID_TARGETS="" BUILD_SND_RENDERER=no BUILD_GL=no BUILD_SW=no +BUILD_SW32=no CAN_BUILD_GL=no CAN_BUILD_SW=no +CAN_BUILD_SW32=no HAVE_3DFX=no HAVE_GLX=no @@ -1330,6 +1337,14 @@ if test "x$HAVE_SDL" = xyes; then BUILD_SW=yes fi CAN_BUILD_SW=yes + if test "x$ENABLE_SDL32" = xyes; then + QW_TARGETS="$QW_TARGETS qw-client-sdl32\$(EXEEXT)" + NQ_TARGETS="$NQ_TARGETS nq-sdl32\$(EXEEXT)" + CL_TARGETS="$CL_TARGETS SDL32" + VID_TARGETS="$VID_TARGETS libQFsdl32.la" + BUILD_SW32=yes + fi + CAN_BUILD_SW32=yes fi if test "x$HAVE_SGL" = xyes; then if test "x$ENABLE_SGL" = xyes; then @@ -1378,6 +1393,7 @@ fi AC_SUBST(CAN_BUILD_GL) AC_SUBST(CAN_BUILD_SW) +AC_SUBST(CAN_BUILD_SW32) AC_SUBST(HAVE_3DFX) AC_SUBST(HAVE_FBDEV) @@ -1437,6 +1453,7 @@ AC_SUBST(VID_TARGETS) AM_CONDITIONAL(BUILD_SND_RENDERER, test "$BUILD_SND_RENDERER" = "yes") AM_CONDITIONAL(BUILD_GL, test "$BUILD_GL" = "yes") AM_CONDITIONAL(BUILD_SW, test "$BUILD_SW" = "yes") +AM_CONDITIONAL(BUILD_SW32, test "$BUILD_SW32" = "yes") dnl Output files AC_OUTPUT( @@ -1468,6 +1485,7 @@ AC_OUTPUT( libs/video/renderer/Makefile libs/video/renderer/gl/Makefile libs/video/renderer/sw/Makefile + libs/video/renderer/sw32/Makefile libs/video/targets/Makefile qw/Makefile diff --git a/include/QF/draw.h b/include/QF/draw.h index 2d337ce46..db61f48a7 100644 --- a/include/QF/draw.h +++ b/include/QF/draw.h @@ -35,7 +35,7 @@ extern qpic_t *draw_disc; // also used on sbar void Draw_Init (void); void Draw_Init_Cvars (void); -void Draw_Character8 (int x, int y, int num); +void Draw_Character (int x, int y, int num); void Draw_Pic (int x, int y, qpic_t *pic); void Draw_SubPic(int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height); void Draw_TextBox (int x, int y, int width, int lines); @@ -48,8 +48,8 @@ void Draw_EndDisc (void); void Draw_TileClear (int x, int y, int w, int h); void Draw_Fill (int x, int y, int w, int h, int c); void Draw_FadeScreen (void); -void Draw_String8 (int x, int y, const char *str); -void Draw_AltString8 (int x, int y, const char *str); +void Draw_String (int x, int y, const char *str); +void Draw_AltString (int x, int y, const char *str); qpic_t *Draw_PicFromWad (const char *name); qpic_t *Draw_CachePic (const char *path, qboolean alpha); diff --git a/include/QF/qtypes.h b/include/QF/qtypes.h index 30ad898e0..a44eceadc 100644 --- a/include/QF/qtypes.h +++ b/include/QF/qtypes.h @@ -71,6 +71,4 @@ typedef struct mplane_s { byte pad[2]; } mplane_t; -typedef byte pixel_t; - #endif // __qtypes_h diff --git a/include/QF/skin.h b/include/QF/skin.h index fb017282a..564693b69 100644 --- a/include/QF/skin.h +++ b/include/QF/skin.h @@ -55,19 +55,20 @@ extern int skin_textures; extern int skin_fb_textures; struct tex_s; +struct tex_s *Skin_Cache (skin_t *skin); struct player_info_s; struct model_s; void Skin_Find (struct player_info_s *sc); -struct tex_s *Skin_Cache (skin_t *skin); void Skin_Flush (void); int Skin_Init_Textures (int base); void Skin_Init (void); void Skin_Init_Cvars (void); void Skin_Init_Translation (void); -void Skin_Set_Translate (int top, int bottom, byte *dest); +void Skin_Set_Translate (int top, int bottom, void *_dest); void Skin_Do_Translation (skin_t *player_skin, int slot, skin_t *skin); -void Skin_Do_Translation_Model (struct model_s *model, int skinnum, int slot, skin_t *skin); +void Skin_Do_Translation_Model (struct model_s *model, int skinnum, + int slot, skin_t *skin); void Skin_Process (skin_t *skin, struct tex_s *); skin_t *Skin_NewTempSkin (void); diff --git a/include/QF/vid.h b/include/QF/vid.h index 3476870b7..bc2fcaa30 100644 --- a/include/QF/vid.h +++ b/include/QF/vid.h @@ -39,37 +39,38 @@ extern byte *vid_basepal; extern byte *vid_colormap; typedef struct vrect_s { - int x,y,width,height; + int x,y,width,height; struct vrect_s *pnext; } vrect_t; typedef struct { - qboolean initialized; - pixel_t *buffer; // invisible buffer + qboolean initialized; + void *buffer; // invisible buffer short *zbuffer; void *surfcache; - pixel_t *colormap; // 256 * VID_GRADES size + byte *colormap8; // 256 * VID_GRADES size unsigned short *colormap16; // 256 * VID_GRADES size - int fullbright; // index of first fullbright color - unsigned int rowbytes; // may be > width if displayed in a window - unsigned int width; - unsigned int height; - float aspect; // width / height -- < 0 is taller than wide - int numpages; - qboolean recalc_refdef; // if true, recalc vid-based stuff - qboolean cshift_changed; - pixel_t *conbuffer; - int conrowbytes; - unsigned int conwidth; - unsigned int conheight; - int maxwarpwidth; - int maxwarpheight; - pixel_t *direct; // direct drawing to framebuffer, if not + unsigned int *colormap32; // 256 * VID_GRADES size + int fullbright; // index of first fullbright color + unsigned int rowbytes; // may be > width if displayed in a window + unsigned int width; + unsigned int height; + float aspect; // width / height -- < 0 is taller than wide + int numpages; + qboolean recalc_refdef; // if true, recalc vid-based stuff + qboolean cshift_changed; + void *conbuffer; + int conrowbytes; + unsigned int conwidth; + unsigned int conheight; + int maxwarpwidth; + int maxwarpheight; + byte *direct; // direct drawing to framebuffer, if not // NULL - int (*surf_cache_size)(int width, int height); - void (*flush_caches)(void); - void (*init_caches)(void *cache, int size); - void (*do_screen_buffer)(void); + int (*surf_cache_size)(int width, int height); + void (*flush_caches)(void); + void (*init_caches)(void *cache, int size); + void (*do_screen_buffer)(void); } viddef_t; extern viddef_t vid; // global video state diff --git a/include/d_iface.h b/include/d_iface.h index 3af3b96aa..751164bbe 100644 --- a/include/d_iface.h +++ b/include/d_iface.h @@ -224,7 +224,7 @@ extern void *acolormap; // FIXME: should go away typedef struct { - pixel_t *surfdat; // destination for generated surface + byte *surfdat; // destination for generated surface int rowbytes; // destination logical width in bytes msurface_t *surf; // description for surface to generate fixed8_t lightadj[MAXLIGHTMAPS]; diff --git a/include/d_local.h b/include/d_local.h index 0d119c366..ed7048d99 100644 --- a/include/d_local.h +++ b/include/d_local.h @@ -79,15 +79,15 @@ extern float d_sdivzorigin, d_tdivzorigin, d_ziorigin; extern fixed16_t sadjust, tadjust; extern fixed16_t bbextents, bbextentt; - +// FIXME: Better way of handling D_DrawSpans depths? +void D_DrawSpans (espan_t *pspans); void D_DrawSpans8 (espan_t *pspans); void D_DrawSpans16 (espan_t *pspans); void D_DrawZSpans (espan_t *pspans); -void Turbulent8 (espan_t *pspan); +void Turbulent (espan_t *pspan); void D_SpriteDrawSpans (sspan_t *pspan); -void D_DrawSkyScans8 (espan_t *pspan); -void D_DrawSkyScans16 (espan_t *pspan); +void D_DrawSkyScans (espan_t *pspan); void R_ShowSubDiv (void); void (*prealspandrawer)(void); @@ -104,18 +104,18 @@ extern short *d_pzbuffer; extern unsigned int d_zrowbytes, d_zwidth; extern int *d_pscantable; -extern int d_scantable[MAXHEIGHT]; +extern int d_scantable[MAXHEIGHT]; -extern int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle; +extern int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle; -extern int d_y_aspect_shift, d_pix_min, d_pix_max, d_pix_shift; +extern int d_y_aspect_shift, d_pix_min, d_pix_max, d_pix_shift; -extern pixel_t *d_viewbuffer; +extern byte *d_viewbuffer; -extern short *zspantable[MAXHEIGHT]; +extern short *zspantable[MAXHEIGHT]; -extern int d_minmip; -extern float d_scalemip[3]; +extern int d_minmip; +extern float d_scalemip[3]; extern void (*d_drawspans) (espan_t *pspan); diff --git a/include/r_shared.h b/include/r_shared.h index c9d604070..449a18496 100644 --- a/include/r_shared.h +++ b/include/r_shared.h @@ -54,10 +54,10 @@ extern void R_DrawLine (polyvert_t *polyvert0, polyvert_t *polyvert1); extern int cachewidth; -extern pixel_t *cacheblock; +extern byte *cacheblock; extern int screenwidth; -extern float pixelAspect; +extern float pixelAspect; extern int r_drawnpolycount; diff --git a/libs/console/client.c b/libs/console/client.c index 5569d8efe..a71dce74b 100644 --- a/libs/console/client.c +++ b/libs/console/client.c @@ -419,7 +419,7 @@ Con_DrawInput (void) y = con_vislines - 22; for (i = 0; i < con_linewidth; i++) - Draw_Character8 ((i + 1) << 3, con_vislines - 22, text[i]); + Draw_Character ((i + 1) << 3, con_vislines - 22, text[i]); } @@ -456,7 +456,7 @@ Con_DrawNotify (void) scr_copytop = 1; for (x = 0; x < con_linewidth; x++) - Draw_Character8 ((x + 1) << 3, v, text[x]); + Draw_Character ((x + 1) << 3, v, text[x]); v += 8; } @@ -466,10 +466,10 @@ Con_DrawNotify (void) scr_copytop = 1; if (chat_team) { - Draw_String8 (8, v, "say_team:"); + Draw_String (8, v, "say_team:"); skip = 11; } else { - Draw_String8 (8, v, "say:"); + Draw_String (8, v, "say:"); skip = 5; } @@ -478,12 +478,12 @@ Con_DrawNotify (void) s += chat_bufferlen - ((vid.width >> 3) - (skip + 1)); x = 0; while (s[x]) { - Draw_Character8 ((x + skip) << 3, v, s[x]); + Draw_Character ((x + skip) << 3, v, s[x]); x++; } -/*XXX - Draw_Character8 ((x + skip) << 3, v, - 10 + ((int) (realtime * con_cursorspeed) & 1)); +/* XXX + Draw_Character ((x + skip) << 3, v, + 10 + ((int) (realtime * con_cursorspeed) & 1)); */ v += 8; } @@ -524,7 +524,7 @@ Con_DrawConsole (int lines) if (con->display != con->current) { // draw arrows to show the buffer is backscrolled for (x = 0; x < con_linewidth; x += 4) - Draw_Character8 ((x + 1) << 3, y, '^'); + Draw_Character ((x + 1) << 3, y, '^'); y -= 8; rows--; @@ -540,7 +540,7 @@ Con_DrawConsole (int lines) text = con->text + (row % con_totallines) * con_linewidth; for (x = 0; x < con_linewidth; x++) - Draw_Character8 ((x + 1) << 3, y, text[x]); + Draw_Character ((x + 1) << 3, y, text[x]); } // draw the input prompt, user text, and cursor if desired @@ -597,7 +597,7 @@ Con_DrawDownload (int lines) // draw it y = lines - 22 + 8; for (i = 0; i < strlen (dlbar); i++) - Draw_Character8 ((i + 1) << 3, y, dlbar[i]); + Draw_Character ((i + 1) << 3, y, dlbar[i]); } static general_funcs_t plugin_info_general_funcs = { diff --git a/libs/models/Makefile.am b/libs/models/Makefile.am index a2e930106..db3ebc017 100644 --- a/libs/models/Makefile.am +++ b/libs/models/Makefile.am @@ -14,7 +14,13 @@ else MODELS_SW = endif -lib_LTLIBRARIES = libQFmodels.la $(MODELS_GL) $(MODELS_SW) +if BUILD_SW32 +MODELS_SW32 = libQFmodels_sw32.la +else +MODELS_SW32 = +endif + +lib_LTLIBRARIES = libQFmodels.la $(MODELS_GL) $(MODELS_SW) $(MODELS_SW32) models_SOURCES = clip_hull.c model.c @@ -33,4 +39,9 @@ libQFmodels_sw_la_LIBADD = alias/libalias_sw.la brush/libbrush_sw.la sprite/libs libQFmodels_sw_la_SOURCES = $(models_SOURCES) libQFmodels_sw_la_DEPENDENCIES = alias/libalias_sw.la brush/libbrush_sw.la sprite/libsprite_sw.la -LIBLIST = libQFmodels.la libQFmodels_gl.la libQFmodels_sw.la +libQFmodels_sw32_la_LDFLAGS = -version-info 1:0:0 +libQFmodels_sw32_la_LIBADD = alias/libalias_sw32.la brush/libbrush_sw32.la sprite/libsprite_sw32.la +libQFmodels_sw32_la_SOURCES = $(models_SOURCES) +libQFmodels_sw32_la_DEPENDENCIES = alias/libalias_sw32.la brush/libbrush_sw32.la sprite/libsprite_sw32.la + +LIBLIST = libQFmodels.la libQFmodels_gl.la libQFmodels_sw.la libQFmodels_sw32.la diff --git a/libs/models/alias/Makefile.am b/libs/models/alias/Makefile.am index e55aef543..93605f0c4 100644 --- a/libs/models/alias/Makefile.am +++ b/libs/models/alias/Makefile.am @@ -12,10 +12,19 @@ else ALIAS_SW = endif -noinst_LTLIBRARIES = $(ALIAS_GL) $(ALIAS_SW) +if BUILD_SW32 +ALIAS_SW32 = libalias_sw32.la +else +ALIAS_SW32 = +endif + +noinst_LTLIBRARIES = $(ALIAS_GL) $(ALIAS_SW) $(ALIAS_SW32) libalias_gl_la_LDFLAGS = -version-info 1:0:0 libalias_gl_la_SOURCES = gl_mesh.c gl_model_alias.c model_alias.c libalias_sw_la_LDFLAGS = -version-info 1:0:0 libalias_sw_la_SOURCES = sw_model_alias.c model_alias.c + +libalias_sw32_la_LDFLAGS = -version-info 1:0:0 +libalias_sw32_la_SOURCES = sw32_model_alias.c model_alias.c diff --git a/libs/models/alias/sw32_model_alias.c b/libs/models/alias/sw32_model_alias.c new file mode 100644 index 000000000..bfcc38b6c --- /dev/null +++ b/libs/models/alias/sw32_model_alias.c @@ -0,0 +1,289 @@ +/* + sw32_model_alias.c + + model loading and caching + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +// models are the only shared resource between a client and server running +// on the same machine. + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/model.h" +#include "QF/qendian.h" +#include "QF/sys.h" + +//#include "checksum.h" +#include "d_iface.h" +//#include "server.h" // DESPAIR + +extern char loadname[]; +extern model_t *loadmodel; + +/* + ALIAS MODELS +*/ + +extern aliashdr_t *pheader; + +extern stvert_t stverts[MAXALIASVERTS]; +extern mtriangle_t triangles[MAXALIASTRIS]; + +// a pose is a single set of vertexes. a frame may be +// an animating sequence of poses +extern trivertx_t *poseverts[MAXALIASFRAMES]; +extern int posenum; + + +void * +Mod_LoadSkin (byte * skin, int skinsize, int *pskinindex, int snum, int gnum) +{ + byte *pskin; +// unsigned short *pusskin; +// int i; + + // LordHavoc: model rendering expects skin in 8bit always + pskin = Hunk_AllocName (skinsize, loadname); + memcpy (pskin, skin, skinsize); + /* + pskin = Hunk_AllocName (skinsize * r_pixbytes, loadname); + + switch (r_pixbytes) { + case 1: + memcpy (pskin, skin, skinsize); + break; + case 2: + pusskin = (unsigned short *) skin; + for (i = 0; i < skinsize; i++) + pusskin[i] = d_8to16table[skin[i]]; + break; + default: + Sys_Error ("Mod_LoadAliasSkin: driver set invalid r_pixbytes: " + "%d\n", r_pixbytes); + break; + } + */ + *pskinindex = (byte *) pskin - (byte *) pheader; + return skin + skinsize; +} + +void * +Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int *pskinindex) +{ + int snum, gnum, t; + int skinsize; + byte *skin; + int groupskins; + daliasskingroup_t *pinskingroup; + daliasskininterval_t *pinskinintervals; + maliasskindesc_t *pskindesc; + maliasskingroup_t *paliasskingroup; + float *poutskinintervals; + + if (numskins < 1 || numskins > MAX_SKINS) + Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins); + + skinsize = pheader->mdl.skinwidth * pheader->mdl.skinheight; + pskindesc = Hunk_AllocName (numskins * sizeof (maliasskindesc_t), + loadname); + + pheader->skindesc = (byte *) pskindesc - (byte *) pheader; + + for (snum = 0; snum < numskins; snum++) { + if (pskintype->type == ALIAS_SKIN_SINGLE) { + skin = (byte *) (pskintype + 1); + skin = + Mod_LoadSkin (skin, skinsize, &pskindesc[snum].skin, snum, 0); + } else { + pskintype++; + pinskingroup = (daliasskingroup_t *) pskintype; + groupskins = LittleLong (pinskingroup->numskins); + + t = (int) &((maliasskingroup_t *) 0)->skindescs[groupskins]; + paliasskingroup = Hunk_AllocName (t, loadname); + paliasskingroup->numskins = groupskins; + + *pskinindex = (byte *) paliasskingroup - (byte *) pheader; + + pinskinintervals = (daliasskininterval_t *) (pinskingroup + 1); + poutskinintervals = + + Hunk_AllocName (groupskins * sizeof (float), loadname); + paliasskingroup->intervals = + (byte *) poutskinintervals - (byte *) pheader; + for (gnum = 0; gnum < groupskins; gnum++) { + *poutskinintervals = LittleFloat (pinskinintervals->interval); + if (*poutskinintervals <= 0) + Sys_Error ("Mod_LoadAliasSkinGroup: interval<=0"); + + poutskinintervals++; + pinskinintervals++; + } + + pskintype = (void *) pinskinintervals; + skin = (byte *) pskintype; + + for (gnum = 0; gnum < groupskins; gnum++) { + skin = + Mod_LoadSkin (skin, skinsize, + &paliasskingroup->skindescs[snum].skin, snum, + gnum); + } + } + pskintype = (daliasskintype_t *) skin; + } + + return pskintype; +} + +void +GL_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, int _s) +{ + int i, j; + stvert_t *pstverts; + mtriangle_t *ptri; + int numv = hdr->mdl.numverts; + int numt = hdr->mdl.numtris; + + pstverts = (stvert_t *) Hunk_AllocName (numv * sizeof (stvert_t), + loadname); + ptri = (mtriangle_t *) Hunk_AllocName (numt * sizeof (mtriangle_t), + loadname); + + hdr->stverts = (byte *) pstverts - (byte *) hdr; + hdr->triangles = (byte *) ptri - (byte *) hdr; + + for (i = 0; i < numv; i++) { + pstverts[i].onseam = stverts[i].onseam; + pstverts[i].s = stverts[i].s << 16; + pstverts[i].t = stverts[i].t << 16; + } + + for (i = 0; i < numt; i++) { + ptri[i].facesfront = triangles[i].facesfront; + for (j = 0; j < 3; j++) { + ptri[i].vertindex[j] = triangles[i].vertindex[j]; + } + } +} + +void * +Mod_LoadAliasFrame (void *pin, maliasframedesc_t *frame) +{ + trivertx_t *pframe, *pinframe; + int i, j; + daliasframe_t *pdaliasframe; + + pdaliasframe = (daliasframe_t *) pin; + + strcpy (frame->name, pdaliasframe->name); + + for (i = 0; i < 3; i++) { // byte values, don't worry about endianness + frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i]; + frame->bboxmax.v[i] = pdaliasframe->bboxmax.v[i]; + } + + pinframe = (trivertx_t *) (pdaliasframe + 1); + pframe = Hunk_AllocName (pheader->mdl.numverts * sizeof (*pframe), + loadname); + + frame->frame = (byte *) pframe - (byte *) pheader; + + for (j = 0; j < pheader->mdl.numverts; j++) { + int k; + + // these are all byte values, so no need to deal with endianness + pframe[j].lightnormalindex = pinframe[j].lightnormalindex; + + for (k = 0; k < 3; k++) { + pframe[j].v[k] = pinframe[j].v[k]; + } + } + + pinframe += pheader->mdl.numverts; + + return (void *) pinframe; +} + +void * +Mod_LoadAliasGroup (void *pin, maliasframedesc_t *frame) +{ + daliasgroup_t *pingroup; + maliasgroup_t *paliasgroup; + int i, numframes; + daliasinterval_t *pin_intervals; + float *poutintervals; + void *ptemp; + + pingroup = (daliasgroup_t *) pin; + + numframes = LittleLong (pingroup->numframes); + + paliasgroup = Hunk_AllocName (sizeof (maliasgroup_t) + (numframes - 1) * + sizeof (paliasgroup->frames[0]), loadname); + paliasgroup->numframes = numframes; + + for (i = 0; i < 3; i++) { + // these are byte values, so we don't have to worry about endianness + frame->bboxmin.v[i] = pingroup->bboxmin.v[i]; + frame->bboxmax.v[i] = pingroup->bboxmax.v[i]; + } + + frame->frame = (byte *) paliasgroup - (byte *) pheader; + + pin_intervals = (daliasinterval_t *) (pingroup + 1); + + poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname); + + paliasgroup->intervals = (byte *) poutintervals - (byte *) pheader; + + for (i = 0; i < numframes; i++) { + *poutintervals = LittleFloat (pin_intervals->interval); + if (*poutintervals <= 0.0) + Sys_Error ("Mod_LoadAliasGroup: interval<=0"); + + poutintervals++; + pin_intervals++; + } + + ptemp = (void *) pin_intervals; + + for (i = 0; i < numframes; i++) { + maliasframedesc_t temp_frame; + ptemp = Mod_LoadAliasFrame (ptemp, &temp_frame); + memcpy (&paliasgroup->frames[i], &temp_frame, + sizeof(paliasgroup->frames[i])); + } + + return ptemp; +} diff --git a/libs/models/alias/sw_model_alias.c b/libs/models/alias/sw_model_alias.c index b9ae4409d..18ed306b7 100644 --- a/libs/models/alias/sw_model_alias.c +++ b/libs/models/alias/sw_model_alias.c @@ -32,12 +32,11 @@ #ifdef HAVE_CONFIG_H # include "config.h" #endif - #ifdef HAVE_STRING_H -#include +# include #endif #ifdef HAVE_STRINGS_H -#include +# include #endif #include "QF/checksum.h" @@ -65,6 +64,7 @@ extern mtriangle_t triangles[MAXALIASTRIS]; extern trivertx_t *poseverts[MAXALIASFRAMES]; extern int posenum; + void * Mod_LoadSkin (byte * skin, int skinsize, int *pskinindex, int snum, int gnum) { @@ -92,9 +92,6 @@ Mod_LoadSkin (byte * skin, int skinsize, int *pskinindex, int snum, int gnum) return skin + skinsize; } -/* - Mod_LoadAllSkins -*/ void * Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int *pskinindex) { @@ -112,7 +109,8 @@ Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int *pskinindex) Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins); skinsize = pheader->mdl.skinwidth * pheader->mdl.skinheight; - pskindesc = Hunk_AllocName (numskins * sizeof (maliasskindesc_t), loadname); + pskindesc = Hunk_AllocName (numskins * sizeof (maliasskindesc_t), + loadname); pheader->skindesc = (byte *) pskindesc - (byte *) pheader; @@ -191,9 +189,6 @@ GL_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr, void *_m, int _s) } } -/* - Mod_LoadAliasFrame -*/ void * Mod_LoadAliasFrame (void *pin, maliasframedesc_t *frame) { @@ -212,7 +207,8 @@ Mod_LoadAliasFrame (void *pin, maliasframedesc_t *frame) } pinframe = (trivertx_t *) (pdaliasframe + 1); - pframe = Hunk_AllocName (pheader->mdl.numverts * sizeof (*pframe), loadname); + pframe = Hunk_AllocName (pheader->mdl.numverts * sizeof (*pframe), + loadname); frame->frame = (byte *) pframe - (byte *) pheader; @@ -232,10 +228,6 @@ Mod_LoadAliasFrame (void *pin, maliasframedesc_t *frame) return (void *) pinframe; } - -/* - Mod_LoadAliasGroup -*/ void * Mod_LoadAliasGroup (void *pin, maliasframedesc_t *frame) { diff --git a/libs/models/brush/Makefile.am b/libs/models/brush/Makefile.am index 8a527d6d0..82425320b 100644 --- a/libs/models/brush/Makefile.am +++ b/libs/models/brush/Makefile.am @@ -12,7 +12,13 @@ else BRUSH_SW = endif -noinst_LTLIBRARIES = $(BRUSH_GL) $(BRUSH_SW) libbrush.la +if BUILD_SW32 +BRUSH_SW32 = libbrush_sw32.la +else +BRUSH_SW32 = +endif + +noinst_LTLIBRARIES = $(BRUSH_GL) $(BRUSH_SW) $(BRUSH_SW32) libbrush.la libbrush_la_LDFLAGS = -version-info 1:0:0 libbrush_la_SOURCES = model_brush.c @@ -22,3 +28,6 @@ libbrush_gl_la_SOURCES = gl_model_brush.c model_brush.c libbrush_sw_la_LDFLAGS = -version-info 1:0:0 libbrush_sw_la_SOURCES = sw_model_brush.c model_brush.c + +libbrush_sw32_la_LDFLAGS = -version-info 1:0:0 +libbrush_sw32_la_SOURCES = sw32_model_brush.c model_brush.c diff --git a/libs/models/brush/model_brush.c b/libs/models/brush/model_brush.c index dd0fdc385..3b14794cb 100644 --- a/libs/models/brush/model_brush.c +++ b/libs/models/brush/model_brush.c @@ -41,7 +41,6 @@ #include - #include "QF/checksum.h" #include "QF/cvar.h" #include "QF/model.h" @@ -162,8 +161,8 @@ Mod_LoadTextures (lump_t *l) m->nummiptex = LittleLong (m->nummiptex); loadmodel->numtextures = m->nummiptex; - loadmodel->textures = - Hunk_AllocName (m->nummiptex * sizeof (*loadmodel->textures), loadname); + loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof + (*loadmodel->textures), loadname); for (i = 0; i < m->nummiptex; i++) { m->dataofs[i] = LittleLong (m->dataofs[i]); diff --git a/libs/models/brush/sw32_model_brush.c b/libs/models/brush/sw32_model_brush.c new file mode 100644 index 000000000..ce119af5f --- /dev/null +++ b/libs/models/brush/sw32_model_brush.c @@ -0,0 +1,70 @@ +/* + model_bursh.c + + model loading and caching + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +// models are the only shared resource between a client and server running +// on the same machine. + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/model.h" + +extern model_t *loadmodel; +extern char loadname[]; +extern byte *mod_base; + +const int mod_lightmap_bytes = 1; // was extern const int mod_lightmap_bytes; + + +void +GL_SubdivideSurface (msurface_t *fa) +{ +} + +void +Mod_ProcessTexture (miptex_t *mt, texture_t *tx) +{ +} + +void +Mod_LoadLighting (lump_t *l) +{ + if (!l->filelen) { + loadmodel->lightdata = NULL; + return; + } + loadmodel->lightdata = Hunk_AllocName (l->filelen, loadname); + memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen); +} diff --git a/libs/models/sprite/Makefile.am b/libs/models/sprite/Makefile.am index 3c62f6fd7..2471e5736 100644 --- a/libs/models/sprite/Makefile.am +++ b/libs/models/sprite/Makefile.am @@ -12,10 +12,19 @@ else SPRITE_SW = endif -noinst_LTLIBRARIES = $(SPRITE_GL) $(SPRITE_SW) +if BUILD_SW32 +SPRITE_SW32 = libsprite_sw32.la +else +SPRITE_SW32 = +endif + +noinst_LTLIBRARIES = $(SPRITE_GL) $(SPRITE_SW) $(SPRITE_SW32) libsprite_gl_la_LDFLAGS = -version-info 1:0:0 libsprite_gl_la_SOURCES = gl_model_sprite.c model_sprite.c libsprite_sw_la_LDFLAGS = -version-info 1:0:0 libsprite_sw_la_SOURCES = sw_model_sprite.c model_sprite.c + +libsprite_sw32_la_LDFLAGS = -version-info 1:0:0 +libsprite_sw32_la_SOURCES = sw32_model_sprite.c model_sprite.c diff --git a/libs/models/sprite/sw32_model_sprite.c b/libs/models/sprite/sw32_model_sprite.c new file mode 100644 index 000000000..df3fe24e2 --- /dev/null +++ b/libs/models/sprite/sw32_model_sprite.c @@ -0,0 +1,116 @@ +/* + sw_model_sprite.c + + model loading and caching + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +// models are the only shared resource between a client and server running +// on the same machine. + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/model.h" +#include "QF/qendian.h" +#include "QF/sys.h" + +#include "d_iface.h" + +extern model_t *loadmodel; +extern char loadname[]; + + +void * +Mod_LoadSpriteFrame (void *pin, mspriteframe_t **ppframe, int framenum) +{ + dspriteframe_t *pinframe; + mspriteframe_t *pspriteframe; + int width, height, size, origin[2]; +// int i; + + pinframe = (dspriteframe_t *) pin; + + width = LittleLong (pinframe->width); + height = LittleLong (pinframe->height); + size = width * height; + + // LordHavoc: sprite renderer uses 8bit pixels regardless of output + // (see note below) + pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t) + size, loadname); +// pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t) + size * r_pixbytes, loadname); + + memset (pspriteframe, 0, sizeof (mspriteframe_t) + size); + + *ppframe = pspriteframe; + + pspriteframe->width = width; + pspriteframe->height = height; + origin[0] = LittleLong (pinframe->origin[0]); + origin[1] = LittleLong (pinframe->origin[1]); + + pspriteframe->up = origin[1]; + pspriteframe->down = origin[1] - height; + pspriteframe->left = origin[0]; + pspriteframe->right = width + origin[0]; + + // LordHavoc: rewrote this and then realized that the sprite renderer uses + // pixel conversion anyway + memcpy (&pspriteframe->pixels[0], (byte *) (pinframe + 1), size); +/* + switch(r_pixbytes) { + case 1: + memcpy (&pspriteframe->pixels[0], (byte *) (pinframe + 1), size); + break; + case 2: + { + byte *ppixin = (byte *) (pinframe + 1); + unsigned short *ppixout = (unsigned short *) &pspriteframe->pixels[0]; + for (i = 0; i < size; i++) + ppixout[i] = d_8to16table[ppixin[i]]; + } + break; + case 4: + { + byte *ppixin = (byte *) (pinframe + 1); + unsigned int *ppixout = (int short *) &pspriteframe->pixels[0]; + for (i = 0; i < size; i++) + ppixout[i] = d_8to24table[ppixin[i]]; + } + break; + default: + Sys_Error("Mod_LoadSpriteFrame: unsupported r_pixbytes %i\n", + r_pixbytes); + } +*/ + + return (void *) ((byte *) pinframe + sizeof (dspriteframe_t) + size); +} diff --git a/libs/video/renderer/Makefile.am b/libs/video/renderer/Makefile.am index 958e2c47d..164919a60 100644 --- a/libs/video/renderer/Makefile.am +++ b/libs/video/renderer/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS= gl sw +SUBDIRS= gl sw sw32 INCLUDES= -I$(top_srcdir)/include if BUILD_GL @@ -13,7 +13,13 @@ else RENDERER_SW = endif -lib_LTLIBRARIES = $(RENDERER_GL) $(RENDERER_SW) +if BUILD_SW32 +RENDERER_SW32 = libQFrenderer_sw32.la +else +RENDERER_SW32 = +endif + +lib_LTLIBRARIES = $(RENDERER_GL) $(RENDERER_SW) $(RENDERER_SW32) common_SOURCES = r_cvar.c r_efrag.c r_ent.c r_graph.c r_main.c r_part.c @@ -27,4 +33,9 @@ libQFrenderer_sw_la_LIBADD = sw/libsw.la libQFrenderer_sw_la_SOURCES = $(common_SOURCES) libQFrenderer_sw_la_DEPENDENCIES = sw/libsw.la -LIBLIST = libQFrenderer_gl.la libQFrenderer_sw.la +libQFrenderer_sw32_la_LDFLAGS = -version-info 1:0:0 +libQFrenderer_sw32_la_LIBADD = sw32/libsw32.la +libQFrenderer_sw32_la_SOURCES = $(common_SOURCES) +libQFrenderer_sw32_la_DEPENDENCIES = sw32/libsw32.la + +LIBLIST = libQFrenderer_gl.la libQFrenderer_sw.la libQFrenderer_sw32.la diff --git a/libs/video/renderer/gl/gl_draw.c b/libs/video/renderer/gl/gl_draw.c index a8095440a..6ab0fb591 100644 --- a/libs/video/renderer/gl/gl_draw.c +++ b/libs/video/renderer/gl/gl_draw.c @@ -273,14 +273,14 @@ Draw_Init (void) } /* - Draw_Character8 + Draw_Character Draws one 8*8 graphics character with 0 being transparent. It can be clipped to the top of the screen to allow the console to be smoothly scrolled off. */ void -Draw_Character8 (int x, int y, int num) +Draw_Character (int x, int y, int num) { int row, col; float frow, fcol, size; @@ -315,20 +315,20 @@ Draw_Character8 (int x, int y, int num) } void -Draw_String8 (int x, int y, const char *str) +Draw_String (int x, int y, const char *str) { while (*str) { - Draw_Character8 (x, y, *str); + Draw_Character (x, y, *str); str++; x += 8; } } void -Draw_AltString8 (int x, int y, const char *str) +Draw_AltString (int x, int y, const char *str) { while (*str) { - Draw_Character8 (x, y, (*str) | 0x80); + Draw_Character (x, y, (*str) | 0x80); str++; x += 8; } @@ -346,10 +346,10 @@ Draw_Crosshair (int swap) break; case 1: default: - Draw_Character8 (scr_vrect.x + scr_vrect.width / 2 - 4 + - cl_crossx->int_val, - scr_vrect.y + scr_vrect.height / 2 - 4 + - cl_crossy->int_val, '+'); + Draw_Character (scr_vrect.x + scr_vrect.width / 2 - 4 + + cl_crossx->int_val, + scr_vrect.y + scr_vrect.height / 2 - 4 + + cl_crossy->int_val, '+'); break; case 2: x = scr_vrect.x + scr_vrect.width / 2 - 3 + cl_crossx->int_val; @@ -549,8 +549,8 @@ Draw_ConsoleBackground (int lines) qfglPopMatrix (); } - Draw_AltString8 (vid.conwidth - strlen (cl_verstring->string) * 8 - 11, - lines - 14, cl_verstring->string); + Draw_AltString (vid.conwidth - strlen (cl_verstring->string) * 8 - 11, + lines - 14, cl_verstring->string); qfglColor3ubv (lighthalf_v); } diff --git a/libs/video/renderer/gl/gl_rmisc.c b/libs/video/renderer/gl/gl_rmisc.c index 71d27f0b2..5795f2328 100644 --- a/libs/video/renderer/gl/gl_rmisc.c +++ b/libs/video/renderer/gl/gl_rmisc.c @@ -202,7 +202,8 @@ R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) continue; if (!strncmp (r_worldentity.model->textures[i]->name, "sky", 3)) skytexturenum = i; - if (!strncmp (r_worldentity.model->textures[i]->name, "window02_1", 10)) + if (!strncmp (r_worldentity.model->textures[i]->name, + "window02_1", 10)) mirrortexturenum = i; r_worldentity.model->textures[i]->texturechain = NULL; } @@ -231,7 +232,7 @@ R_TimeRefresh_f (void) start = Sys_DoubleTime (); for (i = 0; i < 128; i++) { GL_BeginRendering (&glx, &gly, &glwidth, &glheight); - r_refdef.viewangles[1] = i / 128.0 * 360.0; + r_refdef.viewangles[1] = i * (360.0 / 128.0); R_RenderView (); qfglFinish (); GL_EndRendering (); diff --git a/libs/video/renderer/gl/gl_screen.c b/libs/video/renderer/gl/gl_screen.c index 34c8f3fca..d7a3bb131 100644 --- a/libs/video/renderer/gl/gl_screen.c +++ b/libs/video/renderer/gl/gl_screen.c @@ -209,7 +209,7 @@ SCR_DrawCenterString (void) break; x = (vid.width - l * 8) / 2; for (j = 0; j < l; j++, x += 8) { - Draw_Character8 (x, y, start[j]); + Draw_Character (x, y, start[j]); if (!remaining--) return; } @@ -440,7 +440,7 @@ SCR_DrawFPS (int swap) x = swap ? vid.width - ((strlen (st) * 8) + i) : i; y = vid.height - sb_lines - 8; - Draw_String8 (x, y, st); + Draw_String (x, y, st); } /* @@ -477,7 +477,7 @@ SCR_DrawTime (int swap) // Print it at far left/right of screen x = swap ? (vid.width - ((strlen (st) * 8) + 8)) : 8; y = vid.height - (sb_lines + 8); - Draw_String8 (x, y, st); + Draw_String (x, y, st); } void @@ -742,7 +742,7 @@ SCR_DrawNotifyString (void) break; x = (vid.width - l * 8) / 2; for (j = 0; j < l; j++, x += 8) - Draw_Character8 (x, y, start[j]); + Draw_Character (x, y, start[j]); y += 8; diff --git a/libs/video/renderer/gl/gl_skin.c b/libs/video/renderer/gl/gl_skin.c index 5f10ff1ad..b865b722c 100644 --- a/libs/video/renderer/gl/gl_skin.c +++ b/libs/video/renderer/gl/gl_skin.c @@ -52,7 +52,7 @@ static byte translate[256]; static unsigned int translate32[256]; void -Skin_Set_Translate (int top, int bottom, byte *dest) +Skin_Set_Translate (int top, int bottom, void *_dest) { int i; diff --git a/libs/video/renderer/r_ent.c b/libs/video/renderer/r_ent.c index 6c5d11bc2..5b9ab1011 100644 --- a/libs/video/renderer/r_ent.c +++ b/libs/video/renderer/r_ent.c @@ -62,7 +62,7 @@ R_Init_Entity (entity_t *ent) { memset (ent, 0, sizeof (*ent)); - ent->colormap = vid.colormap; + ent->colormap = vid.colormap8; ent->glow_size = 0; ent->glow_color = 254; ent->alpha = 1; diff --git a/libs/video/renderer/r_graph.c b/libs/video/renderer/r_graph.c index 46b1908a2..8d115a099 100644 --- a/libs/video/renderer/r_graph.c +++ b/libs/video/renderer/r_graph.c @@ -59,18 +59,11 @@ R_TimeGraph (void) r_time2 = Sys_DoubleTime (); - a = (r_time2 - r_time1) / 0.01; -// a = fabs(mouse_y * 0.05); -// a = (int)((r_refdef.vieworg[2] + 1024)/1)%(int)r_graphheight->value; -// a = (int)((pmove.velocity[2] + 500)/10); -// a = fabs(velocity[0])/20; -// a = ((int)fabs(origin[0])/8)%20; -// a = (cl.idealpitch + 30)/5; -// a = (int)(cl.simangles[YAW] * 64/360) & 63; +// a = (r_time2 - r_time1) / 0.01; a = graphval; r_timings[timex] = a; - a = timex; +// a = timex; l = MAX_TIMINGS; if (l > r_refdef.vrect.width) @@ -78,7 +71,8 @@ R_TimeGraph (void) x = r_refdef.vrect.width - l; a = timex - l; if (a < 0) { - R_LineGraph (x, r_refdef.vrect.height - 2, &r_timings[a + MAX_TIMINGS], -a); + R_LineGraph (x, r_refdef.vrect.height - 2, + &r_timings[a + MAX_TIMINGS], -a); x -= a; l += a; a = 0; @@ -88,7 +82,6 @@ R_TimeGraph (void) timex = (timex + 1) % MAX_TIMINGS; } - void R_ZGraph (void) { diff --git a/libs/video/renderer/sw/d_edge.c b/libs/video/renderer/sw/d_edge.c index c19d6db4a..ae36fee60 100644 --- a/libs/video/renderer/sw/d_edge.c +++ b/libs/video/renderer/sw/d_edge.c @@ -194,7 +194,7 @@ D_DrawSurfaces (void) R_MakeSky (); } - D_DrawSkyScans8 (s->spans); + D_DrawSkyScans (s->spans); D_DrawZSpans (s->spans); } else if (s->flags & SURF_DRAWBACKGROUND) { // set up a gradient for the background surface that places @@ -209,9 +209,8 @@ D_DrawSurfaces (void) } else if (s->flags & SURF_DRAWTURB) { pface = s->data; miplevel = 0; - cacheblock = (pixel_t *) - ((byte *) pface->texinfo->texture + - pface->texinfo->texture->offsets[0]); + cacheblock = ((byte *) pface->texinfo->texture + + pface->texinfo->texture->offsets[0]); cachewidth = 64; if (s->insubmodel) { @@ -229,7 +228,7 @@ D_DrawSurfaces (void) D_CalcGradients (pface); - Turbulent8 (s->spans); + Turbulent (s->spans); D_DrawZSpans (s->spans); if (s->insubmodel) { @@ -267,7 +266,7 @@ D_DrawSurfaces (void) // FIXME: make this passed in to D_CacheSurface pcurrentcache = D_CacheSurface (pface, miplevel); - cacheblock = (pixel_t *) pcurrentcache->data; + cacheblock = (byte *) pcurrentcache->data; cachewidth = pcurrentcache->width; D_CalcGradients (pface); diff --git a/libs/video/renderer/sw/d_scan.c b/libs/video/renderer/sw/d_scan.c index 4ae140595..1572153af 100644 --- a/libs/video/renderer/sw/d_scan.c +++ b/libs/video/renderer/sw/d_scan.c @@ -119,7 +119,7 @@ D_DrawTurbulent8Span (void) #endif // !USE_INTEL_ASM void -Turbulent8 (espan_t *pspan) +Turbulent (espan_t *pspan) { int count; fixed16_t snext, tnext; diff --git a/libs/video/renderer/sw/d_sky.c b/libs/video/renderer/sw/d_sky.c index b0fbbe7f9..a73d2c798 100644 --- a/libs/video/renderer/sw/d_sky.c +++ b/libs/video/renderer/sw/d_sky.c @@ -66,7 +66,7 @@ D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t) } void -D_DrawSkyScans8 (espan_t *pspan) +D_DrawSkyScans (espan_t *pspan) { int count, spancount, u, v; unsigned char *pdest; diff --git a/libs/video/renderer/sw/d_surf.c b/libs/video/renderer/sw/d_surf.c index 18566a610..a82216aca 100644 --- a/libs/video/renderer/sw/d_surf.c +++ b/libs/video/renderer/sw/d_surf.c @@ -308,7 +308,7 @@ D_CacheSurface (msurface_t *surface, int miplevel) else cache->dlight = 0; - r_drawsurf.surfdat = (pixel_t *) cache->data; + r_drawsurf.surfdat = (byte *) cache->data; cache->texture = r_drawsurf.texture; cache->lightadj[0] = r_drawsurf.lightadj[0]; diff --git a/libs/video/renderer/sw/d_vars.c b/libs/video/renderer/sw/d_vars.c index 9ce238e7d..9facc20ed 100644 --- a/libs/video/renderer/sw/d_vars.c +++ b/libs/video/renderer/sw/d_vars.c @@ -33,7 +33,7 @@ #include "QF/qtypes.h" #ifdef PIC -#undef USE_INTEL_ASM //XXX asm pic hack +# undef USE_INTEL_ASM //XXX asm pic hack #endif #ifndef USE_INTEL_ASM @@ -52,9 +52,9 @@ float d_sdivzorigin, d_tdivzorigin, d_ziorigin; fixed16_t sadjust, tadjust, bbextents, bbextentt; -pixel_t *cacheblock; +byte *cacheblock; int cachewidth; -pixel_t *d_viewbuffer; +byte *d_viewbuffer; short *d_pzbuffer; unsigned int d_zrowbytes; unsigned int d_zwidth; diff --git a/libs/video/renderer/sw/draw.c b/libs/video/renderer/sw/draw.c index ba76a7b13..12aae0f32 100644 --- a/libs/video/renderer/sw/draw.c +++ b/libs/video/renderer/sw/draw.c @@ -196,14 +196,14 @@ Draw_Init (void) /* - Draw_Character8 + Draw_Character Draws one 8*8 graphics character with 0 being transparent. It can be clipped to the top of the screen to allow the console to be smoothly scrolled off. */ void -Draw_Character8 (int x, int y, int num) +Draw_Character (int x, int y, int num) { byte *dest; byte *source; @@ -287,10 +287,10 @@ Draw_Character8 (int x, int y, int num) void -Draw_String8 (int x, int y, const char *str) +Draw_String (int x, int y, const char *str) { while (*str) { - Draw_Character8 (x, y, *str); + Draw_Character (x, y, *str); str++; x += 8; } @@ -298,10 +298,10 @@ Draw_String8 (int x, int y, const char *str) void -Draw_AltString8 (int x, int y, const char *str) +Draw_AltString (int x, int y, const char *str) { while (*str) { - Draw_Character8 (x, y, (*str) | 0x80); + Draw_Character (x, y, (*str) | 0x80); str++; x += 8; } @@ -346,10 +346,10 @@ Draw_Crosshair (int swap) Draw_Pixel (x, y + 1, c); Draw_Pixel (x, y + 3, c); } else if (crosshair->int_val) - Draw_Character8 (scr_vrect.x + scr_vrect.width / 2 - 4 + - cl_crossx->int_val, - scr_vrect.y + scr_vrect.height / 2 - 4 + - cl_crossy->int_val, '+'); + Draw_Character (scr_vrect.x + scr_vrect.width / 2 - 4 + + cl_crossx->int_val, + scr_vrect.y + scr_vrect.height / 2 - 4 + + cl_crossy->int_val, '+'); } @@ -590,11 +590,10 @@ Draw_ConsoleBackground (int lines) } } - Draw_AltString8 (vid.conwidth - strlen (cl_verstring->string) - * 8 - 11, lines - 14, cl_verstring->string); + Draw_AltString (vid.conwidth - strlen (cl_verstring->string) * 8 - 11, + lines - 14, cl_verstring->string); } - void R_DrawRect8 (vrect_t *prect, int rowbytes, byte * psrc, int transparent) { diff --git a/libs/video/renderer/sw/screen.c b/libs/video/renderer/sw/screen.c index 8e6cd27a8..0c6d50a93 100644 --- a/libs/video/renderer/sw/screen.c +++ b/libs/video/renderer/sw/screen.c @@ -58,53 +58,48 @@ #include "sbar.h" #include "view.h" - /* + background clear + rendering + turtle/net/ram icons + sbar + centerprint / slow centerprint + notify lines + intermission / finale overlay + loading plaque + console + menu -background clear -rendering -turtle/net/ram icons -sbar -centerprint / slow centerprint -notify lines -intermission / finale overlay -loading plaque -console -menu - -required background clears -required update regions + required background clears + required update regions -syncronous draw mode or async -One off screen buffer, with updates either copied or xblited -Need to double buffer? + syncronous draw mode or async + One off screen buffer, with updates either copied or xblited + Need to double buffer? + async draw will require the refresh area to be cleared, because it will be + xblited, but sync draw can just ignore it. -async draw will require the refresh area to be cleared, because it will be -xblited, but sync draw can just ignore it. + sync + draw -sync -draw + CenterPrint () + SlowPrint () + Screen_Update (); + Con_Printf (); - CenterPrint () - SlowPrint () - Screen_Update (); - Con_Printf (); + net + turn off messages option -net -turn off messages option + the refresh is always rendered, unless the console is full screen -the refresh is always rendered, unless the console is full screen - - -console is: + console is: notify lines half full */ - // only the refresh window will be updated unless these variables are flagged int scr_copytop; int scr_copyeverything; @@ -175,7 +170,6 @@ SCR_CenterPrint (const char *str) } } - void SCR_DrawCenterString (void) { @@ -187,7 +181,8 @@ SCR_DrawCenterString (void) // the finale prints the characters one at a time if (r_force_fullscreen /*FIXME*/) - remaining = scr_printspeed->value * (r_realtime - scr_centertime_start); + remaining = scr_printspeed->value * (r_realtime - + scr_centertime_start); else remaining = 9999; @@ -206,7 +201,7 @@ SCR_DrawCenterString (void) break; x = (vid.width - l * 8) / 2; for (j = 0; j < l; j++, x += 8) { - Draw_Character8 (x, y, start[j]); + Draw_Character (x, y, start[j]); if (!remaining--) return; } @@ -222,7 +217,6 @@ SCR_DrawCenterString (void) } while (1); } - void SCR_CheckDrawCenterString (int swap) { @@ -240,10 +234,8 @@ SCR_CheckDrawCenterString (int swap) SCR_DrawCenterString (); } - //============================================================================= - float CalcFov (float fov_x, float width, float height) { @@ -262,7 +254,6 @@ CalcFov (float fov_x, float width, float height) return a; } - /* SCR_CalcRefdef @@ -321,8 +312,8 @@ SCR_CalcRefdef (void) } r_refdef.vrect.height = vid.height * size + 0.5; - if (r_refdef.vrect.height > vid.height - r_lineadj) - r_refdef.vrect.height = vid.height - r_lineadj; + if (r_refdef.vrect.height > h) + r_refdef.vrect.height = h; r_refdef.vrect.x = (vid.width - r_refdef.vrect.width) / 2; if (full) r_refdef.vrect.y = 0; @@ -353,7 +344,6 @@ SCR_CalcRefdef (void) R_ViewChanged (&vrect, r_lineadj, vid.aspect); } - extern float v_blend[4]; void @@ -383,7 +373,6 @@ SCR_ApplyBlend (void) // Used to be V_UpdatePalette VID_ShiftPalette (pal); } - /* SCR_SizeUp_f @@ -398,7 +387,6 @@ SCR_SizeUp_f (void) } } - /* SCR_SizeDown_f @@ -411,10 +399,8 @@ SCR_SizeDown_f (void) vid.recalc_refdef = 1; } - //============================================================================ - void SCR_Init (void) { @@ -432,7 +418,6 @@ SCR_Init (void) scr_initialized = true; } - void SCR_DrawRam (int swap) { @@ -445,7 +430,6 @@ SCR_DrawRam (int swap) Draw_Pic (scr_vrect.x + 32, scr_vrect.y, scr_ram); } - void SCR_DrawTurtle (int swap) { @@ -466,7 +450,6 @@ SCR_DrawTurtle (int swap) Draw_Pic (scr_vrect.x, scr_vrect.y, scr_turtle); } - extern cvar_t *show_fps; extern cvar_t *show_time; @@ -502,10 +485,9 @@ SCR_DrawFPS (int swap) } x = swap ? vid.width - ((strlen (st) * 8) + i) : i; y = vid.height - (sb_lines + 8); - Draw_String8 (x, y, st); + Draw_String (x, y, st); } - /* SCR_DrawTime @@ -540,10 +522,9 @@ SCR_DrawTime (int swap) strftime (st, sizeof (st), timefmt, local); x = swap ? (vid.width - ((strlen (st) * 8) + 8)) : 8; y = vid.height - (sb_lines + 8); - Draw_String8 (x, y, st); + Draw_String (x, y, st); } - void SCR_DrawPause (int swap) { @@ -560,10 +541,8 @@ SCR_DrawPause (int swap) (vid.height - 48 - pic->height) / 2, pic); } - //============================================================================= - void SCR_SetUpToDrawConsole (void) { @@ -596,7 +575,6 @@ SCR_SetUpToDrawConsole (void) con_notifylines = 0; } - void SCR_DrawConsole (int swap) { @@ -611,7 +589,6 @@ SCR_DrawConsole (int swap) } } - /* SCREEN SHOTS */ @@ -707,7 +684,6 @@ SCR_ScreenShot_f (void) Con_Printf ("Wrote %s\n", pcxname); } - /* Find closest color in the palette for named color */ @@ -744,7 +720,6 @@ MipColor (int r, int g, int b) return best; } - // in draw.c extern byte *draw_chars; // 8*8 graphic characters @@ -774,7 +749,6 @@ SCR_DrawCharToSnap (int num, byte * dest, int width) } - void SCR_DrawStringToSnap (const char *s, tex_t *tex, int x, int y) { @@ -792,10 +766,8 @@ SCR_DrawStringToSnap (const char *s, tex_t *tex, int x, int y) } } - //============================================================================= - char *scr_notifystring; void @@ -817,7 +789,7 @@ SCR_DrawNotifyString (void) break; x = (vid.width - l * 8) / 2; for (j = 0; j < l; j++, x += 8) - Draw_Character8 (x, y, start[j]); + Draw_Character (x, y, start[j]); y += 8; @@ -830,10 +802,8 @@ SCR_DrawNotifyString (void) } while (1); } - //============================================================================= - /* SCR_UpdateScreen @@ -876,9 +846,8 @@ SCR_UpdateScreen (double realtime, SCR_Func *scr_funcs, int swap) oldscr_viewsize = scr_viewsize->int_val; vid.recalc_refdef = 1; } - // + // check for vid changes - // if (oldfov != scr_fov->int_val) { oldfov = scr_fov->int_val; vid.recalc_refdef = true; @@ -893,11 +862,10 @@ SCR_UpdateScreen (double realtime, SCR_Func *scr_funcs, int swap) // something changed, so reorder the screen SCR_CalcRefdef (); } - // + // do 3D refresh drawing, and then update the screen - // D_EnableBackBufferAccess (); // of all overlay stuff if drawing - // directly + // directly if (scr_fullupdate++ < vid.numpages) { // clear the entire screen scr_copyeverything = 1; @@ -907,19 +875,16 @@ SCR_UpdateScreen (double realtime, SCR_Func *scr_funcs, int swap) pconupdate = NULL; - SCR_SetUpToDrawConsole (); - D_DisableBackBufferAccess (); // for adapters that can't stay - // mapped in - // for linear writes all the time - + D_DisableBackBufferAccess (); // for adapters that can't stay mapped + // in for linear writes all the time VID_LockBuffer (); V_RenderView (); VID_UnlockBuffer (); D_EnableBackBufferAccess (); // of all overlay stuff if drawing - // directly + // directly if (r_force_fullscreen /*FIXME*/ == 1 && key_dest == key_game) { Sbar_IntermissionOverlay (); @@ -933,19 +898,15 @@ SCR_UpdateScreen (double realtime, SCR_Func *scr_funcs, int swap) } } - - D_DisableBackBufferAccess (); // for adapters that can't stay - // mapped in - // for linear writes all the time + D_DisableBackBufferAccess (); // for adapters that can't stay mapped + // in for linear writes all the time if (pconupdate) { D_UpdateRects (pconupdate); } SCR_ApplyBlend (); - // // update one of three areas - // if (scr_copyeverything) { vrect.x = 0; vrect.y = 0; diff --git a/libs/video/renderer/sw/sw_graph.c b/libs/video/renderer/sw/sw_graph.c index 4cfeec3f2..e03d1c9c2 100644 --- a/libs/video/renderer/sw/sw_graph.c +++ b/libs/video/renderer/sw/sw_graph.c @@ -1,5 +1,5 @@ /* - r_misc.c + sw_graph.c (description) @@ -45,11 +45,8 @@ void R_LineGraph (int x, int y, int *h_vals, int count) { - int i; + int h, i, s, color; byte *dest; - int s; - int color; - int h; // FIXME: should be disabled on no-buffer adapters, or should be in the driver s = r_graphheight->int_val; diff --git a/libs/video/renderer/sw/sw_raclip.c b/libs/video/renderer/sw/sw_raclip.c index 6c4724e65..52912e691 100644 --- a/libs/video/renderer/sw/sw_raclip.c +++ b/libs/video/renderer/sw/sw_raclip.c @@ -30,9 +30,10 @@ # include "config.h" #endif +#include "QF/render.h" + #include "d_local.h" #include "r_local.h" -#include "QF/render.h" static finalvert_t fv[2][8]; static auxvert_t av[8]; diff --git a/libs/video/renderer/sw/sw_ralias.c b/libs/video/renderer/sw/sw_ralias.c index bba06ee9e..e1e950aee 100644 --- a/libs/video/renderer/sw/sw_ralias.c +++ b/libs/video/renderer/sw/sw_ralias.c @@ -1,5 +1,5 @@ /* - r_alias.c + sw_ralias.c routines for setting up to draw alias models diff --git a/libs/video/renderer/sw/sw_rbsp.c b/libs/video/renderer/sw/sw_rbsp.c index 4d12a777c..b8070ee6c 100644 --- a/libs/video/renderer/sw/sw_rbsp.c +++ b/libs/video/renderer/sw/sw_rbsp.c @@ -1,5 +1,5 @@ /* - r_bsp.c + sw_r_bsp.c (description) diff --git a/libs/video/renderer/sw/sw_rdraw.c b/libs/video/renderer/sw/sw_rdraw.c index be8889c9a..d8fd0cf8c 100644 --- a/libs/video/renderer/sw/sw_rdraw.c +++ b/libs/video/renderer/sw/sw_rdraw.c @@ -1,5 +1,5 @@ /* - r_draw.c + sw_r_draw.c (description) @@ -30,9 +30,10 @@ # include "config.h" #endif -#include "r_local.h" #include "QF/render.h" +#include "r_local.h" + #define MAXLEFTCLIPEDGES 100 // !!! if these are changed, they must be changed in asm_draw.h too !!! diff --git a/libs/video/renderer/sw/sw_redge.c b/libs/video/renderer/sw/sw_redge.c index f74501094..7003de7d4 100644 --- a/libs/video/renderer/sw/sw_redge.c +++ b/libs/video/renderer/sw/sw_redge.c @@ -1,5 +1,5 @@ /* - r_edge.c + sw_redge.c (description) diff --git a/libs/video/renderer/sw/sw_rlight.c b/libs/video/renderer/sw/sw_rlight.c index be0312dd7..387b7d870 100644 --- a/libs/video/renderer/sw/sw_rlight.c +++ b/libs/video/renderer/sw/sw_rlight.c @@ -55,12 +55,10 @@ R_AnimateLight (void) } } - /* DYNAMIC LIGHTS */ - void R_RecursiveMarkLights (vec3_t lightorigin, dlight_t *light, int bit, mnode_t *node) diff --git a/libs/video/renderer/sw/sw_rmain.c b/libs/video/renderer/sw/sw_rmain.c index d7959b960..be3dad482 100644 --- a/libs/video/renderer/sw/sw_rmain.c +++ b/libs/video/renderer/sw/sw_rmain.c @@ -173,7 +173,7 @@ R_Init (void) // TODO: collect 386-specific code in one place #ifdef PIC -#undef USE_INTEL_ASM //XXX asm pic hack +# undef USE_INTEL_ASM //XXX asm pic hack #endif #ifdef USE_INTEL_ASM @@ -183,7 +183,6 @@ R_Init (void) D_Init (); } - void R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) { @@ -193,7 +192,7 @@ R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) r_worldentity.model = worldmodel; // clear out efrags in case the level hasn't been reloaded -// FIXME: is this one short? + // FIXME: is this one short? for (i = 0; i < r_worldentity.model->numleafs; i++) r_worldentity.model->leafs[i].efrags = NULL; @@ -238,7 +237,6 @@ R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) r_viewchanged = false; } - void R_SetVrect (vrect_t *pvrectin, vrect_t *pvrect, int lineadj) { @@ -249,6 +247,7 @@ R_SetVrect (vrect_t *pvrectin, vrect_t *pvrect, int lineadj) if (scr_viewsize->int_val >= 100) { size = 100.0; full = true; + lineadj = 0; } else { size = scr_viewsize->int_val; } @@ -258,8 +257,6 @@ R_SetVrect (vrect_t *pvrectin, vrect_t *pvrect, int lineadj) size = 100.0; } size /= 100.0; - if (full) - lineadj = 0; h = pvrectin->height - lineadj; @@ -276,8 +273,8 @@ R_SetVrect (vrect_t *pvrectin, vrect_t *pvrect, int lineadj) pvrect->width &= ~7; pvrect->height = pvrectin->height * size; - if (pvrect->height > pvrectin->height - lineadj) - pvrect->height = pvrectin->height - lineadj; + if (pvrect->height > h) + pvrect->height = h; pvrect->height &= ~1; @@ -288,7 +285,6 @@ R_SetVrect (vrect_t *pvrectin, vrect_t *pvrect, int lineadj) pvrect->y = (h - pvrect->height) / 2; } - /* R_ViewChanged @@ -324,7 +320,8 @@ R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect) r_refdef.aliasvrect.x = (int) (r_refdef.vrect.x * r_aliasuvscale); r_refdef.aliasvrect.y = (int) (r_refdef.vrect.y * r_aliasuvscale); r_refdef.aliasvrect.width = (int) (r_refdef.vrect.width * r_aliasuvscale); - r_refdef.aliasvrect.height = (int) (r_refdef.vrect.height * r_aliasuvscale); + r_refdef.aliasvrect.height = (int) (r_refdef.vrect.height * + r_aliasuvscale); r_refdef.aliasvrectright = r_refdef.aliasvrect.x + r_refdef.aliasvrect.width; r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y + @@ -335,9 +332,9 @@ R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect) yOrigin = r_refdef.yOrigin; screenAspect = r_refdef.vrect.width * pixelAspect / r_refdef.vrect.height; -// 320*200 1.0 pixelAspect = 1.6 screenAspect -// 320*240 1.0 pixelAspect = 1.3333 screenAspect -// proper 320*200 pixelAspect = 0.8333333 + // 320*200 1.0 pixelAspect = 1.6 screenAspect + // 320*240 1.0 pixelAspect = 1.3333 screenAspect + // proper 320*200 pixelAspect = 0.8333333 verticalFieldOfView = r_refdef.horizontalFieldOfView / screenAspect; @@ -364,7 +361,8 @@ R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect) yscaleshrink = xscaleshrink * pixelAspect; // left side clip - screenedge[0].normal[0] = -1.0 / (xOrigin * r_refdef.horizontalFieldOfView); + screenedge[0].normal[0] = -1.0 / (xOrigin * + r_refdef.horizontalFieldOfView); screenedge[0].normal[1] = 0; screenedge[0].normal[2] = 1; screenedge[0].type = PLANE_ANYZ; @@ -392,7 +390,8 @@ R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect) VectorNormalize (screenedge[i].normal); res_scale = sqrt ((double) (r_refdef.vrect.width * r_refdef.vrect.height) / - (320.0 * 152.0)) * (2.0 / r_refdef.horizontalFieldOfView); + (320.0 * 152.0)) * (2.0 / + r_refdef.horizontalFieldOfView); r_aliastransition = r_aliastransbase->value * res_scale; r_resfudge = r_aliastransadj->value * res_scale; @@ -406,7 +405,7 @@ R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect) if (r_pixbytes == 1) { Sys_MakeCodeWriteable ((long) R_Surf8Start, (long) R_Surf8End - (long) R_Surf8Start); - colormap = vid.colormap; + colormap = vid.colormap8; R_Surf8Patch (); } else { Sys_MakeCodeWriteable ((long) R_Surf16Start, @@ -419,7 +418,6 @@ R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect) D_ViewChanged (); } - void R_MarkLeaves (void) { @@ -460,7 +458,6 @@ R_MarkLeaves (void) } } - static void R_ShowNearestLoc (void) { @@ -482,7 +479,6 @@ R_ShowNearestLoc (void) R_RunParticleEffect(trueloc,252,10); } } - void R_DrawEntitiesOnList (void) @@ -553,7 +549,6 @@ R_DrawEntitiesOnList (void) } } - void R_DrawViewModel (void) { @@ -614,7 +609,6 @@ R_DrawViewModel (void) R_AliasDrawModel (&r_viewlighting); } - int R_BmodelCheckBBox (model_t *clmodel, float *minmaxs) { @@ -669,7 +663,6 @@ R_BmodelCheckBBox (model_t *clmodel, float *minmaxs) return clipflags; } - void R_DrawBEntitiesOnList (void) { @@ -723,9 +716,10 @@ R_DrawBEntitiesOnList (void) (!r_dlights[k].radius)) continue; VectorSubtract (r_dlights[k].origin, - currententity->origin, lightorigin); - R_RecursiveMarkLights (lightorigin, &r_dlights[k], 1 << k, - clmodel->nodes + + currententity->origin, + lightorigin); + R_RecursiveMarkLights (lightorigin, &r_dlights[k], + 1 << k, clmodel->nodes + clmodel->hulls[0].firstclipnode); } } @@ -783,7 +777,6 @@ R_DrawBEntitiesOnList (void) insubmodel = false; } - void R_EdgeDrawing (void) { @@ -846,7 +839,6 @@ R_EdgeDrawing (void) R_ScanEdges (); } - /* R_RenderView @@ -945,7 +937,6 @@ R_RenderView_ (void) Sys_HighFPPrecision (); } - void R_RenderView (void) { @@ -968,7 +959,6 @@ R_RenderView (void) R_RenderView_ (); } - void R_InitTurb (void) { diff --git a/libs/video/renderer/sw/sw_rmisc.c b/libs/video/renderer/sw/sw_rmisc.c index bd153b230..032253dc3 100644 --- a/libs/video/renderer/sw/sw_rmisc.c +++ b/libs/video/renderer/sw/sw_rmisc.c @@ -1,5 +1,5 @@ /* - r_misc.c + sw_rmisc.c (description) @@ -30,22 +30,22 @@ # include "config.h" #endif -#include "compat.h" -#include "QF/console.h" #include "QF/cmd.h" +#include "QF/console.h" #include "QF/cvar.h" #include "QF/draw.h" #include "QF/render.h" #include "QF/sys.h" +#include "compat.h" #include "r_local.h" + void R_CheckVariables (void) { } - /* Show @@ -63,7 +63,6 @@ Show (void) VID_Update (&vr); } - /* R_TimeRefresh_f @@ -103,7 +102,6 @@ R_TimeRefresh_f (void) r_refdef.viewangles[1] = startangle; } - void R_LoadSky_f (void) { @@ -115,7 +113,6 @@ R_LoadSky_f (void) R_LoadSkys (Cmd_Argv (1)); } - void R_PrintTimes (void) { @@ -131,7 +128,6 @@ R_PrintTimes (void) c_surf = 0; } - void R_PrintDSpeeds (void) { @@ -154,14 +150,12 @@ R_PrintDSpeeds (void) de_time, dv_time); } - void R_PrintAliasStats (void) { Con_Printf ("%3i polygon model drawn\n", r_amodels_drawn); } - void WarpPalette (void) { @@ -184,7 +178,6 @@ WarpPalette (void) VID_ShiftPalette (newpalette); } - void R_TransformFrustum (void) { @@ -207,7 +200,7 @@ R_TransformFrustum (void) } #ifdef PIC -#undef USE_INTEL_ASM //XXX asm pic hack +# undef USE_INTEL_ASM //XXX asm pic hack #endif #ifndef USE_INTEL_ASM @@ -220,7 +213,6 @@ TransformVector (vec3_t in, vec3_t out) } #endif - void R_TransformPlane (mplane_t *p, float *normal, float *dist) { @@ -232,7 +224,6 @@ R_TransformPlane (mplane_t *p, float *normal, float *dist) TransformVector (p->normal, normal); } - void R_SetUpFrustumIndexes (void) { @@ -257,7 +248,6 @@ R_SetUpFrustumIndexes (void) } } - void R_SetupFrame (void) { @@ -318,7 +308,8 @@ R_SetupFrame (void) r_viewleaf = Mod_PointInLeaf (r_origin, r_worldentity.model); r_dowarpold = r_dowarp; - r_dowarp = r_waterwarp->int_val && (r_viewleaf->contents <= CONTENTS_WATER); + r_dowarp = r_waterwarp->int_val && (r_viewleaf->contents <= + CONTENTS_WATER); if ((r_dowarp != r_dowarpold) || r_viewchanged) { if (r_dowarp) { diff --git a/libs/video/renderer/sw/sw_rsprite.c b/libs/video/renderer/sw/sw_rsprite.c index ce75d8e11..bbdda4b2f 100644 --- a/libs/video/renderer/sw/sw_rsprite.c +++ b/libs/video/renderer/sw/sw_rsprite.c @@ -1,5 +1,5 @@ /* - r_sprite.c + sw_rsprite.c (description) diff --git a/libs/video/renderer/sw/sw_rsurf.c b/libs/video/renderer/sw/sw_rsurf.c index 7a5fa6480..b5193d165 100644 --- a/libs/video/renderer/sw/sw_rsurf.c +++ b/libs/video/renderer/sw/sw_rsurf.c @@ -1,5 +1,5 @@ /* - r_surf.c + sw_rsurf.c surface-related refresh code @@ -328,7 +328,7 @@ R_DrawSurfaceBlock8_mip0 (void) for (b = 15; b >= 0; b--) { pix = psource[b]; - prowdest[b] = ((unsigned char *) vid.colormap) + prowdest[b] = ((unsigned char *) vid.colormap8) [(light & 0xFF00) + pix]; light += lightstep; } @@ -371,7 +371,7 @@ R_DrawSurfaceBlock8_mip1 (void) for (b = 7; b >= 0; b--) { pix = psource[b]; - prowdest[b] = ((unsigned char *) vid.colormap) + prowdest[b] = ((unsigned char *) vid.colormap8) [(light & 0xFF00) + pix]; light += lightstep; } @@ -414,7 +414,7 @@ R_DrawSurfaceBlock8_mip2 (void) for (b = 3; b >= 0; b--) { pix = psource[b]; - prowdest[b] = ((unsigned char *) vid.colormap) + prowdest[b] = ((unsigned char *) vid.colormap8) [(light & 0xFF00) + pix]; light += lightstep; } @@ -457,7 +457,7 @@ R_DrawSurfaceBlock8_mip3 (void) for (b = 1; b >= 0; b--) { pix = psource[b]; - prowdest[b] = ((unsigned char *) vid.colormap) + prowdest[b] = ((unsigned char *) vid.colormap8) [(light & 0xFF00) + pix]; light += lightstep; } @@ -522,7 +522,7 @@ R_DrawSurfaceBlock16 (void) void -R_GenTurbTile (pixel_t *pbasetex, void *pdest) +R_GenTurbTile (byte *pbasetex, void *pdest) { int *turb; int i, j, s, t; @@ -542,7 +542,7 @@ R_GenTurbTile (pixel_t *pbasetex, void *pdest) void -R_GenTurbTile16 (pixel_t *pbasetex, void *pdest) +R_GenTurbTile16 (byte *pbasetex, void *pdest) { int *turb; int i, j, s, t; @@ -566,14 +566,10 @@ R_GenTile (msurface_t *psurf, void *pdest) { if (psurf->flags & SURF_DRAWTURB) { if (r_pixbytes == 1) { - R_GenTurbTile ((pixel_t *) - - ((byte *) psurf->texinfo->texture + + R_GenTurbTile (((byte *) psurf->texinfo->texture + psurf->texinfo->texture->offsets[0]), pdest); } else { - R_GenTurbTile16 ((pixel_t *) - - ((byte *) psurf->texinfo->texture + + R_GenTurbTile16 (((byte *) psurf->texinfo->texture + psurf->texinfo->texture->offsets[0]), pdest); } } else if (psurf->flags & SURF_DRAWSKY) { diff --git a/libs/video/renderer/sw/sw_skin.c b/libs/video/renderer/sw/sw_skin.c index 15fd5077f..cc945be79 100644 --- a/libs/video/renderer/sw/sw_skin.c +++ b/libs/video/renderer/sw/sw_skin.c @@ -36,24 +36,26 @@ # include #endif -#include "compat.h" #include "QF/model.h" +#include "QF/render.h" #include "QF/skin.h" -#include "QF/render.h" +#include "compat.h" void -Skin_Set_Translate (int top, int bottom, byte *dest) +Skin_Set_Translate (int top, int bottom, void *_dest) { int i, j; byte *source; + byte *dest = (byte *) _dest; + top = bound (0, top, 13) * 16; bottom = bound (0, bottom, 13) * 16; - source = vid.colormap; - memcpy (dest, vid.colormap, VID_GRADES*256); + source = vid.colormap8; + memcpy (dest, vid.colormap8, VID_GRADES*256); for (i = 0; i < VID_GRADES; i++, dest += 256, source += 256) { if (top < 128) // the artists made some backwards diff --git a/libs/video/renderer/sw32/Makefile.am b/libs/video/renderer/sw32/Makefile.am new file mode 100644 index 000000000..d14fd2470 --- /dev/null +++ b/libs/video/renderer/sw32/Makefile.am @@ -0,0 +1,17 @@ +INCLUDES= -I$(top_srcdir)/include + +if BUILD_SW32 +SW32 = libsw32.la +else +SW32 = +endif + +noinst_LTLIBRARIES = $(SW32) + +libsw32_la_LDFLAGS = -version-info 1:0:0 +libsw32_la_SOURCES = d_edge.c d_fill.c d_init.c d_modech.c d_part.c \ + d_polyse.c d_scan.c d_sky.c d_sprite.c d_surf.c d_vars.c d_zpoint.c \ + draw.c screen.c sw32_graph.c sw32_raclip.c sw32_ralias.c \ + sw32_rbsp.c sw32_rdraw.c sw32_redge.c sw32_rlight.c sw32_rmain.c \ + sw32_rmisc.c sw32_rpart.c sw32_rsky.c sw32_rsprite.c sw32_rsurf.c \ + sw32_skin.c diff --git a/libs/video/renderer/sw32/d_edge.c b/libs/video/renderer/sw32/d_edge.c new file mode 100644 index 000000000..3d7d1fd7f --- /dev/null +++ b/libs/video/renderer/sw32/d_edge.c @@ -0,0 +1,316 @@ +/* + d_edge.c + + (description) + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/cvar.h" +#include "QF/render.h" +#include "QF/sys.h" + +#include "d_local.h" +#include "r_local.h" +//#include "vid.h" // DESPAIR + +static int miplevel; + +float scale_for_mip; +extern int screenwidth; +int ubasestep, errorterm, erroradjustup, erroradjustdown, vstartscan; + +vec3_t transformed_modelorg; + + +void +D_DrawPoly (void) +{ +// this driver takes spans, not polygons +} + +int +D_MipLevelForScale (float scale) +{ + int lmiplevel; + + if (scale >= d_scalemip[0]) + lmiplevel = 0; + else if (scale >= d_scalemip[1]) + lmiplevel = 1; + else if (scale >= d_scalemip[2]) + lmiplevel = 2; + else + lmiplevel = 3; + + if (lmiplevel < d_minmip) + lmiplevel = d_minmip; + + return lmiplevel; +} + +// FIXME: clean this up + +void +D_DrawSolidSurface (surf_t *surf, int color) +{ + espan_t *span; + + switch(r_pixbytes) { + case 1: + { + byte *pdest, pix; + int u, u2; + + pix = color; + for (span = surf->spans; span; span = span->pnext) + { + pdest = (byte *) d_viewbuffer + screenwidth * span->v; + u = span->u; + u2 = span->u + span->count - 1; + for (;u <= u2; u++) + pdest[u] = pix; + } + } + break; + case 2: + { + short *pdest, pix; + int u, u2; + + pix = d_8to16table[color]; + for (span = surf->spans; span; span = span->pnext) + { + pdest = (short *) d_viewbuffer + screenwidth * span->v; + u = span->u; + u2 = span->u + span->count - 1; + for (;u <= u2; u++) + pdest[u] = pix; + } + } + break; + case 4: + { + int *pdest, pix; + int u, u2; + + pix = d_8to24table[color]; + for (span = surf->spans; span; span = span->pnext) + { + pdest = (int *) d_viewbuffer + screenwidth * span->v; + u = span->u; + u2 = span->u + span->count - 1; + for (;u <= u2; u++) + pdest[u] = pix; + } + } + break; + default: + Sys_Error("D_DrawSolidSurface: unsupported r_pixbytes %i\n", + r_pixbytes); + } +} + +void +D_CalcGradients (msurface_t *pface) +{ + mplane_t *pplane; + float mipscale, t; + vec3_t p_temp1, p_saxis, p_taxis; + + pplane = pface->plane; + + mipscale = 1.0 / (float) (1 << miplevel); + + TransformVector (pface->texinfo->vecs[0], p_saxis); + TransformVector (pface->texinfo->vecs[1], p_taxis); + + t = xscaleinv * mipscale; + d_sdivzstepu = p_saxis[0] * t; + d_tdivzstepu = p_taxis[0] * t; + + t = yscaleinv * mipscale; + d_sdivzstepv = -p_saxis[1] * t; + d_tdivzstepv = -p_taxis[1] * t; + + d_sdivzorigin = p_saxis[2] * mipscale - xcenter * d_sdivzstepu - + ycenter * d_sdivzstepv; + d_tdivzorigin = p_taxis[2] * mipscale - xcenter * d_tdivzstepu - + ycenter * d_tdivzstepv; + + VectorScale (transformed_modelorg, mipscale, p_temp1); + + t = 0x10000 * mipscale; + sadjust = ((fixed16_t) (DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) - + ((pface->texturemins[0] << 16) >> miplevel) + + pface->texinfo->vecs[0][3] * t; + tadjust = ((fixed16_t) (DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) - + ((pface->texturemins[1] << 16) >> miplevel) + + pface->texinfo->vecs[1][3] * t; + + // -1 (-epsilon) so we never wander off the edge of the texture + bbextents = ((pface->extents[0] << 16) >> miplevel) - 1; + bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1; +} + +void +D_DrawSurfaces (void) +{ + surf_t *s; + msurface_t *pface; + surfcache_t *pcurrentcache; + vec3_t local_modelorg, world_transformed_modelorg; + + currententity = &r_worldentity; + TransformVector (modelorg, transformed_modelorg); + VectorCopy (transformed_modelorg, world_transformed_modelorg); + + // TODO: could preset a lot of this at mode set time + if (r_drawflat->int_val) { + for (s = &surfaces[1]; s < surface_p; s++) { + if (!s->spans) + continue; + + d_zistepu = s->d_zistepu; + d_zistepv = s->d_zistepv; + d_ziorigin = s->d_ziorigin; + + D_DrawSolidSurface (s, ((int)&s->data) & 0xFF); + D_DrawZSpans (s->spans); + } + } else { + for (s = &surfaces[1]; s < surface_p; s++) { + if (!s->spans) + continue; + + r_drawnpolycount++; + + d_zistepu = s->d_zistepu; + d_zistepv = s->d_zistepv; + d_ziorigin = s->d_ziorigin; + + if (s->flags & SURF_DRAWSKY) { + if (!r_skymade) + R_MakeSky (); + + D_DrawSkyScans (s->spans); + D_DrawZSpans (s->spans); + } else if (s->flags & SURF_DRAWBACKGROUND) { + // set up a gradient for the background surface that places + // it effectively at infinity distance from the viewpoint + d_zistepu = 0; + d_zistepv = 0; + d_ziorigin = -0.9; + + D_DrawSolidSurface (s, r_clearcolor->int_val & 0xFF); + D_DrawZSpans (s->spans); + } else if (s->flags & SURF_DRAWTURB) { + pface = s->data; + miplevel = 0; + cacheblock = (void *)((byte *) pface->texinfo->texture + + pface->texinfo->texture->offsets[0]); + cachewidth = 64; + + if (s->insubmodel) { + // FIXME: we don't want to do all this for every polygon! + // TODO: store once at start of frame + currententity = s->entity; // FIXME: make this passed in + // to R_RotateBmodel () + VectorSubtract (r_origin, currententity->origin, + local_modelorg); + TransformVector (local_modelorg, transformed_modelorg); + + R_RotateBmodel (); // FIXME: don't mess with the + // frustum, make entity passed in + } + + D_CalcGradients (pface); + + Turbulent (s->spans); + D_DrawZSpans (s->spans); + + if (s->insubmodel) { + // restore the old drawing state + // FIXME: we don't want to do this every time! + // TODO: speed up + currententity = &r_worldentity; + VectorCopy (world_transformed_modelorg, + transformed_modelorg); + VectorCopy (base_vpn, vpn); + VectorCopy (base_vup, vup); + VectorCopy (base_vright, vright); + VectorCopy (base_modelorg, modelorg); + R_TransformFrustum (); + } + } else { + if (s->insubmodel) { + // FIXME: we don't want to do all this for every polygon! + // TODO: store once at start of frame + currententity = s->entity; // FIXME: make this passed in + // to + // R_RotateBmodel () + VectorSubtract (r_origin, currententity->origin, + local_modelorg); + TransformVector (local_modelorg, transformed_modelorg); + + R_RotateBmodel (); // FIXME: don't mess with the + // frustum, make entity passed in + } + + pface = s->data; + miplevel = D_MipLevelForScale (s->nearzi * scale_for_mip + * pface->texinfo->mipadjust); + + // FIXME: make this passed in to D_CacheSurface + pcurrentcache = D_CacheSurface (pface, miplevel); + + cacheblock = (void *) pcurrentcache->data; + cachewidth = pcurrentcache->width; + + D_CalcGradients (pface); + + D_DrawSpans (s->spans); + + D_DrawZSpans (s->spans); + + if (s->insubmodel) { + // restore the old drawing state + // FIXME: we don't want to do this every time! + // TODO: speed up + VectorCopy (world_transformed_modelorg, + transformed_modelorg); + VectorCopy (base_vpn, vpn); + VectorCopy (base_vup, vup); + VectorCopy (base_vright, vright); + VectorCopy (base_modelorg, modelorg); + R_TransformFrustum (); + currententity = &r_worldentity; + } + } + } + } +} diff --git a/libs/video/renderer/sw32/d_fill.c b/libs/video/renderer/sw32/d_fill.c new file mode 100644 index 000000000..ef07da385 --- /dev/null +++ b/libs/video/renderer/sw32/d_fill.c @@ -0,0 +1,162 @@ +/* + d_fill.c + + clears a specified rectangle to the specified color + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/sys.h" + +#include "d_iface.h" +// #include "vid.h" DESPAIR + + +void +D_FillRect (vrect_t *rect, int color) +{ + switch (r_pixbytes) + { + case 1: + { + int rx, ry, rwidth, rheight; + byte *dest, pix; + + pix = color; + + rx = rect->x; + ry = rect->y; + rwidth = rect->width; + rheight = rect->height; + + if (rx < 0) { + rwidth += rx; + rx = 0; + } + if (ry < 0) { + rheight += ry; + ry = 0; + } + if (rx + rwidth > vid.width) + rwidth = vid.width - rx; + if (ry + rheight > vid.height) + rheight = vid.height - rx; + + if (rwidth < 1 || rheight < 1) + return; + + dest = (byte *) vid.buffer + ry * vid.rowbytes + rx; + + for (ry = 0; ry < rheight; ry++) + { + for (rx = 0; rx < rwidth; rx++) + dest[rx] = pix; + dest += vid.rowbytes; + } + } + break; + case 2: + { + int rx, ry, rwidth, rheight; + unsigned short *dest, pix; + + pix = d_8to16table[color]; + + rx = rect->x; + ry = rect->y; + rwidth = rect->width; + rheight = rect->height; + + if (rx < 0) { + rwidth += rx; + rx = 0; + } + if (ry < 0) { + rheight += ry; + ry = 0; + } + if (rx + rwidth > vid.width) + rwidth = vid.width - rx; + if (ry + rheight > vid.height) + rheight = vid.height - rx; + + if (rwidth < 1 || rheight < 1) + return; + + dest = (unsigned short *) vid.buffer + ry * (vid.rowbytes >> 1) + + rx; + + for (ry = 0; ry < rheight; ry++) + { + for (rx = 0; rx < rwidth; rx++) + dest[rx] = pix; + dest += (vid.rowbytes >> 1); + } + } + break; + case 4: + { + int rx, ry, rwidth, rheight; + unsigned int *dest, pix; + + pix = d_8to24table[color]; + + rx = rect->x; + ry = rect->y; + rwidth = rect->width; + rheight = rect->height; + + if (rx < 0) { + rwidth += rx; + rx = 0; + } + if (ry < 0) { + rheight += ry; + ry = 0; + } + if (rx + rwidth > vid.width) + rwidth = vid.width - rx; + if (ry + rheight > vid.height) + rheight = vid.height - rx; + + if (rwidth < 1 || rheight < 1) + return; + + dest = (unsigned int *) vid.buffer + ry * (vid.rowbytes >> 2) + rx; + + for (ry = 0; ry < rheight; ry++) + { + for (rx = 0; rx < rwidth; rx++) + dest[rx] = pix; + dest += (vid.rowbytes >> 2); + } + } + break; + default: + Sys_Error("D_FillRect: unsupported r_pixbytes %i\n", r_pixbytes); + } +} diff --git a/libs/video/renderer/sw32/d_init.c b/libs/video/renderer/sw32/d_init.c new file mode 100644 index 000000000..e91628626 --- /dev/null +++ b/libs/video/renderer/sw32/d_init.c @@ -0,0 +1,141 @@ +/* + d_init.c + + rasterization driver initialization + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/cvar.h" +// #include "QF/render.h" +// #include "QF/vid.h" + +#include "compat.h" +#include "d_local.h" +// #include "r_cvar.h" + +#define NUM_MIPS 4 + +cvar_t *d_mipcap; +cvar_t *d_mipscale; + +surfcache_t *d_initial_rover; +qboolean d_roverwrapped; +int d_minmip; +float d_scalemip[NUM_MIPS - 1]; + +static float basemip[NUM_MIPS - 1] = { 1.0, 0.5 * 0.8, 0.25 * 0.8 }; + +extern int d_aflatcolor; + +float d_zitable[65536]; + + +void +D_Init (void) +{ + r_skydirect = 1; + + r_drawpolys = false; + r_worldpolysbacktofront = false; + r_aliasuvscale = 1.0; + + // LordHavoc: compute 1/zi table for use in rendering code everywhere + if (!d_zitable[1]) + { + int i; + d_zitable[0] = 0; + for (i = 1;i < 65536;i++) + d_zitable[i] = (65536.0 * 65536.0 / (double) i); + } +} + +void +D_CopyRects (vrect_t *prects, int transparent) +{ +/* + this function is only required if the CPU doesn't have direct access to the + back buffer, and there's some driver interface function that the driver + doesn't support and requires Quake to do in software (such as drawing the + console); Quake will then draw into wherever the driver points vid.buffer + and will call this function before swapping buffers +*/ +// UNUSED (prects); +// UNUSED (transparent); +} + +void +D_EnableBackBufferAccess (void) +{ + + VID_LockBuffer (); +} + +void +D_TurnZOn (void) +{ + // not needed for software version +} + +void +D_DisableBackBufferAccess (void) +{ + VID_UnlockBuffer (); +} + +void +D_SetupFrame (void) +{ + int i; + + if (r_dowarp) + d_viewbuffer = (void *) r_warpbuffer; + else + d_viewbuffer = (void *) vid.buffer; + + if (r_dowarp) + screenwidth = WARP_WIDTH; + else + screenwidth = vid.rowbytes / r_pixbytes; + + d_roverwrapped = false; + d_initial_rover = sc_rover; + + d_minmip = bound (0, d_mipcap->value, 3); + + for (i = 0; i < (NUM_MIPS - 1); i++) + d_scalemip[i] = basemip[i] * d_mipscale->value; + + d_aflatcolor = 0; +} + +void +D_UpdateRects (vrect_t *prect) +{ + // the software driver draws these directly to the vid buffer +// UNUSED (prect); +} diff --git a/libs/video/renderer/sw32/d_modech.c b/libs/video/renderer/sw32/d_modech.c new file mode 100644 index 000000000..f43d9e893 --- /dev/null +++ b/libs/video/renderer/sw32/d_modech.c @@ -0,0 +1,98 @@ +/* + d_modech.c + + called when mode has just changed + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/render.h" +// #include "QF/sys.h" // DESPAIR + +#include "d_local.h" + +int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle; + +int d_y_aspect_shift, d_pix_min, d_pix_max, d_pix_shift; + +int d_scantable[MAXHEIGHT]; +short *zspantable[MAXHEIGHT]; + + +void +D_Patch (void) +{ +} + +void +D_ViewChanged (void) +{ + int rowpixels; + + if (r_dowarp) + rowpixels = WARP_WIDTH; + else + rowpixels = vid.rowbytes / r_pixbytes; + + scale_for_mip = xscale; + if (yscale > xscale) + scale_for_mip = yscale; + + d_zrowbytes = vid.width * 2; + d_zwidth = vid.width; + + d_pix_min = r_refdef.vrect.width / 320; + if (d_pix_min < 1) + d_pix_min = 1; + + d_pix_max = (int) ((float) r_refdef.vrect.width / (320.0 / 4.0) + 0.5); + d_pix_shift = 8 - (int) ((float) r_refdef.vrect.width / 320.0 + 0.5); + if (d_pix_max < 1) + d_pix_max = 1; + + if (pixelAspect > 1.4) + d_y_aspect_shift = 1; + else + d_y_aspect_shift = 0; + + d_vrectx = r_refdef.vrect.x; + d_vrecty = r_refdef.vrect.y; + d_vrectright_particle = r_refdef.vrectright - d_pix_max; + d_vrectbottom_particle = + r_refdef.vrectbottom - (d_pix_max << d_y_aspect_shift); + + { + int i; + + for (i = 0; i < vid.height; i++) { + d_scantable[i] = i * rowpixels; + zspantable[i] = d_pzbuffer + i * d_zwidth; + } + } + + D_Patch (); +} diff --git a/libs/video/renderer/sw32/d_part.c b/libs/video/renderer/sw32/d_part.c new file mode 100644 index 000000000..2d971bf1d --- /dev/null +++ b/libs/video/renderer/sw32/d_part.c @@ -0,0 +1,382 @@ +/* + d_part.c + + software driver module for drawing particles + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/sys.h" + +#include "d_local.h" +#include "r_local.h" +// #include "vid.h" // DESPAIR + + +void +D_EndParticles (void) +{ + // not used by software driver +} + +void +D_StartParticles (void) +{ + // not used by software driver +} + +void +D_DrawParticle (particle_t *pparticle) +{ + vec3_t local, transformed; + float zi; + short *pz; + int i, izi, pix, count, u, v; + + // transform point + VectorSubtract (pparticle->org, r_origin, local); + + transformed[0] = DotProduct (local, r_pright); + transformed[1] = DotProduct (local, r_pup); + transformed[2] = DotProduct (local, r_ppn); + + if (transformed[2] < PARTICLE_Z_CLIP) + return; + + // project the point + // FIXME: preadjust xcenter and ycenter + zi = 1.0 / transformed[2]; + u = (int) (xcenter + zi * transformed[0] + 0.5); + v = (int) (ycenter - zi * transformed[1] + 0.5); + + if ((v > d_vrectbottom_particle) || + (u > d_vrectright_particle) || (v < d_vrecty) || (u < d_vrectx)) { + return; + } + + pz = d_pzbuffer + (d_zwidth * v) + u; + izi = (int) (zi * 0x8000); + + pix = izi >> d_pix_shift; + + if (pix < d_pix_min) + pix = d_pix_min; + else if (pix > d_pix_max) + pix = d_pix_max; + + switch(r_pixbytes) + { + case 1: + { + byte *pdest = (byte *) d_viewbuffer + d_scantable[v] + u, + pixcolor = pparticle->color; + switch (pix) { + case 1: + count = 1 << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, + pdest += screenwidth) { + if (pz[0] <= izi) { + pz[0] = izi; + pdest[0] = pixcolor; + } + } + break; + case 2: + count = 2 << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, + pdest += screenwidth) { + if (pz[0] <= izi) { + pz[0] = izi; + pdest[0] = pixcolor; + } + + if (pz[1] <= izi) { + pz[1] = izi; + pdest[1] = pixcolor; + } + } + break; + case 3: + count = 3 << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, + pdest += screenwidth) { + if (pz[0] <= izi) { + pz[0] = izi; + pdest[0] = pixcolor; + } + + if (pz[1] <= izi) { + pz[1] = izi; + pdest[1] = pixcolor; + } + + if (pz[2] <= izi) { + pz[2] = izi; + pdest[2] = pixcolor; + } + } + break; + case 4: + count = 4 << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, + pdest += screenwidth) { + if (pz[0] <= izi) { + pz[0] = izi; + pdest[0] = pixcolor; + } + + if (pz[1] <= izi) { + pz[1] = izi; + pdest[1] = pixcolor; + } + + if (pz[2] <= izi) { + pz[2] = izi; + pdest[2] = pixcolor; + } + + if (pz[3] <= izi) { + pz[3] = izi; + pdest[3] = pixcolor; + } + } + break; + default: + count = pix << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, + pdest += screenwidth) { + for (i = 0; i < pix; i++) { + if (pz[i] <= izi) { + pz[i] = izi; + pdest[i] = pixcolor; + } + } + } + break; + } + } + break; + case 2: + { + unsigned short *pdest = (unsigned short *) d_viewbuffer + + d_scantable[v] + u, + pixcolor = d_8to16table[(int) pparticle->color]; + switch (pix) { + case 1: + count = 1 << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, + pdest += screenwidth) { + if (pz[0] <= izi) { + pz[0] = izi; + pdest[0] = pixcolor; + } + } + break; + case 2: + count = 2 << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, + pdest += screenwidth) { + if (pz[0] <= izi) { + pz[0] = izi; + pdest[0] = pixcolor; + } + + if (pz[1] <= izi) { + pz[1] = izi; + pdest[1] = pixcolor; + } + } + break; + case 3: + count = 3 << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, + pdest += screenwidth) { + if (pz[0] <= izi) { + pz[0] = izi; + pdest[0] = pixcolor; + } + + if (pz[1] <= izi) { + pz[1] = izi; + pdest[1] = pixcolor; + } + + if (pz[2] <= izi) { + pz[2] = izi; + pdest[2] = pixcolor; + } + } + break; + case 4: + count = 4 << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, + pdest += screenwidth) { + if (pz[0] <= izi) { + pz[0] = izi; + pdest[0] = pixcolor; + } + + if (pz[1] <= izi) { + pz[1] = izi; + pdest[1] = pixcolor; + } + + if (pz[2] <= izi) { + pz[2] = izi; + pdest[2] = pixcolor; + } + + if (pz[3] <= izi) { + pz[3] = izi; + pdest[3] = pixcolor; + } + } + break; + default: + count = pix << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, + pdest += screenwidth) { + for (i = 0; i < pix; i++) { + if (pz[i] <= izi) { + pz[i] = izi; + pdest[i] = pixcolor; + } + } + } + break; + } + } + break; + case 4: + { + int *pdest = (int *) d_viewbuffer + d_scantable[v] + u, + pixcolor = d_8to24table[(int) pparticle->color]; + switch (pix) { + case 1: + count = 1 << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, + pdest += screenwidth) { + if (pz[0] <= izi) { + pz[0] = izi; + pdest[0] = pixcolor; + } + } + break; + case 2: + count = 2 << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, + pdest += screenwidth) { + if (pz[0] <= izi) { + pz[0] = izi; + pdest[0] = pixcolor; + } + + if (pz[1] <= izi) { + pz[1] = izi; + pdest[1] = pixcolor; + } + } + break; + case 3: + count = 3 << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, + pdest += screenwidth) { + if (pz[0] <= izi) { + pz[0] = izi; + pdest[0] = pixcolor; + } + + if (pz[1] <= izi) { + pz[1] = izi; + pdest[1] = pixcolor; + } + + if (pz[2] <= izi) { + pz[2] = izi; + pdest[2] = pixcolor; + } + } + break; + case 4: + count = 4 << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, + pdest += screenwidth) { + if (pz[0] <= izi) { + pz[0] = izi; + pdest[0] = pixcolor; + } + + if (pz[1] <= izi) { + pz[1] = izi; + pdest[1] = pixcolor; + } + + if (pz[2] <= izi) { + pz[2] = izi; + pdest[2] = pixcolor; + } + + if (pz[3] <= izi) { + pz[3] = izi; + pdest[3] = pixcolor; + } + } + break; + default: + count = pix << d_y_aspect_shift; + + for (; count; count--, pz += d_zwidth, + pdest += screenwidth) { + for (i = 0; i < pix; i++) { + if (pz[i] <= izi) { + pz[i] = izi; + pdest[i] = pixcolor; + } + } + } + break; + } + } + break; + default: + Sys_Error("D_DrawParticles: unsupported r_pixbytes %i\n", r_pixbytes); + } +} diff --git a/libs/video/renderer/sw32/d_polyse.c b/libs/video/renderer/sw32/d_polyse.c new file mode 100644 index 000000000..90ce300c4 --- /dev/null +++ b/libs/video/renderer/sw32/d_polyse.c @@ -0,0 +1,941 @@ +/* + d_polyse.c + + routines for drawing sets of polygons sharing the same texture + (used for Alias models) + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +//#include "QF/render.h" +#include "QF/sys.h" + +#include "r_local.h" +#include "d_local.h" +//#include "vid.h" // DESPAIR + +// TODO: put in span spilling to shrink list size +// !!! if this is changed, it must be changed in d_polysa.s too !!! +#define DPS_MAXSPANS MAXHEIGHT+1 // +1 for spanpackage marking end + +// !!! if this is changed, it must be changed in asm_draw.h too !!! +typedef struct { + int pdest; + short *pz; + int count; + byte *ptex; + int sfrac, tfrac, light, zi; +} spanpackage_t; + +typedef struct { + int isflattop; + int numleftedges; + int *pleftedgevert0; + int *pleftedgevert1; + int *pleftedgevert2; + int numrightedges; + int *prightedgevert0; + int *prightedgevert1; + int *prightedgevert2; +} edgetable; + +int r_p0[6], r_p1[6], r_p2[6]; +int d_aflatcolor; +int d_xdenom; + +byte *d_pcolormap; + +edgetable *pedgetable; + +edgetable edgetables[12] = { + {0, 1, r_p0, r_p2, NULL, 2, r_p0, r_p1, r_p2}, + {0, 2, r_p1, r_p0, r_p2, 1, r_p1, r_p2, NULL}, + {1, 1, r_p0, r_p2, NULL, 1, r_p1, r_p2, NULL}, + {0, 1, r_p1, r_p0, NULL, 2, r_p1, r_p2, r_p0}, + {0, 2, r_p0, r_p2, r_p1, 1, r_p0, r_p1, NULL}, + {0, 1, r_p2, r_p1, NULL, 1, r_p2, r_p0, NULL}, + {0, 1, r_p2, r_p1, NULL, 2, r_p2, r_p0, r_p1}, + {0, 2, r_p2, r_p1, r_p0, 1, r_p2, r_p0, NULL}, + {0, 1, r_p1, r_p0, NULL, 1, r_p1, r_p2, NULL}, + {1, 1, r_p2, r_p1, NULL, 1, r_p0, r_p1, NULL}, + {1, 1, r_p1, r_p0, NULL, 1, r_p2, r_p0, NULL}, + {0, 1, r_p0, r_p2, NULL, 1, r_p0, r_p1, NULL}, +}; + +// FIXME: some of these can become statics +//int a_sstepxfrac, a_tstepxfrac, a_ststepxwhole; +int r_sstepx, r_tstepx, r_lstepx, r_lstepy, r_sstepy, r_tstepy; +int r_zistepx, r_zistepy; +int d_aspancount, d_countextrastep; + +spanpackage_t *a_spans; +spanpackage_t *d_pedgespanpackage; +static int ystart; +int d_pdest; +byte *d_ptex; +short *d_pz; +int d_sfrac, d_tfrac, d_light, d_zi; +int d_ptexextrastep, d_sfracextrastep; +int d_tfracextrastep, d_lightextrastep, d_pdestextrastep; +int d_lightbasestep, d_pdestbasestep, d_ptexbasestep; +int d_sfracbasestep, d_tfracbasestep; +int d_ziextrastep, d_zibasestep; +int d_pzextrastep, d_pzbasestep; + +typedef struct { + int quotient; + int remainder; +} adivtab_t; + +static adivtab_t adivtab[32 * 32] = { +#include "adivtab.h" +}; + +byte *skintable[MAX_LBM_HEIGHT]; +int skinwidth; +byte *skinstart; + +void D_PolysetDrawSpans (spanpackage_t * pspanpackage); +void D_PolysetCalcGradients (int skinwidth); +void D_DrawNonSubdiv (void); +void D_PolysetSetEdgeTable (void); +void D_RasterizeAliasPolySmooth (void); +void D_PolysetScanLeftEdge (int height); + + +void +D_PolysetDraw (void) +{ + spanpackage_t spans[DPS_MAXSPANS + 1 + + ((CACHE_SIZE - 1) / sizeof (spanpackage_t)) + 1]; + + // one extra because of cache line pretouching + + a_spans = (spanpackage_t *) + (((long) &spans[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); + + D_DrawNonSubdiv (); +} + +void +D_DrawNonSubdiv (void) +{ + mtriangle_t *ptri; + finalvert_t *pfv, *index0, *index1, *index2; + int i; + int lnumtriangles; + + pfv = r_affinetridesc.pfinalverts; + ptri = r_affinetridesc.ptriangles; + lnumtriangles = r_affinetridesc.numtriangles; + + for (i = 0; i < lnumtriangles; i++, ptri++) { + index0 = pfv + ptri->vertindex[0]; + index1 = pfv + ptri->vertindex[1]; + index2 = pfv + ptri->vertindex[2]; + + d_xdenom = + (index0->v[1] - index1->v[1]) * (index0->v[0] - index2->v[0]) - + (index0->v[0] - index1->v[0]) * (index0->v[1] - index2->v[1]); + + if (d_xdenom >= 0) + continue; + + r_p0[0] = index0->v[0]; // u + r_p0[1] = index0->v[1]; // v + r_p0[2] = index0->v[2]; // s + r_p0[3] = index0->v[3]; // t + r_p0[4] = index0->v[4]; // light + r_p0[5] = index0->v[5]; // iz + + r_p1[0] = index1->v[0]; + r_p1[1] = index1->v[1]; + r_p1[2] = index1->v[2]; + r_p1[3] = index1->v[3]; + r_p1[4] = index1->v[4]; + r_p1[5] = index1->v[5]; + + r_p2[0] = index2->v[0]; + r_p2[1] = index2->v[1]; + r_p2[2] = index2->v[2]; + r_p2[3] = index2->v[3]; + r_p2[4] = index2->v[4]; + r_p2[5] = index2->v[5]; + + if (!ptri->facesfront) { + if (index0->flags & ALIAS_ONSEAM) + r_p0[2] += r_affinetridesc.seamfixupX16; + if (index1->flags & ALIAS_ONSEAM) + r_p1[2] += r_affinetridesc.seamfixupX16; + if (index2->flags & ALIAS_ONSEAM) + r_p2[2] += r_affinetridesc.seamfixupX16; + } + + D_PolysetSetEdgeTable (); + D_RasterizeAliasPolySmooth (); + } +} + +void +D_PolysetUpdateTables (void) +{ + int i; + byte *s; + + if (r_affinetridesc.skinwidth != skinwidth || + r_affinetridesc.pskin != skinstart) { + skinwidth = r_affinetridesc.skinwidth; + skinstart = r_affinetridesc.pskin; + s = skinstart; + for (i = 0; i < MAX_LBM_HEIGHT; i++, s += skinwidth) + skintable[i] = s; + } +} + +void +D_PolysetScanLeftEdge (int height) +{ + + do { + d_pedgespanpackage->pdest = d_pdest; + d_pedgespanpackage->pz = d_pz; + d_pedgespanpackage->count = d_aspancount; + d_pedgespanpackage->ptex = d_ptex; + + d_pedgespanpackage->sfrac = d_sfrac; + d_pedgespanpackage->tfrac = d_tfrac; + + // FIXME: need to clamp l, s, t, at both ends? + d_pedgespanpackage->light = d_light; + d_pedgespanpackage->zi = d_zi; + + d_pedgespanpackage++; + + errorterm += erroradjustup; + if (errorterm >= 0) { + d_pdest += d_pdestextrastep; + d_pz += d_pzextrastep; + d_aspancount += d_countextrastep; + d_ptex += d_ptexextrastep; + d_sfrac += d_sfracextrastep; + d_ptex += d_sfrac >> 16; + + d_sfrac &= 0xFFFF; + d_tfrac += d_tfracextrastep; + if (d_tfrac & 0x10000) { + d_ptex += r_affinetridesc.skinwidth; + d_tfrac &= 0xFFFF; + } + d_light += d_lightextrastep; + d_zi += d_ziextrastep; + errorterm -= erroradjustdown; + } else { + d_pdest += d_pdestbasestep; + d_pz += d_pzbasestep; + d_aspancount += ubasestep; + d_ptex += d_ptexbasestep; + d_sfrac += d_sfracbasestep; + d_ptex += d_sfrac >> 16; + d_sfrac &= 0xFFFF; + d_tfrac += d_tfracbasestep; + if (d_tfrac & 0x10000) { + d_ptex += r_affinetridesc.skinwidth; + d_tfrac &= 0xFFFF; + } + d_light += d_lightbasestep; + d_zi += d_zibasestep; + } + } while (--height); +} + +void +D_PolysetSetUpForLineScan (fixed8_t startvertu, fixed8_t startvertv, + fixed8_t endvertu, fixed8_t endvertv) +{ + double dm, dn; + int tm, tn; + adivtab_t *ptemp; + + // TODO: implement x86 version + + errorterm = -1; + + tm = endvertu - startvertu; + tn = endvertv - startvertv; + + if (((tm <= 16) && (tm >= -15)) && ((tn <= 16) && (tn >= -15))) { + ptemp = &adivtab[((tm + 15) << 5) + (tn + 15)]; + ubasestep = ptemp->quotient; + erroradjustup = ptemp->remainder; + erroradjustdown = tn; + } else { + dm = (double) tm; + dn = (double) tn; + + FloorDivMod (dm, dn, &ubasestep, &erroradjustup); + + erroradjustdown = dn; + } +} + +void +D_PolysetCalcGradients (int skinwidth) +{ + float xstepdenominv, ystepdenominv, t0, t1; + float p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20; + + p00_minus_p20 = r_p0[0] - r_p2[0]; + p01_minus_p21 = r_p0[1] - r_p2[1]; + p10_minus_p20 = r_p1[0] - r_p2[0]; + p11_minus_p21 = r_p1[1] - r_p2[1]; + + xstepdenominv = 1.0 / (float) d_xdenom; + + ystepdenominv = -xstepdenominv; + + // ceil () for light so positive steps are exaggerated, negative steps + // diminished, pushing us away from underflow toward overflow. Underflow + // is very visible, overflow is very unlikely, because of ambient lighting + t0 = r_p0[4] - r_p2[4]; + t1 = r_p1[4] - r_p2[4]; + r_lstepx = (int) + ceil ((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv); + r_lstepy = (int) + ceil ((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv); + + t0 = r_p0[2] - r_p2[2]; + t1 = r_p1[2] - r_p2[2]; + r_sstepx = (int) ((t1 * p01_minus_p21 - t0 * p11_minus_p21) * + xstepdenominv); + r_sstepy = (int) ((t1 * p00_minus_p20 - t0 * p10_minus_p20) * + ystepdenominv); + + t0 = r_p0[3] - r_p2[3]; + t1 = r_p1[3] - r_p2[3]; + r_tstepx = (int) ((t1 * p01_minus_p21 - t0 * p11_minus_p21) * + xstepdenominv); + r_tstepy = (int) ((t1 * p00_minus_p20 - t0 * p10_minus_p20) * + ystepdenominv); + + t0 = r_p0[5] - r_p2[5]; + t1 = r_p1[5] - r_p2[5]; + r_zistepx = (int) ((t1 * p01_minus_p21 - t0 * p11_minus_p21) * + xstepdenominv); + r_zistepy = (int) ((t1 * p00_minus_p20 - t0 * p10_minus_p20) * + ystepdenominv); + +// a_sstepxfrac = r_sstepx & 0xFFFF; +// a_tstepxfrac = r_tstepx & 0xFFFF; + +// a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16); +} + +/* +byte gelmap[256]; +void +InitGel (byte * palette) +{ + int i; + int r; + + for (i = 0; i < 256; i++) { +// r = (palette[i*3]>>4); + r = + (palette[i * 3] + palette[i * 3 + 1] + + palette[i * 3 + 2]) / (16 * 3); + gelmap[i] = *//* 64 *//* 0 + r; + } +} +*/ + +void +D_PolysetDrawSpans (spanpackage_t * pspanpackage) +{ + int i, j, texscantable[1024], *texscan; + // LordHavoc: compute skin row table + for (i = 0, j = -r_affinetridesc.skinheight * r_affinetridesc.skinwidth; + i < r_affinetridesc.skinheight*2;i++, j += r_affinetridesc.skinwidth) + texscantable[i] = j; + texscan = texscantable + r_affinetridesc.skinheight; + + switch(r_pixbytes) { + case 1: + { + int lcount, count = 0; + byte *lpdest; + byte *lptex; + int lsfrac, ltfrac; + int llight; + int lzi; + short *lpz; + + do + { + lcount = d_aspancount - pspanpackage->count; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_aspancount += d_countextrastep; + errorterm -= erroradjustdown; + } + else + d_aspancount += ubasestep; + + if (lcount) + { + lpdest = (byte *) d_viewbuffer + pspanpackage->pdest; + lptex = pspanpackage->ptex; + lpz = pspanpackage->pz; + lsfrac = pspanpackage->sfrac; + ltfrac = pspanpackage->tfrac; + llight = pspanpackage->light; + lzi = pspanpackage->zi; + + // LordHavoc: optimized zbuffer check (switchs between + // loops when state changes, and quickly skips groups + // of hidden pixels) + do + { + if ((lzi >> 16) < *lpz) // hidden + { + count = 0; + goto skiploop8; + } +drawloop8: + *lpz++ = lzi >> 16; + *lpdest++ = ((byte *)acolormap) + [(llight & 0xFF00) | lptex[texscan[ltfrac >> 16] + + (lsfrac >> 16)]]; + lzi += r_zistepx; + lsfrac += r_sstepx; + ltfrac += r_tstepx; + llight += r_lstepx; + } + while (--lcount); + goto done8; + + do + { + if ((lzi >> 16) >= *lpz) // draw + { + lsfrac += r_sstepx * count; + ltfrac += r_tstepx * count; + llight += r_lstepx * count; + lpdest += count; + goto drawloop8; + } +skiploop8: + count++; + lzi += r_zistepx; + lpz++; + } + while (--lcount); +done8: ; + } + + pspanpackage++; + } + while (pspanpackage->count != -999999); + } + break; + + case 2: + { + int lcount, count = 0; + short *lpdest; + byte *lptex; + int lsfrac, ltfrac; + int llight; + int lzi; + short *lpz; + + do + { + lcount = d_aspancount - pspanpackage->count; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_aspancount += d_countextrastep; + errorterm -= erroradjustdown; + } + else + d_aspancount += ubasestep; + + if (lcount) + { + lpdest = (short *) d_viewbuffer + pspanpackage->pdest; + lptex = pspanpackage->ptex; + lpz = pspanpackage->pz; + lsfrac = pspanpackage->sfrac; + ltfrac = pspanpackage->tfrac; + llight = pspanpackage->light; + lzi = pspanpackage->zi; + + do + { + if ((lzi >> 16) < *lpz) // hidden + { + count = 0; + goto skiploop16; + } +drawloop16: + *lpz++ = lzi >> 16; + *lpdest++ = ((short *)acolormap)[(llight & 0xFF00) | lptex[texscan[ltfrac >> 16] + (lsfrac >> 16)]]; + lzi += r_zistepx; + lsfrac += r_sstepx; + ltfrac += r_tstepx; + llight += r_lstepx; + } + while (--lcount); + goto done16; + + do + { + if ((lzi >> 16) >= *lpz) // draw + { + lsfrac += r_sstepx * count; + ltfrac += r_tstepx * count; + llight += r_lstepx * count; + lpdest += count; + goto drawloop16; + } +skiploop16: + count++; + lzi += r_zistepx; + lpz++; + } + while (--lcount); +done16: ; + } + + pspanpackage++; + } + while (pspanpackage->count != -999999); + } + break; + + case 4: + { + int lcount, count = 0; + int *lpdest; + byte *lptex; + int lsfrac, ltfrac; + int llight; + int lzi; + short *lpz; + + do + { + lcount = d_aspancount - pspanpackage->count; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_aspancount += d_countextrastep; + errorterm -= erroradjustdown; + } + else + d_aspancount += ubasestep; + + if (lcount) + { + lpdest = (int *) d_viewbuffer + pspanpackage->pdest; + lptex = pspanpackage->ptex; + lpz = pspanpackage->pz; + lsfrac = pspanpackage->sfrac; + ltfrac = pspanpackage->tfrac; + llight = pspanpackage->light; + lzi = pspanpackage->zi; + + do + { + if ((lzi >> 16) < *lpz) // hidden + { + count = 0; + goto skiploop32; + } +drawloop32: + *lpz++ = lzi >> 16; + *lpdest++ = + vid.colormap32[(llight & 0xFF00) | + lptex[texscan[ltfrac >> 16] + + (lsfrac >> 16)]]; + lzi += r_zistepx; + lsfrac += r_sstepx; + ltfrac += r_tstepx; + llight += r_lstepx; + } + while (--lcount); + goto done32; + + do + { + if ((lzi >> 16) >= *lpz) // draw + { + lsfrac += r_sstepx * count; + ltfrac += r_tstepx * count; + llight += r_lstepx * count; + lpdest += count; + goto drawloop32; + } +skiploop32: + count++; + lzi += r_zistepx; + lpz++; + } + while (--lcount); +done32: ; + } + + pspanpackage++; + } + while (pspanpackage->count != -999999); + } + break; + + default: + Sys_Error("D_PolysetDrawSpans: unsupported r_pixbytes %i\n", + r_pixbytes); + } +} + + +/* + D_PolysetFillSpans +*/ +/* +void +D_PolysetFillSpans (spanpackage_t * pspanpackage) +{ + int color, lcount; + switch(r_pixbytes) + { + case 1: + // FIXME: do z buffering + color = (d_aflatcolor++) & 0xFF; + while (1) { + int lcount; + byte *lpdest; + + lcount = pspanpackage->count; + + if (lcount == -1) + return; + + if (lcount) { + lpdest = (byte *) d_viewbuffer + pspanpackage->pdest; + + do { + *lpdest++ = color; + } while (--lcount); + } + + pspanpackage++; + } + break; + case 2: + color = d_8to16table[(d_aflatcolor++) & 0xFF]; + while (1) { + short *lpdest; + + lcount = pspanpackage->count; + + if (lcount == -1) + return; + + if (lcount) { + lpdest = (short *) d_viewbuffer + pspanpackage->pdest; + + do { + *lpdest++ = color; + } while (--lcount); + } + + pspanpackage++; + } + break; + case 4: + color = d_8to24table[(d_aflatcolor++) & 0xFF]; + while (1) { + int lcount; + int *lpdest; + + lcount = pspanpackage->count; + + if (lcount == -1) + return; + + if (lcount) { + lpdest = (int *) d_viewbuffer + pspanpackage->pdest; + + do { + *lpdest++ = color; + } while (--lcount); + } + + pspanpackage++; + } + break; + default: + Sys_Error("D_PolysetFillSpans: unsupported r_pixbytes %i\n", r_pixbytes); + } +} +*/ + +/* + D_RasterizeAliasPolySmooth +*/ +void +D_RasterizeAliasPolySmooth (void) +{ + int initialleftheight, initialrightheight; + int *plefttop, *prighttop, *pleftbottom, *prightbottom; + int working_lstepx, originalcount; + + plefttop = pedgetable->pleftedgevert0; + prighttop = pedgetable->prightedgevert0; + + pleftbottom = pedgetable->pleftedgevert1; + prightbottom = pedgetable->prightedgevert1; + + initialleftheight = pleftbottom[1] - plefttop[1]; + initialrightheight = prightbottom[1] - prighttop[1]; + +// +// set the s, t, and light gradients, which are consistent across the triangle +// because being a triangle, things are affine +// + D_PolysetCalcGradients (r_affinetridesc.skinwidth); + +// +// rasterize the polygon +// + +// +// scan out the top (and possibly only) part of the left edge +// + D_PolysetSetUpForLineScan (plefttop[0], plefttop[1], + pleftbottom[0], pleftbottom[1]); + + d_pedgespanpackage = a_spans; + + ystart = plefttop[1]; + d_aspancount = plefttop[0] - prighttop[0]; + + d_ptex = (byte *) r_affinetridesc.pskin + (plefttop[2] >> 16) + + (plefttop[3] >> 16) * r_affinetridesc.skinwidth; + d_sfrac = plefttop[2] & 0xFFFF; + d_tfrac = plefttop[3] & 0xFFFF; + d_pzbasestep = d_zwidth + ubasestep; + d_pzextrastep = d_pzbasestep + 1; + d_light = plefttop[4]; + d_zi = plefttop[5]; + + d_pdestbasestep = screenwidth + ubasestep; + d_pdestextrastep = d_pdestbasestep + 1; + // LordHavoc: d_pdest has been changed to pixel offset + d_pdest = ystart * screenwidth + plefttop[0]; + d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0]; + +// TODO: can reuse partial expressions here + +// for negative steps in x along left edge, bias toward overflow rather than +// underflow (sort of turning the floor () we did in the gradient calcs into +// ceil (), but plus a little bit) + if (ubasestep < 0) + working_lstepx = r_lstepx - 1; + else + working_lstepx = r_lstepx; + + d_countextrastep = ubasestep + 1; + d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) + + ((r_tstepy + r_tstepx * ubasestep) >> 16) * r_affinetridesc.skinwidth; + d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF; + d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF; + d_lightbasestep = r_lstepy + working_lstepx * ubasestep; + d_zibasestep = r_zistepy + r_zistepx * ubasestep; + + d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) + + ((r_tstepy + r_tstepx * d_countextrastep) >> 16) * + r_affinetridesc.skinwidth; + d_sfracextrastep = (r_sstepy + r_sstepx * d_countextrastep) & 0xFFFF; + d_tfracextrastep = (r_tstepy + r_tstepx * d_countextrastep) & 0xFFFF; + d_lightextrastep = d_lightbasestep + working_lstepx; + d_ziextrastep = d_zibasestep + r_zistepx; + + D_PolysetScanLeftEdge (initialleftheight); + +// +// scan out the bottom part of the left edge, if it exists +// + if (pedgetable->numleftedges == 2) { + int height; + + plefttop = pleftbottom; + pleftbottom = pedgetable->pleftedgevert2; + + D_PolysetSetUpForLineScan (plefttop[0], plefttop[1], + pleftbottom[0], pleftbottom[1]); + + height = pleftbottom[1] - plefttop[1]; + +// TODO: make this a function; modularize this function in general + + ystart = plefttop[1]; + d_aspancount = plefttop[0] - prighttop[0]; + d_ptex = (byte *) r_affinetridesc.pskin + (plefttop[2] >> 16) + + (plefttop[3] >> 16) * r_affinetridesc.skinwidth; + d_sfrac = 0; + d_tfrac = 0; + d_light = plefttop[4]; + d_zi = plefttop[5]; + + d_pdestbasestep = screenwidth + ubasestep; + d_pdestextrastep = d_pdestbasestep + 1; + // LordHavoc: d_pdest and relatives have been changed to pixel + // offsets into framebuffer + d_pdest = ystart * screenwidth + plefttop[0]; + d_pzbasestep = d_zwidth + ubasestep; + d_pzextrastep = d_pzbasestep + 1; + d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0]; + + if (ubasestep < 0) + working_lstepx = r_lstepx - 1; + else + working_lstepx = r_lstepx; + + d_countextrastep = ubasestep + 1; + d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) + + ((r_tstepy + r_tstepx * ubasestep) >> 16) * + r_affinetridesc.skinwidth; + d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF; + d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF; + d_lightbasestep = r_lstepy + working_lstepx * ubasestep; + d_zibasestep = r_zistepy + r_zistepx * ubasestep; + + d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) + + ((r_tstepy + r_tstepx * d_countextrastep) >> 16) * + r_affinetridesc.skinwidth; + d_sfracextrastep = (r_sstepy + r_sstepx * d_countextrastep) & 0xFFFF; + d_tfracextrastep = (r_tstepy + r_tstepx * d_countextrastep) & 0xFFFF; + d_lightextrastep = d_lightbasestep + working_lstepx; + d_ziextrastep = d_zibasestep + r_zistepx; + + D_PolysetScanLeftEdge (height); + } +// scan out the top (and possibly only) part of the right edge, updating the +// count field + d_pedgespanpackage = a_spans; + + D_PolysetSetUpForLineScan (prighttop[0], prighttop[1], + prightbottom[0], prightbottom[1]); + d_aspancount = 0; + d_countextrastep = ubasestep + 1; + originalcount = a_spans[initialrightheight].count; + a_spans[initialrightheight].count = -999999; // mark end of the + // spanpackages + D_PolysetDrawSpans (a_spans); + +// scan out the bottom part of the right edge, if it exists + if (pedgetable->numrightedges == 2) { + int height; + spanpackage_t *pstart; + + pstart = a_spans + initialrightheight; + pstart->count = originalcount; + + d_aspancount = prightbottom[0] - prighttop[0]; + + prighttop = prightbottom; + prightbottom = pedgetable->prightedgevert2; + + height = prightbottom[1] - prighttop[1]; + + D_PolysetSetUpForLineScan (prighttop[0], prighttop[1], + prightbottom[0], prightbottom[1]); + + d_countextrastep = ubasestep + 1; + a_spans[initialrightheight + height].count = -999999; + // mark end of the spanpackages + D_PolysetDrawSpans (pstart); + } +} + + +/* + D_PolysetSetEdgeTable +*/ +void +D_PolysetSetEdgeTable (void) +{ + int edgetableindex; + + // assume the vertices are already in top to bottom order + edgetableindex = 0; + +// +// determine which edges are right & left, and the order in which +// to rasterize them +// + if (r_p0[1] >= r_p1[1]) { + if (r_p0[1] == r_p1[1]) { + if (r_p0[1] < r_p2[1]) + pedgetable = &edgetables[2]; + else + pedgetable = &edgetables[5]; + + return; + } else + edgetableindex = 1; + } + + if (r_p0[1] == r_p2[1]) { + if (edgetableindex) + pedgetable = &edgetables[8]; + else + pedgetable = &edgetables[9]; + + return; + } else if (r_p1[1] == r_p2[1]) { + if (edgetableindex) + pedgetable = &edgetables[10]; + else + pedgetable = &edgetables[11]; + + return; + } + + if (r_p0[1] > r_p2[1]) + edgetableindex += 2; + + if (r_p1[1] > r_p2[1]) + edgetableindex += 4; + + pedgetable = &edgetables[edgetableindex]; +} diff --git a/libs/video/renderer/sw32/d_scan.c b/libs/video/renderer/sw32/d_scan.c new file mode 100644 index 000000000..2e6d43fbf --- /dev/null +++ b/libs/video/renderer/sw32/d_scan.c @@ -0,0 +1,892 @@ +/* + d_scan.c + + Portable C scan-level rasterization code, all pixel depths. + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/qendian.h" +#include "QF/render.h" +#include "QF/sys.h" + +#include "compat.h" +#include "d_local.h" +#include "r_local.h" +//#include "vid.h" // DESPAIR + +byte *r_turb_pbase; +void *r_turb_pdest; +fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep; +int *r_turb_turb; +int r_turb_spancount; + +void D_DrawTurbulentSpan (void); + +extern float *d_zitable; // DESPAIR + + +/* + D_WarpScreen + + this performs a slight compression of the screen at the same time as + the sine warp, to keep the edges from wrapping +*/ +void +D_WarpScreen (void) +{ + switch(r_pixbytes) { + case 1: + { + int w, h; + int u, v; + byte *dest; + int *turb; + int *col; + byte **row; + byte *rowptr[1024]; + int column[1280]; + float wratio, hratio; + + w = r_refdef.vrect.width; + h = r_refdef.vrect.height; + + wratio = w / (float) scr_vrect.width; + hratio = h / (float) scr_vrect.height; + + for (v = 0; v < scr_vrect.height + AMP2 * 2; v++) { + rowptr[v] = (byte *) d_viewbuffer + (r_refdef.vrect.y * + screenwidth) + + (screenwidth * (int) ((float) v * hratio * h / + (h + AMP2 * 2))); + } + + for (u = 0; u < scr_vrect.width + AMP2 * 2; u++) { + column[u] = r_refdef.vrect.x + + (int) ((float) u * wratio * w / (w + AMP2 * 2)); + } + + turb = intsintable + ((int) (r_realtime * SPEED) & (CYCLE - 1)); + dest = (byte *) (vid.buffer + scr_vrect.y * vid.rowbytes + + scr_vrect.x); + + for (v = 0; v < scr_vrect.height; v++, dest += vid.rowbytes) { + col = &column[turb[v]]; + row = &rowptr[v]; + for (u = 0; u < scr_vrect.width; u += 4) { + dest[u + 0] = row[turb[u + 0]][col[u + 0]]; + dest[u + 1] = row[turb[u + 1]][col[u + 1]]; + dest[u + 2] = row[turb[u + 2]][col[u + 2]]; + dest[u + 3] = row[turb[u + 3]][col[u + 3]]; + } + } + } + break; + case 2: + { + int w, h; + int u, v; + short *dest; + int *turb; + int *col; + short **row; + short *rowptr[1024]; + int column[1280]; + float wratio, hratio; + + w = r_refdef.vrect.width; + h = r_refdef.vrect.height; + + wratio = w / (float) scr_vrect.width; + hratio = h / (float) scr_vrect.height; + + for (v = 0; v < scr_vrect.height + AMP2 * 2; v++) { + rowptr[v] = (short *) d_viewbuffer + + (r_refdef.vrect.y * screenwidth) + + (screenwidth * (int) ((float) v * hratio * h / + (h + AMP2 * 2))); + } + + for (u = 0; u < scr_vrect.width + AMP2 * 2; u++) { + column[u] = r_refdef.vrect.x + + (int) ((float) u * wratio * w / (w + AMP2 * 2)); + } + + turb = intsintable + ((int) (r_realtime * SPEED) & (CYCLE - 1)); + dest = (short *) vid.buffer + scr_vrect.y * (vid.rowbytes >> 1) + + scr_vrect.x; + + for (v = 0; v < scr_vrect.height; v++, dest += (vid.rowbytes >> 1)) { + col = &column[turb[v]]; + row = &rowptr[v]; + for (u = 0; u < scr_vrect.width; u += 4) { + dest[u + 0] = row[turb[u + 0]][col[u + 0]]; + dest[u + 1] = row[turb[u + 1]][col[u + 1]]; + dest[u + 2] = row[turb[u + 2]][col[u + 2]]; + dest[u + 3] = row[turb[u + 3]][col[u + 3]]; + } + } + } + break; + case 4: + { + int w, h; + int u, v; + int *dest; + int *turb; + int *col; + int **row; + int *rowptr[1024]; + int column[1280]; + float wratio, hratio; + + w = r_refdef.vrect.width; + h = r_refdef.vrect.height; + + wratio = w / (float) scr_vrect.width; + hratio = h / (float) scr_vrect.height; + + for (v = 0; v < scr_vrect.height + AMP2 * 2; v++) { + rowptr[v] = (int *) d_viewbuffer + + (r_refdef.vrect.y * screenwidth) + + (screenwidth * (int) ((float) v * hratio * h / + (h + AMP2 * 2))); + } + + for (u = 0; u < scr_vrect.width + AMP2 * 2; u++) { + column[u] = r_refdef.vrect.x + + (int) ((float) u * wratio * w / (w + AMP2 * 2)); + } + + turb = intsintable + ((int) (r_realtime * SPEED) & (CYCLE - 1)); + dest = (int *) vid.buffer + scr_vrect.y * (vid.rowbytes >> 2) + + scr_vrect.x; + + for (v = 0; v < scr_vrect.height; v++, dest += (vid.rowbytes >> 2)) { + col = &column[turb[v]]; + row = &rowptr[v]; + for (u = 0; u < scr_vrect.width; u += 4) { + dest[u + 0] = row[turb[u + 0]][col[u + 0]]; + dest[u + 1] = row[turb[u + 1]][col[u + 1]]; + dest[u + 2] = row[turb[u + 2]][col[u + 2]]; + dest[u + 3] = row[turb[u + 3]][col[u + 3]]; + } + } + } + break; + default: + Sys_Error("D_WarpScreen: unsupported r_pixbytes %i\n", r_pixbytes); + } +} + +void +D_DrawTurbulentSpan (void) +{ + int sturb, tturb; + + switch (r_pixbytes) { + case 1: + { + byte *pdest = (byte *) r_turb_pdest; + do { + sturb = ((r_turb_s + r_turb_turb[(r_turb_t >> 16) & + (CYCLE - 1)]) >> 16) & 63; + tturb = ((r_turb_t + r_turb_turb[(r_turb_s >> 16) & + (CYCLE - 1)]) >> 16) & 63; + *pdest++ = r_turb_pbase[(tturb << 6) + sturb]; + r_turb_s += r_turb_sstep; + r_turb_t += r_turb_tstep; + } while (--r_turb_spancount > 0); + r_turb_pdest = (byte *)pdest; + } + break; + case 2: + { + short *pdest = (short *) r_turb_pdest; + do { + sturb = ((r_turb_s + r_turb_turb[(r_turb_t >> 16) & + (CYCLE - 1)]) >> 16) & 63; + tturb = ((r_turb_t + r_turb_turb[(r_turb_s >> 16) & + (CYCLE - 1)]) >> 16) & 63; + *pdest++ = d_8to16table[r_turb_pbase[(tturb << 6) + sturb]]; + r_turb_s += r_turb_sstep; + r_turb_t += r_turb_tstep; + } while (--r_turb_spancount > 0); + r_turb_pdest = (byte *)pdest; + } + break; + case 4: + { + int *pdest = (int *) r_turb_pdest; + do { + sturb = ((r_turb_s + r_turb_turb[(r_turb_t >> 16) & + (CYCLE - 1)]) >> 16) & 63; + tturb = ((r_turb_t + r_turb_turb[(r_turb_s >> 16) & + (CYCLE - 1)]) >> 16) & 63; + *pdest++ = d_8to24table[r_turb_pbase[(tturb << 6) + sturb]]; + r_turb_s += r_turb_sstep; + r_turb_t += r_turb_tstep; + } while (--r_turb_spancount > 0); + r_turb_pdest = (byte *)pdest; + } + break; + default: + Sys_Error("D_DrawTurbulentSpan: unsupported r_pixbytes %i\n", + r_pixbytes); + } +} + +void +Turbulent (espan_t *pspan) +{ + int count; + fixed16_t snext, tnext; + float sdivz, tdivz, zi, z, du, dv, spancountminus1; + float sdivz16stepu, tdivz16stepu, zi16stepu; + + r_turb_turb = sintable + ((int) (r_realtime * SPEED) & (CYCLE - 1)); + + r_turb_sstep = 0; // keep compiler happy + r_turb_tstep = 0; // ditto + + r_turb_pbase = (byte *) cacheblock; + + sdivz16stepu = d_sdivzstepu * 16; + tdivz16stepu = d_tdivzstepu * 16; + zi16stepu = d_zistepu * 16 * 65536; + + do { + r_turb_pdest = ((byte *) d_viewbuffer + ((screenwidth * pspan->v) + + pspan->u) * r_pixbytes); + + count = pspan->count; + + // calculate the initial s/z, t/z, 1/z, s, and t and clamp + du = (float) pspan->u; + dv = (float) pspan->v; + + sdivz = d_sdivzorigin + dv * d_sdivzstepv + du * d_sdivzstepu; + tdivz = d_tdivzorigin + dv * d_tdivzstepv + du * d_tdivzstepu; + zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f; + z = d_zitable[(int) zi]; + + r_turb_s = (int) (sdivz * z) + sadjust; + if (r_turb_s > bbextents) + r_turb_s = bbextents; + else if (r_turb_s < 0) + r_turb_s = 0; + + r_turb_t = (int) (tdivz * z) + tadjust; + if (r_turb_t > bbextentt) + r_turb_t = bbextentt; + else if (r_turb_t < 0) + r_turb_t = 0; + + do { + // calculate s and t at the far end of the span + if (count >= 16) + r_turb_spancount = 16; + else + r_turb_spancount = count; + + count -= r_turb_spancount; + + if (count) { + // calculate s/z, t/z, zi->fixed s and t at far end of span, + // calculate s and t steps across span by shifting + sdivz += sdivz16stepu; + tdivz += tdivz16stepu; + zi += zi16stepu; + z = d_zitable[(int) zi]; + + snext = (int) (sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 16) + snext = 16; // prevent round-off error on <0 + // steps from + // from causing overstepping & running off the + // edge of the texture + + tnext = (int) (tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 16) + tnext = 16; // guard against round-off error on + // <0 steps + + r_turb_sstep = (snext - r_turb_s) >> 4; + r_turb_tstep = (tnext - r_turb_t) >> 4; + } else { + // calculate s/z, t/z, zi->fixed s and t at last pixel in + // span (so + // can't step off polygon), clamp, calculate s and t steps + // across + // span by division, biasing steps low so we don't run off + // the + // texture + spancountminus1 = (float) (r_turb_spancount - 1); + sdivz += d_sdivzstepu * spancountminus1; + tdivz += d_tdivzstepu * spancountminus1; + zi += d_zistepu * 65536.0f * spancountminus1; + z = d_zitable[(int) zi]; + snext = (int) (sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 16) + snext = 16; // prevent round-off error on <0 + // steps from + // from causing overstepping & running off the + // edge of the texture + + tnext = (int) (tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 16) + tnext = 16; // guard against round-off error on + // <0 steps + + if (r_turb_spancount > 1) { + r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1); + r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1); + } + } + + r_turb_s = r_turb_s & ((CYCLE << 16) - 1); + r_turb_t = r_turb_t & ((CYCLE << 16) - 1); + + D_DrawTurbulentSpan (); + + r_turb_s = snext; + r_turb_t = tnext; + + } while (count > 0); + + } while ((pspan = pspan->pnext) != NULL); +} + +void +D_DrawSpans (espan_t *pspan) +{ + switch(r_pixbytes) { + case 1: + { + byte *pbase = (byte *) cacheblock, *pdest; + int count; + fixed16_t s, t, snext, tnext, sstep, tstep; + float sdivz, tdivz, zi, z, du, dv; + float sdivz8stepu, tdivz8stepu, zi8stepu; + + sstep = 0; // keep compiler happy + tstep = 0; // ditto + + sdivz8stepu = d_sdivzstepu * 8; + tdivz8stepu = d_tdivzstepu * 8; + zi8stepu = d_zistepu * 8 * 65536; + + do { + pdest = (byte *) d_viewbuffer + (screenwidth * pspan->v) + + pspan->u; + + count = pspan->count; + + // calculate the initial s/z, t/z, 1/z, s, and t and clamp + du = (float) pspan->u; + dv = (float) pspan->v; + + sdivz = d_sdivzorigin + dv * d_sdivzstepv + du * d_sdivzstepu; + tdivz = d_tdivzorigin + dv * d_tdivzstepv + du * d_tdivzstepu; + zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f; + z = d_zitable[(int) zi]; + + s = (int) (sdivz * z) + sadjust; + s = bound(0, s, bbextents); + t = (int) (tdivz * z) + tadjust; + t = bound(0, t, bbextentt); + + while(count >= 8) { + count -= 8; + // calculate s/z, t/z, zi->fixed s and t at far end of span, + // calculate s and t steps across span by shifting + sdivz += sdivz8stepu; + tdivz += tdivz8stepu; + zi += zi8stepu; + z = d_zitable[(int) zi]; + + // prevent round-off error on <0 steps from from causing + // overstepping & running off the edge of the texture + snext = (int) (sdivz * z) + sadjust; + snext = bound(8, snext, bbextents); + tnext = (int) (tdivz * z) + tadjust; + tnext = bound(8, tnext, bbextentt); + + sstep = (snext - s) >> 3; + tstep = (tnext - t) >> 3; + + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep;t += tstep; + pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[2] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[3] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[4] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[5] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[6] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[7] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s = snext; + t = tnext; + pdest += 8; + } + if (count) + { + // calculate s/z, t/z, zi->fixed s and t at last pixel in span + // (so can't step off polygon), clamp, calculate s and t steps + // across span by division, biasing steps low so we don't run + // off the texture + //countminus1 = (float) (count - 1); + sdivz += d_sdivzstepu * count; //minus1; + tdivz += d_tdivzstepu * count; //minus1; + zi += d_zistepu * 65536.0f * count; //minus1; + z = d_zitable[(int) zi]; + + // prevent round-off error on <0 steps from from causing + // overstepping & running off the edge of the texture + snext = (int) (sdivz * z) + sadjust; + snext = bound(count, snext, bbextents); + tnext = (int) (tdivz * z) + tadjust; + tnext = bound(count, tnext, bbextentt); + + if (count > 1) { + sstep = (snext - s) / count; //(count - 1); + tstep = (tnext - t) / count; //(count - 1); + + if (count & 4) + { + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[2] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[3] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest += 4; + } + if (count & 2) + { + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest += 2; + } + if (count & 1) + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + } + else + { + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + } + } + } while ((pspan = pspan->pnext) != NULL); + } + break; + case 2: + { + short *pbase = (short *) cacheblock, *pdest; + int count; + fixed16_t s, t, snext, tnext, sstep, tstep; + float sdivz, tdivz, zi, z, du, dv; + float sdivz8stepu, tdivz8stepu, zi8stepu; + + sstep = 0; // keep compiler happy + tstep = 0; // ditto + + sdivz8stepu = d_sdivzstepu * 8; + tdivz8stepu = d_tdivzstepu * 8; + zi8stepu = d_zistepu * 8 * 65536; + + do { + pdest = (short *) d_viewbuffer + (screenwidth * pspan->v) + + pspan->u; + + count = pspan->count; + + // calculate the initial s/z, t/z, 1/z, s, and t and clamp + du = (float) pspan->u; + dv = (float) pspan->v; + + sdivz = d_sdivzorigin + dv * d_sdivzstepv + du * d_sdivzstepu; + tdivz = d_tdivzorigin + dv * d_tdivzstepv + du * d_tdivzstepu; + zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f; + z = d_zitable[(int) zi]; + + s = (int) (sdivz * z) + sadjust; + s = bound(0, s, bbextents); + t = (int) (tdivz * z) + tadjust; + t = bound(0, t, bbextentt); + + while(count >= 8) { + count -= 8; + // calculate s/z, t/z, zi->fixed s and t at far end of span, + // calculate s and t steps across span by shifting + sdivz += sdivz8stepu; + tdivz += tdivz8stepu; + zi += zi8stepu; + z = d_zitable[(int) zi]; + + // prevent round-off error on <0 steps from from causing + // overstepping & running off the edge of the texture + snext = (int) (sdivz * z) + sadjust; + snext = bound(8, snext, bbextents); + tnext = (int) (tdivz * z) + tadjust; + tnext = bound(8, tnext, bbextentt); + + sstep = (snext - s) >> 3; + tstep = (tnext - t) >> 3; + + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[2] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[3] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[4] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[5] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[6] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[7] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s = snext;t = tnext; + pdest += 8; + } + if (count) + { + // calculate s/z, t/z, zi->fixed s and t at last pixel in span + // (so can't step off polygon), clamp, calculate s and t steps + // across span by division, biasing steps low so we don't run + // off the texture + //countminus1 = (float) (count - 1); + sdivz += d_sdivzstepu * count; //minus1; + tdivz += d_tdivzstepu * count; //minus1; + zi += d_zistepu * 65536.0f * count; //minus1; + z = d_zitable[(int) zi]; + + // prevent round-off error on <0 steps from from causing + // overstepping & running off the edge of the texture + snext = (int) (sdivz * z) + sadjust; + snext = bound(count, snext, bbextents); + tnext = (int) (tdivz * z) + tadjust; + tnext = bound(count, tnext, bbextentt); + + if (count > 1) { + sstep = (snext - s) / count; //(count - 1); + tstep = (tnext - t) / count; //(count - 1); + + if (count & 4) + { + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[2] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[3] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep;t += tstep; + pdest += 4; + } + if (count & 2) + { + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest += 2; + } + if (count & 1) + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + } + else + { + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + } + } + } while ((pspan = pspan->pnext) != NULL); + } + break; + case 4: + { + int *pbase = (int *) cacheblock, *pdest; + int count; + fixed16_t s, t, snext, tnext, sstep, tstep; + float sdivz, tdivz, zi, z, du, dv; + float sdivz8stepu, tdivz8stepu, zi8stepu; + + sstep = 0; // keep compiler happy + tstep = 0; // ditto + + sdivz8stepu = d_sdivzstepu * 8; + tdivz8stepu = d_tdivzstepu * 8; + zi8stepu = d_zistepu * 8 * 65536; + + do { + pdest = (int *) d_viewbuffer + (screenwidth * pspan->v) + pspan->u; + + count = pspan->count; + + // calculate the initial s/z, t/z, 1/z, s, and t and clamp + du = (float) pspan->u; + dv = (float) pspan->v; + + sdivz = d_sdivzorigin + dv * d_sdivzstepv + du * d_sdivzstepu; + tdivz = d_tdivzorigin + dv * d_tdivzstepv + du * d_tdivzstepu; + zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f; + z = d_zitable[(int) zi]; + + s = (int) (sdivz * z) + sadjust; + s = bound(0, s, bbextents); + t = (int) (tdivz * z) + tadjust; + t = bound(0, t, bbextentt); + + while(count >= 8) { + count -= 8; + // calculate s/z, t/z, zi->fixed s and t at far end of span, + // calculate s and t steps across span by shifting + sdivz += sdivz8stepu; + tdivz += tdivz8stepu; + zi += zi8stepu; + z = d_zitable[(int) zi]; + + // prevent round-off error on <0 steps from from causing + // overstepping & running off the edge of the texture + snext = (int) (sdivz * z) + sadjust; + snext = bound(8, snext, bbextents); + tnext = (int) (tdivz * z) + tadjust; + tnext = bound(8, tnext, bbextentt); + + sstep = (snext - s) >> 3; + tstep = (tnext - t) >> 3; + + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[2] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[3] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[4] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[5] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[6] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[7] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s = snext; + t = tnext; + pdest += 8; + } + if (count) + { + // calculate s/z, t/z, zi->fixed s and t at last pixel in span + // (so can't step off polygon), clamp, calculate s and t steps + // across span by division, biasing steps low so we don't run + // off the texture + //countminus1 = (float) (count - 1); + sdivz += d_sdivzstepu * count; //minus1; + tdivz += d_tdivzstepu * count; //minus1; + zi += d_zistepu * 65536.0f * count; //minus1; + z = d_zitable[(int) zi]; + + // prevent round-off error on <0 steps from from causing + // overstepping & running off the edge of the texture + snext = (int) (sdivz * z) + sadjust; + snext = bound(count, snext, bbextents); + tnext = (int) (tdivz * z) + tadjust; + tnext = bound(count, tnext, bbextentt); + + if (count > 1) { + sstep = (snext - s) / count; //(count - 1); + tstep = (tnext - t) / count; //(count - 1); + + if (count & 4) + { + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[2] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[3] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest += 4; + } + if (count & 2) + { + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest[1] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + pdest += 2; + } + if (count & 1) + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + } + else + { + pdest[0] = pbase[(t >> 16) * cachewidth + (s >> 16)]; + s += sstep; + t += tstep; + } + } + } while ((pspan = pspan->pnext) != NULL); + } + break; + default: + Sys_Error("D_DrawSpans: unsupported r_pixbytes %i\n", r_pixbytes); + } +} + +void +D_DrawZSpans (espan_t *pspan) +{ + int count, doublecount, izistep; + int izi; + short *pdest; + unsigned int ltemp; + double zi; + float du, dv; + + // FIXME: check for clamping/range problems + // we count on FP exceptions being turned off to avoid range problems + izistep = (int) (d_zistepu * 0x8000 * 0x10000); + + do { + pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; + + count = pspan->count; + + // calculate the initial 1/z + du = (float) pspan->u; + dv = (float) pspan->v; + + zi = d_ziorigin + dv * d_zistepv + du * d_zistepu; + // we count on FP exceptions being turned off to avoid range problems + izi = (int) (zi * 0x8000 * 0x10000); + + // LordHavoc: added big endian case, the old code is not correct on + // big-endian (results in swapped depth pairs), and is tuned more for + // x86, PowerPC compilers can probably do a good job with raw loop + // unrolling if it is even necessary... + if (bigendien) // DESPAIR: was bigendian. this correct? + { + do + { + *pdest++ = (short) (izi >> 16); + izi += izistep; + } + while(--count); + } + else + { + if ((long) pdest & 0x02) { + *pdest++ = (short) (izi >> 16); + izi += izistep; + count--; + } + + if ((doublecount = count >> 1) > 0) { + do { + ltemp = izi >> 16; + izi += izistep; + ltemp |= izi & 0xFFFF0000; + izi += izistep; + *(int *) pdest = ltemp; + pdest += 2; + } while (--doublecount > 0); + } + + if (count & 1) + *pdest = (short) (izi >> 16); + } + } while ((pspan = pspan->pnext) != NULL); +} diff --git a/libs/video/renderer/sw32/d_sky.c b/libs/video/renderer/sw32/d_sky.c new file mode 100644 index 000000000..a0d872c97 --- /dev/null +++ b/libs/video/renderer/sw32/d_sky.c @@ -0,0 +1,277 @@ +/* + d_sky.c + + (description) + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/render.h" +#include "QF/sys.h" + +#include "d_local.h" +#include "r_local.h" +// #include "vid.h" // DESPAIR + +#define SKY_SPAN_SHIFT 5 +#define SKY_SPAN_MAX (1 << SKY_SPAN_SHIFT) + + +void +D_Sky_uv_To_st (int u, int v, fixed16_t *s, fixed16_t *t) +{ + float wu, wv, temp; + vec3_t end; + + if (r_refdef.vrect.width >= r_refdef.vrect.height) + temp = (float) r_refdef.vrect.width; + else + temp = (float) r_refdef.vrect.height; + + wu = 8192.0 * (float) (u - ((int) vid.width >> 1)) / temp; + wv = 8192.0 * (float) (((int) vid.height >> 1) - v) / temp; + + end[0] = 4096 * vpn[0] + wu * vright[0] + wv * vup[0]; + end[1] = 4096 * vpn[1] + wu * vright[1] + wv * vup[1]; + end[2] = 4096 * vpn[2] + wu * vright[2] + wv * vup[2]; + end[2] *= 3; + VectorNormalize (end); + + temp = skytime * skyspeed; // TODO: add D_SetupFrame & set this there + *s = (int) ((temp + 6 * (SKYSIZE / 2 - 1) * end[0]) * 0x10000); + *t = (int) ((temp + 6 * (SKYSIZE / 2 - 1) * end[1]) * 0x10000); +} + +void +D_DrawSkyScans (espan_t *pspan) +{ + switch(r_pixbytes) { + case 1: + { + int count, spancount, u, v; + byte *pdest; + fixed16_t s, t, snext, tnext, sstep, tstep; + int spancountminus1; + + sstep = 0; // keep compiler happy + tstep = 0; // ditto + + do { + pdest = (byte *) d_viewbuffer + screenwidth * pspan->v + pspan->u; + + count = pspan->count; + + // calculate the initial s & t + u = pspan->u; + v = pspan->v; + D_Sky_uv_To_st (u, v, &s, &t); + + do { + if (count >= SKY_SPAN_MAX) + spancount = SKY_SPAN_MAX; + else + spancount = count; + + count -= spancount; + + if (count) { + u += spancount; + + // calculate s and t at far end of span, + // calculate s and t steps across span by shifting + D_Sky_uv_To_st (u, v, &snext, &tnext); + + sstep = (snext - s) >> SKY_SPAN_SHIFT; + tstep = (tnext - t) >> SKY_SPAN_SHIFT; + } else { + // calculate s and t at last pixel in span, + // calculate s and t steps across span by division + spancountminus1 = (float) (spancount - 1); + + if (spancountminus1 > 0) { + u += spancountminus1; + D_Sky_uv_To_st (u, v, &snext, &tnext); + + sstep = (snext - s) / spancountminus1; + tstep = (tnext - t) / spancountminus1; + } + } + + do { + *pdest++ = ((byte *) r_skysource) + [((t & R_SKY_TMASK) >> 8) + ((s & R_SKY_SMASK) >> 16)]; + s += sstep; + t += tstep; + } while (--spancount > 0); + + s = snext; + t = tnext; + + } while (count > 0); + + } while ((pspan = pspan->pnext) != NULL); + } + break; + + case 2: + { + int count, spancount, u, v; + short *pdest; + fixed16_t s, t, snext, tnext, sstep, tstep; + int spancountminus1; + + sstep = 0; // keep compiler happy + tstep = 0; // ditto + + do { + pdest = (short *) d_viewbuffer + screenwidth * pspan->v + pspan->u; + + count = pspan->count; + + // calculate the initial s & t + u = pspan->u; + v = pspan->v; + D_Sky_uv_To_st (u, v, &s, &t); + + do { + if (count >= SKY_SPAN_MAX) + spancount = SKY_SPAN_MAX; + else + spancount = count; + + count -= spancount; + + if (count) { + u += spancount; + + // calculate s and t at far end of span, + // calculate s and t steps across span by shifting + D_Sky_uv_To_st (u, v, &snext, &tnext); + + sstep = (snext - s) >> SKY_SPAN_SHIFT; + tstep = (tnext - t) >> SKY_SPAN_SHIFT; + } else { + // calculate s and t at last pixel in span, + // calculate s and t steps across span by division + spancountminus1 = (float) (spancount - 1); + + if (spancountminus1 > 0) { + u += spancountminus1; + D_Sky_uv_To_st (u, v, &snext, &tnext); + + sstep = (snext - s) / spancountminus1; + tstep = (tnext - t) / spancountminus1; + } + } + + do { + *pdest++ = ((short *) r_skysource) + [((t & R_SKY_TMASK) >> 8) + ((s & R_SKY_SMASK) >> 16)]; + s += sstep; + t += tstep; + } while (--spancount > 0); + + s = snext; + t = tnext; + + } while (count > 0); + + } while ((pspan = pspan->pnext) != NULL); + } + break; + + case 4: + { + int count, spancount, u, v; + int *pdest; + fixed16_t s, t, snext, tnext, sstep, tstep; + int spancountminus1; + + sstep = 0; // keep compiler happy + tstep = 0; // ditto + + do { + pdest = (int *) d_viewbuffer + screenwidth * pspan->v + pspan->u; + + count = pspan->count; + + // calculate the initial s & t + u = pspan->u; + v = pspan->v; + D_Sky_uv_To_st (u, v, &s, &t); + + do { + if (count >= SKY_SPAN_MAX) + spancount = SKY_SPAN_MAX; + else + spancount = count; + + count -= spancount; + + if (count) { + u += spancount; + + // calculate s and t at far end of span, + // calculate s and t steps across span by shifting + D_Sky_uv_To_st (u, v, &snext, &tnext); + + sstep = (snext - s) >> SKY_SPAN_SHIFT; + tstep = (tnext - t) >> SKY_SPAN_SHIFT; + } else { + // calculate s and t at last pixel in span, + // calculate s and t steps across span by division + spancountminus1 = (float) (spancount - 1); + + if (spancountminus1 > 0) { + u += spancountminus1; + D_Sky_uv_To_st (u, v, &snext, &tnext); + + sstep = (snext - s) / spancountminus1; + tstep = (tnext - t) / spancountminus1; + } + } + + do { + *pdest++ = ((int *) r_skysource) + [((t & R_SKY_TMASK) >> 8) + ((s & R_SKY_SMASK) >> 16)]; + s += sstep; + t += tstep; + } while (--spancount > 0); + + s = snext; + t = tnext; + + } while (count > 0); + + } while ((pspan = pspan->pnext) != NULL); + } + break; + + default: + Sys_Error("D_DrawSkyScans: unsupported r_pixbytes %i\n", r_pixbytes); + } +} diff --git a/libs/video/renderer/sw32/d_sprite.c b/libs/video/renderer/sw32/d_sprite.c new file mode 100644 index 000000000..3e6f179da --- /dev/null +++ b/libs/video/renderer/sw32/d_sprite.c @@ -0,0 +1,728 @@ +/* + d_sprite.c + + software top-level rasterization driver module for drawing sprites + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/render.h" +#include "QF/sys.h" + +#include "d_local.h" +// #include "vid.h" // DESPAIR + +static int sprite_height; +static int minindex, maxindex; +static sspan_t *sprite_spans; + +extern float *d_zitable; // DESPAIR + + +void +D_SpriteDrawSpans (sspan_t *pspan) +{ + switch(r_pixbytes) { + case 1: + { + int count, spancount, izistep; + int izi; + byte *pbase; + byte *pdest; + fixed16_t s, t, snext, tnext, sstep, tstep; + float sdivz, tdivz, zi, z, du, dv, spancountminus1; + float sdivz8stepu, tdivz8stepu, zi8stepu; + byte btemp; + short *pz; + + sstep = 0; // keep compiler happy + tstep = 0; // ditto + + pbase = (byte *) cacheblock; + + sdivz8stepu = d_sdivzstepu * 8; + tdivz8stepu = d_tdivzstepu * 8; + zi8stepu = d_zistepu * 8 * 65536.0f; + + // we count on FP exceptions being turned off to avoid range problems + izistep = (int) (d_zistepu * 0x8000 * 0x10000); + + do { + pdest = (byte *) d_viewbuffer + screenwidth * pspan->v + pspan->u; + pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; + + count = pspan->count; + + if (count <= 0) + goto NextSpan1; + + // calculate the initial s/z, t/z, 1/z, s, and t and clamp + du = (float) pspan->u; + dv = (float) pspan->v; + + sdivz = d_sdivzorigin + dv * d_sdivzstepv + du * d_sdivzstepu; + tdivz = d_tdivzorigin + dv * d_tdivzstepv + du * d_tdivzstepu; + zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f; + z = d_zitable[(int) zi]; + // we count on FP exceptions being turned off to avoid range + // problems + + izi = (int) (zi * 0x8000); + + s = (int) (sdivz * z) + sadjust; + if (s > bbextents) + s = bbextents; + else if (s < 0) + s = 0; + + t = (int) (tdivz * z) + tadjust; + if (t > bbextentt) + t = bbextentt; + else if (t < 0) + t = 0; + + do { + // calculate s and t at the far end of the span + if (count >= 8) + spancount = 8; + else + spancount = count; + + count -= spancount; + + if (count) { + // calculate s/z, t/z, zi->fixed s and t at far end of + // span, calculate s and t steps across span by shifting + sdivz += sdivz8stepu; + tdivz += tdivz8stepu; + zi += zi8stepu; + z = d_zitable[(int) zi]; + + snext = (int) (sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 8) + snext = 8; // prevent round-off error on <0 + // steps from causing overstepping + // & running off the texture's edge + + tnext = (int) (tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 8) + tnext = 8; // guard against round-off + // error on <0 steps + + sstep = (snext - s) >> 3; + tstep = (tnext - t) >> 3; + } else { + // calculate s/z, t/z, zi->fixed s and t at last pixel + // in span (so can't step off polygon), clamp, + // calculate s and t steps across span by division, + // biasing steps low so we don't run off the texture + spancountminus1 = (float) (spancount - 1); + sdivz += d_sdivzstepu * spancountminus1; + tdivz += d_tdivzstepu * spancountminus1; + zi += d_zistepu * 65536.0f * spancountminus1; + z = d_zitable[(int) zi]; + snext = (int) (sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 8) + snext = 8; // prevent round-off error on <0 + // steps from from causing + // overstepping & running off the + // edge of the texture + + tnext = (int) (tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 8) + tnext = 8; // guard against round-off error on + // <0 steps + + if (spancount > 1) { + sstep = (snext - s) / (spancount - 1); + tstep = (tnext - t) / (spancount - 1); + } + } + + do { + btemp = pbase[(s >> 16) + (t >> 16) * cachewidth]; + if (btemp != TRANSPARENT_COLOR) { + if (*pz <= (izi >> 16)) { + *pz = izi >> 16; + *pdest = btemp; + } + } + + izi += izistep; + pdest++; + pz++; + s += sstep; + t += tstep; + } while (--spancount > 0); + + s = snext; + t = tnext; + + } while (count > 0); + +NextSpan1: + pspan++; + + } while (pspan->count != DS_SPAN_LIST_END); + } + break; + + case 2: + { + int count, spancount, izistep; + int izi; + byte *pbase; + short *pdest; + fixed16_t s, t, snext, tnext, sstep, tstep; + float sdivz, tdivz, zi, z, du, dv, spancountminus1; + float sdivz8stepu, tdivz8stepu, zi8stepu; + byte btemp; + short *pz; + + sstep = 0; // keep compiler happy + tstep = 0; // ditto + + pbase = (byte *) cacheblock; + + sdivz8stepu = d_sdivzstepu * 8; + tdivz8stepu = d_tdivzstepu * 8; + zi8stepu = d_zistepu * 8 * 65536; + + // we count on FP exceptions being turned off to avoid range problems + izistep = (int) (d_zistepu * 0x8000 * 0x10000); + + do { + pdest = (short *) d_viewbuffer + screenwidth * pspan->v + pspan->u; + pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; + + count = pspan->count; + + if (count <= 0) + goto NextSpan2; + + // calculate the initial s/z, t/z, 1/z, s, and t and clamp + du = (float) pspan->u; + dv = (float) pspan->v; + + sdivz = d_sdivzorigin + dv * d_sdivzstepv + du * d_sdivzstepu; + tdivz = d_tdivzorigin + dv * d_tdivzstepv + du * d_tdivzstepu; + zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f; + z = d_zitable[(int) zi]; + // we count on FP exceptions being turned off to avoid range + // problems + izi = (int) (zi * 0x8000); + + s = (int) (sdivz * z) + sadjust; + if (s > bbextents) + s = bbextents; + else if (s < 0) + s = 0; + + t = (int) (tdivz * z) + tadjust; + if (t > bbextentt) + t = bbextentt; + else if (t < 0) + t = 0; + + do { + // calculate s and t at the far end of the span + if (count >= 8) + spancount = 8; + else + spancount = count; + + count -= spancount; + + if (count) { + // calculate s/z, t/z, zi->fixed s and t at far end of + // span, calculate s and t steps across span by shifting + sdivz += sdivz8stepu; + tdivz += tdivz8stepu; + zi += zi8stepu; + z = d_zitable[(int) zi]; + + snext = (int) (sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 8) + snext = 8; // prevent round-off error on <0 + // steps from causing overstepping + // & running off the texture's edge + + tnext = (int) (tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 8) + tnext = 8; // guard against round-off error on + // <0 steps + + sstep = (snext - s) >> 3; + tstep = (tnext - t) >> 3; + } else { + // calculate s/z, t/z, zi->fixed s and t at last pixel in + // span (so can't step off polygon), clamp, calculate s + // and t steps across span by division, biasing steps + // low so we don't run off the texture + spancountminus1 = (float) (spancount - 1); + sdivz += d_sdivzstepu * spancountminus1; + tdivz += d_tdivzstepu * spancountminus1; + zi += d_zistepu * 65536.0f * spancountminus1; + z = d_zitable[(int) zi]; + snext = (int) (sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 8) + snext = 8; // prevent round-off error on <0 + // steps from from causing + // overstepping & running off the + // edge of the texture + + tnext = (int) (tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 8) + tnext = 8; // guard against round-off error on + // <0 steps + + if (spancount > 1) { + sstep = (snext - s) / (spancount - 1); + tstep = (tnext - t) / (spancount - 1); + } + } + + do { + btemp = pbase[(s >> 16) + (t >> 16) * cachewidth]; + if (btemp != TRANSPARENT_COLOR) { + if (*pz <= (izi >> 16)) { + *pz = izi >> 16; + *pdest = d_8to16table[btemp]; + } + } + + izi += izistep; + pdest++; + pz++; + s += sstep; + t += tstep; + } while (--spancount > 0); + + s = snext; + t = tnext; + + } while (count > 0); + +NextSpan2: + pspan++; + + } while (pspan->count != DS_SPAN_LIST_END); + } + break; + + case 4: + { + int count, spancount, izistep; + int izi; + byte *pbase; + int *pdest; + fixed16_t s, t, snext, tnext, sstep, tstep; + float sdivz, tdivz, zi, z, du, dv, spancountminus1; + float sdivz8stepu, tdivz8stepu, zi8stepu; + byte btemp; + short *pz; + + sstep = 0; // keep compiler happy + tstep = 0; // ditto + + pbase = (byte *) cacheblock; + + sdivz8stepu = d_sdivzstepu * 8; + tdivz8stepu = d_tdivzstepu * 8; + zi8stepu = d_zistepu * 8 * 65536; + + // we count on FP exceptions being turned off to avoid range problems + izistep = (int) (d_zistepu * 0x8000 * 0x10000); + + do { + pdest = (int *) d_viewbuffer + screenwidth * pspan->v + pspan->u; + pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; + + count = pspan->count; + + if (count <= 0) + goto NextSpan4; + + // calculate the initial s/z, t/z, 1/z, s, and t and clamp + du = (float) pspan->u; + dv = (float) pspan->v; + + sdivz = d_sdivzorigin + dv * d_sdivzstepv + du * d_sdivzstepu; + tdivz = d_tdivzorigin + dv * d_tdivzstepv + du * d_tdivzstepu; + zi = (d_ziorigin + dv * d_zistepv + du * d_zistepu) * 65536.0f; + z = d_zitable[(int) zi]; + // we count on FP exceptions being turned off to avoid range + // problems + izi = (int) (zi * 0x8000); + + s = (int) (sdivz * z) + sadjust; + if (s > bbextents) + s = bbextents; + else if (s < 0) + s = 0; + + t = (int) (tdivz * z) + tadjust; + if (t > bbextentt) + t = bbextentt; + else if (t < 0) + t = 0; + + do { + // calculate s and t at the far end of the span + if (count >= 8) + spancount = 8; + else + spancount = count; + + count -= spancount; + + if (count) { + // calculate s/z, t/z, zi->fixed s and t at far end of + // span, calculate s and t steps across span by shifting + sdivz += sdivz8stepu; + tdivz += tdivz8stepu; + zi += zi8stepu; + z = d_zitable[(int) zi]; + + snext = (int) (sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 8) + snext = 8; // prevent round-off error on <0 + // steps from causing overstepping + // & running off the texture's edge + + tnext = (int) (tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 8) + tnext = 8; // guard against round-off error on + // <0 steps + + sstep = (snext - s) >> 3; + tstep = (tnext - t) >> 3; + } else { + // calculate s/z, t/z, zi->fixed s and t at last pixel in + // span (so can't step off polygon), clamp, calculate s + // and t steps across span by division, biasing steps low + // so we don't run off the texture + spancountminus1 = (float) (spancount - 1); + sdivz += d_sdivzstepu * spancountminus1; + tdivz += d_tdivzstepu * spancountminus1; + zi += d_zistepu * 65536.0f * spancountminus1; + z = d_zitable[(int) zi]; + snext = (int) (sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 8) + snext = 8; // prevent round-off error on <0 + // steps fromcausing overstepping + // & running off the texture's edge + + tnext = (int) (tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 8) + tnext = 8; // guard against round-off error on + // <0 steps + + if (spancount > 1) { + sstep = (snext - s) / (spancount - 1); + tstep = (tnext - t) / (spancount - 1); + } + } + + do { + btemp = pbase[(s >> 16) + (t >> 16) * cachewidth]; + if (btemp != TRANSPARENT_COLOR) { + if (*pz <= (izi >> 16)) { + *pz = izi >> 16; + *pdest = d_8to24table[btemp]; + } + } + + izi += izistep; + pdest++; + pz++; + s += sstep; + t += tstep; + } while (--spancount > 0); + + s = snext; + t = tnext; + + } while (count > 0); + +NextSpan4: + pspan++; + + } while (pspan->count != DS_SPAN_LIST_END); + } + break; + + default: + Sys_Error("D_SpriteDrawSpans: unsupported r_pixbytes %i\n", + r_pixbytes); + } +} + +void +D_SpriteScanLeftEdge (void) +{ + int i, v, itop, ibottom, lmaxindex; + emitpoint_t *pvert, *pnext; + sspan_t *pspan; + float du, dv, vtop, vbottom, slope; + fixed16_t u, u_step; + + pspan = sprite_spans; + i = minindex; + if (i == 0) + i = r_spritedesc.nump; + + lmaxindex = maxindex; + if (lmaxindex == 0) + lmaxindex = r_spritedesc.nump; + + vtop = ceil (r_spritedesc.pverts[i].v); + + do { + pvert = &r_spritedesc.pverts[i]; + pnext = pvert - 1; + + vbottom = ceil (pnext->v); + + if (vtop < vbottom) { + du = pnext->u - pvert->u; + dv = pnext->v - pvert->v; + slope = du / dv; + u_step = (int) (slope * 0x10000); + // adjust u to ceil the integer portion + u = (int) ((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) + + (0x10000 - 1); + itop = (int) vtop; + ibottom = (int) vbottom; + + for (v = itop; v < ibottom; v++) { + pspan->u = u >> 16; + pspan->v = v; + u += u_step; + pspan++; + } + } + + vtop = vbottom; + + i--; + if (i == 0) + i = r_spritedesc.nump; + + } while (i != lmaxindex); +} + +void +D_SpriteScanRightEdge (void) +{ + int i, v, itop, ibottom; + emitpoint_t *pvert, *pnext; + sspan_t *pspan; + float du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext; + fixed16_t u, u_step; + + pspan = sprite_spans; + i = minindex; + + vvert = r_spritedesc.pverts[i].v; + if (vvert < r_refdef.fvrecty_adj) + vvert = r_refdef.fvrecty_adj; + if (vvert > r_refdef.fvrectbottom_adj) + vvert = r_refdef.fvrectbottom_adj; + + vtop = ceil (vvert); + + do { + pvert = &r_spritedesc.pverts[i]; + pnext = pvert + 1; + + vnext = pnext->v; + if (vnext < r_refdef.fvrecty_adj) + vnext = r_refdef.fvrecty_adj; + if (vnext > r_refdef.fvrectbottom_adj) + vnext = r_refdef.fvrectbottom_adj; + + vbottom = ceil (vnext); + + if (vtop < vbottom) { + uvert = pvert->u; + if (uvert < r_refdef.fvrectx_adj) + uvert = r_refdef.fvrectx_adj; + if (uvert > r_refdef.fvrectright_adj) + uvert = r_refdef.fvrectright_adj; + + unext = pnext->u; + if (unext < r_refdef.fvrectx_adj) + unext = r_refdef.fvrectx_adj; + if (unext > r_refdef.fvrectright_adj) + unext = r_refdef.fvrectright_adj; + + du = unext - uvert; + dv = vnext - vvert; + slope = du / dv; + u_step = (int) (slope * 0x10000); + // adjust u to ceil the integer portion + u = (int) ((uvert + (slope * (vtop - vvert))) * 0x10000) + + (0x10000 - 1); + itop = (int) vtop; + ibottom = (int) vbottom; + + for (v = itop; v < ibottom; v++) { + pspan->count = (u >> 16) - pspan->u; + u += u_step; + pspan++; + } + } + + vtop = vbottom; + vvert = vnext; + + i++; + if (i == r_spritedesc.nump) + i = 0; + + } while (i != maxindex); + + pspan->count = DS_SPAN_LIST_END; // mark the end of the span list +} + +void +D_SpriteCalculateGradients (void) +{ + vec3_t p_normal, p_saxis, p_taxis, p_temp1; + float distinv; + + TransformVector (r_spritedesc.vpn, p_normal); + TransformVector (r_spritedesc.vright, p_saxis); + TransformVector (r_spritedesc.vup, p_taxis); + VectorInverse (p_taxis); + + distinv = 1.0 / (-DotProduct (modelorg, r_spritedesc.vpn)); + + d_sdivzstepu = p_saxis[0] * xscaleinv; + d_tdivzstepu = p_taxis[0] * xscaleinv; + + d_sdivzstepv = -p_saxis[1] * yscaleinv; + d_tdivzstepv = -p_taxis[1] * yscaleinv; + + d_zistepu = p_normal[0] * xscaleinv * distinv; + d_zistepv = -p_normal[1] * yscaleinv * distinv; + + d_sdivzorigin = p_saxis[2] - xcenter * d_sdivzstepu - + ycenter * d_sdivzstepv; + d_tdivzorigin = p_taxis[2] - xcenter * d_tdivzstepu - + ycenter * d_tdivzstepv; + d_ziorigin = p_normal[2] * distinv - xcenter * d_zistepu - + ycenter * d_zistepv; + + TransformVector (modelorg, p_temp1); + + sadjust = ((fixed16_t) (DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) - + (-(cachewidth >> 1) << 16); + tadjust = ((fixed16_t) (DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) - + (-(sprite_height >> 1) << 16); + + // -1 (-epsilon) so we never wander off the edge of the texture + bbextents = (cachewidth << 16) - 1; + bbextentt = (sprite_height << 16) - 1; +} + +void +D_DrawSprite (void) +{ + int i, nump; + float ymin, ymax; + emitpoint_t *pverts; + sspan_t spans[MAXHEIGHT + 1]; + + sprite_spans = spans; + + // find the top and bottom vertices, and make sure there's at least one + // scan to draw + ymin = 999999.9; + ymax = -999999.9; + pverts = r_spritedesc.pverts; + + for (i = 0; i < r_spritedesc.nump; i++) { + if (pverts->v < ymin) { + ymin = pverts->v; + minindex = i; + } + + if (pverts->v > ymax) { + ymax = pverts->v; + maxindex = i; + } + + pverts++; + } + + ymin = ceil (ymin); + ymax = ceil (ymax); + + if (ymin >= ymax) + return; // doesn't cross any scans at all + + cachewidth = r_spritedesc.pspriteframe->width; + sprite_height = r_spritedesc.pspriteframe->height; + cacheblock = (void *) (&r_spritedesc.pspriteframe->pixels[0]); + + // copy the first vertex to the last vertex, so we don't have to deal with + // wrapping + nump = r_spritedesc.nump; + pverts = r_spritedesc.pverts; + pverts[nump] = pverts[0]; + + D_SpriteCalculateGradients (); + D_SpriteScanLeftEdge (); + D_SpriteScanRightEdge (); + D_SpriteDrawSpans (sprite_spans); +} diff --git a/libs/video/renderer/sw32/d_surf.c b/libs/video/renderer/sw32/d_surf.c new file mode 100644 index 000000000..1bb4f3ad7 --- /dev/null +++ b/libs/video/renderer/sw32/d_surf.c @@ -0,0 +1,318 @@ +/* + d_surf.c + + rasterization driver surface heap manager + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "QF/qargs.h" +#include "QF/sys.h" + +#include "d_local.h" +#include "r_local.h" + +float surfscale; +qboolean r_cache_thrash; // set if surface cache is thrashing + +int sc_size; +surfcache_t *sc_rover, *sc_base; + +#define GUARDSIZE 4 + + +void * +D_SurfaceCacheAddress (void) +{ + return sc_base; +} + +int +D_SurfaceCacheForRes (int width, int height) +{ + int size, pix; + + if (COM_CheckParm ("-surfcachesize")) { + size = atoi (com_argv[COM_CheckParm ("-surfcachesize") + 1]) * 1024; + return size; + } + + size = SURFCACHE_SIZE_AT_320X200; + + pix = width * height; + if (pix > 64000) + size += (pix - 64000) * 3; + + size *= r_pixbytes; + + return size; +} + +void +D_CheckCacheGuard (void) +{ + byte *s; + int i; + + s = (byte *) sc_base + sc_size; + for (i = 0; i < GUARDSIZE; i++) + if (s[i] != (byte) i) + Sys_Error ("D_CheckCacheGuard: failed"); +} + +void +D_ClearCacheGuard (void) +{ + byte *s; + int i; + + s = (byte *) sc_base + sc_size; + for (i = 0; i < GUARDSIZE; i++) + s[i] = (byte) i; +} + +void +D_InitCaches (void *buffer, int size) +{ +// if (!msg_suppress_1) +// Con_Printf ("%ik surface cache\n", size/1024); + + sc_size = size - GUARDSIZE; + sc_base = (surfcache_t *) buffer; + sc_rover = sc_base; + + sc_base->next = NULL; + sc_base->owner = NULL; + sc_base->size = sc_size; + + D_ClearCacheGuard (); +} + +void +D_FlushCaches (void) +{ + surfcache_t *c; + + if (!sc_base) + return; + + for (c = sc_base; c; c = c->next) { + if (c->owner) + *c->owner = NULL; + } + + sc_rover = sc_base; + sc_base->next = NULL; + sc_base->owner = NULL; + sc_base->size = sc_size; +} + +surfcache_t * +D_SCAlloc (int width, int size) +{ + surfcache_t *new; + qboolean wrapped_this_time; + + if ((width < 0) || (width > 256)) + Sys_Error ("D_SCAlloc: bad cache width %d\n", width); + + if ((size <= 0) || (size > (0x10000 * r_pixbytes))) + Sys_Error ("D_SCAlloc: bad cache size %d\n", size); + + /* This adds the offset of data[0] in the surfcache_t struct. */ + size += (int) ((surfcache_t *) 0)->data; + +#define SIZE_ALIGN (sizeof(surfcache_t*)-1) + size = (size + SIZE_ALIGN) & ~SIZE_ALIGN; +#undef SIZE_ALIGN + size = (size + 3) & ~3; + if (size > sc_size) + Sys_Error ("D_SCAlloc: %i > cache size", size); + + // if there is not size bytes after the rover, reset to the start + wrapped_this_time = false; + + if (!sc_rover || (byte *) sc_rover - (byte *) sc_base > sc_size - size) { + if (sc_rover) + wrapped_this_time = true; + sc_rover = sc_base; + } + // colect and free surfcache_t blocks until the rover block is large enough + new = sc_rover; + if (sc_rover->owner) + *sc_rover->owner = NULL; + + while (new->size < size) { + // free another + sc_rover = sc_rover->next; + if (!sc_rover) + Sys_Error ("D_SCAlloc: hit the end of memory"); + if (sc_rover->owner) + *sc_rover->owner = NULL; + + new->size += sc_rover->size; + new->next = sc_rover->next; + } + + // create a fragment out of any leftovers + if (new->size - size > 256) { + sc_rover = (surfcache_t *) ((byte *) new + size); + sc_rover->size = new->size - size; + sc_rover->next = new->next; + sc_rover->width = 0; + sc_rover->owner = NULL; + new->next = sc_rover; + new->size = size; + } else + sc_rover = new->next; + + new->width = width; +// DEBUG + if (width > 0) + new->height = (size - sizeof (*new) + sizeof (new->data)) / + (width * r_pixbytes); + + new->owner = NULL; // should be set properly after return + + if (d_roverwrapped) { + if (wrapped_this_time || (sc_rover >= d_initial_rover)) + r_cache_thrash = true; + } else if (wrapped_this_time) + d_roverwrapped = true; + + D_CheckCacheGuard (); // DEBUG + return new; +} + +void +D_SCDump (void) +{ + surfcache_t *test; + + for (test = sc_base; test; test = test->next) { + if (test == sc_rover) + Sys_Printf ("ROVER:\n"); + Sys_Printf ("%p : %i bytes %i width\n", test, test->size, + test->width); + } +} + +//============================================================================= + +// if the num is not a power of 2, assume it will not repeat + +int +MaskForNum (int num) +{ + if (num == 128) + return 127; + if (num == 64) + return 63; + if (num == 32) + return 31; + if (num == 16) + return 15; + return 255; +} + +int +D_log2 (int num) +{ + int c; + + c = 0; + + while (num >>= 1) + c++; + return c; +} + +//============================================================================= + +surfcache_t * +D_CacheSurface (msurface_t *surface, int miplevel) +{ + surfcache_t *cache; + + // if the surface is animating or flashing, flush the cache + r_drawsurf.texture = R_TextureAnimation (surface->texinfo->texture); + r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]]; + r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]]; + r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]]; + r_drawsurf.lightadj[3] = d_lightstylevalue[surface->styles[3]]; + + // see if the cache holds apropriate data + cache = surface->cachespots[miplevel]; + + if (cache && !cache->dlight && surface->dlightframe != r_framecount + && cache->texture == r_drawsurf.texture + && cache->lightadj[0] == r_drawsurf.lightadj[0] + && cache->lightadj[1] == r_drawsurf.lightadj[1] + && cache->lightadj[2] == r_drawsurf.lightadj[2] + && cache->lightadj[3] == r_drawsurf.lightadj[3]) + return cache; + + // determine shape of surface + surfscale = 1.0 / (1 << miplevel); + r_drawsurf.surfmip = miplevel; + r_drawsurf.surfwidth = surface->extents[0] >> miplevel; + r_drawsurf.rowbytes = r_drawsurf.surfwidth * r_pixbytes; + r_drawsurf.surfheight = surface->extents[1] >> miplevel; + + // allocate memory if needed + if (!cache) // if a texture just animated, don't reallocate it + { + cache = D_SCAlloc (r_drawsurf.surfwidth, + r_drawsurf.rowbytes * r_drawsurf.surfheight); + surface->cachespots[miplevel] = cache; + cache->owner = &surface->cachespots[miplevel]; + cache->mipscale = surfscale; + } + + if (surface->dlightframe == r_framecount) + cache->dlight = 1; + else + cache->dlight = 0; + + r_drawsurf.surfdat = (byte *) cache->data; + + cache->texture = r_drawsurf.texture; + cache->lightadj[0] = r_drawsurf.lightadj[0]; + cache->lightadj[1] = r_drawsurf.lightadj[1]; + cache->lightadj[2] = r_drawsurf.lightadj[2]; + cache->lightadj[3] = r_drawsurf.lightadj[3]; + + // draw and light the surface texture + r_drawsurf.surf = surface; + + c_surf++; + R_DrawSurface (); + + return surface->cachespots[miplevel]; +} diff --git a/libs/video/renderer/sw32/d_vars.c b/libs/video/renderer/sw32/d_vars.c new file mode 100644 index 000000000..67ff861ec --- /dev/null +++ b/libs/video/renderer/sw32/d_vars.c @@ -0,0 +1,54 @@ +/* + d_vars.c + + global refresh variables + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/qtypes.h" + +// all global and static refresh variables are collected in a contiguous block +// to avoid cache conflicts. + +// global refresh variables ----------------------------- + +// FIXME: make into one big structure, like cl or sv +// FIXME: do separately for refresh engine and driver + +float d_sdivzstepu, d_tdivzstepu, d_zistepu; +float d_sdivzstepv, d_tdivzstepv, d_zistepv; +float d_sdivzorigin, d_tdivzorigin, d_ziorigin; + +fixed16_t sadjust, tadjust, bbextents, bbextentt; + +void *cacheblock; +int cachewidth; +void *d_viewbuffer; +short *d_pzbuffer; +unsigned int d_zrowbytes; +unsigned int d_zwidth; diff --git a/libs/video/renderer/sw32/d_zpoint.c b/libs/video/renderer/sw32/d_zpoint.c new file mode 100644 index 000000000..ad489f4bd --- /dev/null +++ b/libs/video/renderer/sw32/d_zpoint.c @@ -0,0 +1,70 @@ +/* + d_zpoint.c + + software driver module for drawing z-buffered points + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/sys.h" + +#include "d_local.h" +// #include "vid.h" // DESPAIR + + +void +D_DrawZPoint (void) +{ + short *pz; + int izi; + + pz = d_pzbuffer + (d_zwidth * r_zpointdesc.v) + r_zpointdesc.u; + izi = (int) (r_zpointdesc.zi * 0x8000); + + if (*pz <= izi) { + *pz = izi; + switch(r_pixbytes) + { + case 1: + ((byte *) d_viewbuffer) [d_scantable[r_zpointdesc.v] + + r_zpointdesc.u] = r_zpointdesc.color; + break; + case 2: + ((short *) d_viewbuffer) [d_scantable[r_zpointdesc.v] + + r_zpointdesc.u] = + d_8to16table[r_zpointdesc.color]; + break; + case 4: + ((int *) d_viewbuffer) [d_scantable[r_zpointdesc.v] + + r_zpointdesc.u] = + d_8to24table[r_zpointdesc.color]; + break; + default: + Sys_Error("D_DrawZPoint: unsupported r_pixbytes %i\n", r_pixbytes); + } + } +} diff --git a/libs/video/renderer/sw32/draw.c b/libs/video/renderer/sw32/draw.c new file mode 100644 index 000000000..7b83a68a2 --- /dev/null +++ b/libs/video/renderer/sw32/draw.c @@ -0,0 +1,1176 @@ +/* + draw.c + + this is the only file outside the refresh that touches the vid buffer + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include "QF/console.h" +#include "QF/cvar.h" +#include "QF/draw.h" +#include "QF/sound.h" +#include "QF/sys.h" +#include "QF/vfs.h" + +//#include "client.h" DESPAIR +//#include "quakefs.h" +//#include "vid.h" + +#include "d_iface.h" +//#include "r_cvar.h" + +typedef struct { + vrect_t rect; + int width; + int height; + byte *ptexbytes; + int rowbytes; +} rectdesc_t; + +static rectdesc_t r_rectdesc; + +byte *draw_chars; // 8*8 graphic characters +qpic_t *draw_disc; +qpic_t *draw_backtile; + +cvar_t *cl_verstring; + +// Support Routines =========================================================== + +typedef struct cachepic_s { + char name[MAX_QPATH]; + cache_user_t cache; +} cachepic_t; + +#define MAX_CACHED_PICS 128 +cachepic_t menu_cachepics[MAX_CACHED_PICS]; +int menu_numcachepics; + + +qpic_t * +Draw_PicFromWad (const char *name) +{ + return W_GetLumpName (name); +} + +void +Draw_ClearCache (void) +{ + // This is a no-op in software targets +} + +qpic_t * +Draw_CachePic (const char *path, qboolean alpha) +{ + cachepic_t *pic; + int i; + qpic_t *dat; + + for (pic = menu_cachepics, i = 0; i < menu_numcachepics; pic++, i++) + if (!strcmp (path, pic->name)) + break; + + if (i == menu_numcachepics) { + if (menu_numcachepics == MAX_CACHED_PICS) + Sys_Error ("menu_numcachepics == MAX_CACHED_PICS"); + menu_numcachepics++; + strcpy (pic->name, path); + } + + dat = Cache_Check (&pic->cache); + + if (dat) + return dat; + + // load the pic from disk + COM_LoadCacheFile (path, &pic->cache); + + dat = (qpic_t *) pic->cache.data; + if (!dat) { + Sys_Error ("Draw_CachePic: failed to load %s", path); + } + + SwapPic (dat); + + return dat; +} + +void +Draw_TextBox (int x, int y, int width, int lines) +{ + qpic_t *p; + int cx, cy; + int n; + + // draw left side + cx = x; + cy = y; + p = Draw_CachePic ("gfx/box_tl.lmp", true); + Draw_Pic (cx, cy, p); + p = Draw_CachePic ("gfx/box_ml.lmp", true); + for (n = 0; n < lines; n++) { + cy += 8; + Draw_Pic (cx, cy, p); + } + p = Draw_CachePic ("gfx/box_bl.lmp", true); + Draw_Pic (cx, cy + 8, p); + + // draw middle + cx += 8; + while (width > 0) { + cy = y; + p = Draw_CachePic ("gfx/box_tm.lmp", true); + Draw_Pic (cx, cy, p); + p = Draw_CachePic ("gfx/box_mm.lmp", true); + for (n = 0; n < lines; n++) { + cy += 8; + if (n == 1) + p = Draw_CachePic ("gfx/box_mm2.lmp", true); + Draw_Pic (cx, cy, p); + } + p = Draw_CachePic ("gfx/box_bm.lmp", true); + Draw_Pic (cx, cy + 8, p); + width -= 2; + cx += 16; + } + + // draw right side + cy = y; + p = Draw_CachePic ("gfx/box_tr.lmp", true); + Draw_Pic (cx, cy, p); + p = Draw_CachePic ("gfx/box_mr.lmp", true); + for (n = 0; n < lines; n++) { + cy += 8; + Draw_Pic (cx, cy, p); + } + p = Draw_CachePic ("gfx/box_br.lmp", true); + Draw_Pic (cx, cy + 8, p); +} + +void +Draw_Init (void) +{ + draw_chars = W_GetLumpName ("conchars"); + draw_disc = W_GetLumpName ("disc"); + draw_backtile = W_GetLumpName ("backtile"); + + r_rectdesc.width = draw_backtile->width; + r_rectdesc.height = draw_backtile->height; + r_rectdesc.ptexbytes = draw_backtile->data; + r_rectdesc.rowbytes = draw_backtile->width; +} + +/* + Draw_Character + + Draws one 8*8 graphics character with 0 being transparent. + It can be clipped to the top of the screen to allow the console to be + smoothly scrolled off. +*/ +void +Draw_Character (int x, int y, int num) +{ + byte *source; + int drawline; + int row, col; + + num &= 255; + + if (y <= -8) + return; // totally off screen + + if (y > vid.height - 8 || x < 0 || x > vid.width - 8) + return; + if (num < 0 || num > 255) + return; + + row = num >> 4; + col = num & 15; + source = draw_chars + (row << 10) + (col << 3); + + if (y < 0) { // clipped + drawline = 8 + y; + source -= 128 * y; + y = 0; + } else + drawline = 8; + + + switch(r_pixbytes) { + case 1: + { + byte *dest = (byte *) vid.conbuffer + y * vid.conrowbytes + x; + + while (drawline--) { + if (source[0]) + dest[0] = source[0]; + if (source[1]) + dest[1] = source[1]; + if (source[2]) + dest[2] = source[2]; + if (source[3]) + dest[3] = source[3]; + if (source[4]) + dest[4] = source[4]; + if (source[5]) + dest[5] = source[5]; + if (source[6]) + dest[6] = source[6]; + if (source[7]) + dest[7] = source[7]; + source += 128; + dest += vid.conrowbytes; + } + } + break; + case 2: + { + unsigned short *dest = (unsigned short *) vid.conbuffer + y * + (vid.conrowbytes >> 1) + x; + + while (drawline--) { + if (source[0]) + dest[0] = d_8to16table[source[0]]; + if (source[1]) + dest[1] = d_8to16table[source[1]]; + if (source[2]) + dest[2] = d_8to16table[source[2]]; + if (source[3]) + dest[3] = d_8to16table[source[3]]; + if (source[4]) + dest[4] = d_8to16table[source[4]]; + if (source[5]) + dest[5] = d_8to16table[source[5]]; + if (source[6]) + dest[6] = d_8to16table[source[6]]; + if (source[7]) + dest[7] = d_8to16table[source[7]]; + + source += 128; + dest += (vid.conrowbytes >> 1); + } + } + break; + case 4: + { + unsigned int *dest = (unsigned int *) vid.conbuffer + y * + (vid.conrowbytes >> 2) + x; + + while (drawline--) { + if (source[0]) + dest[0] = d_8to24table[source[0]]; + if (source[1]) + dest[1] = d_8to24table[source[1]]; + if (source[2]) + dest[2] = d_8to24table[source[2]]; + if (source[3]) + dest[3] = d_8to24table[source[3]]; + if (source[4]) + dest[4] = d_8to24table[source[4]]; + if (source[5]) + dest[5] = d_8to24table[source[5]]; + if (source[6]) + dest[6] = d_8to24table[source[6]]; + if (source[7]) + dest[7] = d_8to24table[source[7]]; + + source += 128; + dest += (vid.conrowbytes >> 2); + } + } + break; + default: + Sys_Error("Draw_Character: unsupported r_pixbytes %i\n", r_pixbytes); + } +} + +void +Draw_String (int x, int y, const char *str) +{ + while (*str) { + Draw_Character (x, y, *str++); + x += 8; + } +} + +void +Draw_AltString (int x, int y, const char *str) +{ + while (*str) { + Draw_Character (x, y, (*str++) | 0x80); + x += 8; + } +} + +void +Draw_Pixel (int x, int y, byte color) +{ + switch(r_pixbytes) + { + case 1: + ((byte *) vid.conbuffer)[y * vid.conrowbytes + x] = color; + break; + case 2: + ((unsigned short *) vid.conbuffer)[y * (vid.conrowbytes >> 1) + x] = + d_8to16table[color]; + break; + case 4: + ((unsigned int *) vid.conbuffer)[y * (vid.conrowbytes >> 2) + x] = + d_8to24table[color]; + break; + default: + Sys_Error("Draw_Pixel: unsupported r_pixbytes %i\n", r_pixbytes); + } +} + +void +Draw_Crosshair (int swap) +{ + int x, y; + extern cvar_t *crosshair, *cl_crossx, *cl_crossy, *crosshaircolor; + extern vrect_t scr_vrect; + byte c = crosshaircolor->int_val; + + if (crosshair->int_val == 2) { + x = scr_vrect.x + scr_vrect.width / 2 + cl_crossx->int_val; + y = scr_vrect.y + scr_vrect.height / 2 + cl_crossy->int_val; + Draw_Pixel (x - 1, y, c); + Draw_Pixel (x - 3, y, c); + Draw_Pixel (x + 1, y, c); + Draw_Pixel (x + 3, y, c); + Draw_Pixel (x, y - 1, c); + Draw_Pixel (x, y - 3, c); + Draw_Pixel (x, y + 1, c); + Draw_Pixel (x, y + 3, c); + } else if (crosshair->int_val) + Draw_Character (scr_vrect.x + scr_vrect.width / 2 - 4 + + cl_crossx->int_val, + scr_vrect.y + scr_vrect.height / 2 - 4 + + cl_crossy->int_val, '+'); +} + +void +Draw_Pic (int x, int y, qpic_t *pic) +{ + byte *source, tbyte; + int v, u; + + if (x < 0 || (unsigned int) (x + pic->width) > vid.width || y < 0 || + (unsigned int) (y + pic->height) > vid.height) { + Sys_Error ("Draw_Pic: bad coordinates"); + } + + source = pic->data; + + switch(r_pixbytes) { + case 1: + { + byte *dest = (byte *) vid.buffer + y * vid.rowbytes + x; + + if (pic->width & 7) { // general + for (v = 0; v < pic->height; v++) { + for (u = 0; u < pic->width; u++) + if ((tbyte = source[u]) != TRANSPARENT_COLOR) + dest[u] = tbyte; + + dest += vid.rowbytes; + source += pic->width; + } + } else { // unwound + for (v = 0; v < pic->height; v++) { + for (u = 0; u < pic->width; u += 8) { + if ((tbyte = source[u]) != TRANSPARENT_COLOR) + dest[u] = tbyte; + if ((tbyte = source[u + 1]) != TRANSPARENT_COLOR) + dest[u + 1] = tbyte; + if ((tbyte = source[u + 2]) != TRANSPARENT_COLOR) + dest[u + 2] = tbyte; + if ((tbyte = source[u + 3]) != TRANSPARENT_COLOR) + dest[u + 3] = tbyte; + if ((tbyte = source[u + 4]) != TRANSPARENT_COLOR) + dest[u + 4] = tbyte; + if ((tbyte = source[u + 5]) != TRANSPARENT_COLOR) + dest[u + 5] = tbyte; + if ((tbyte = source[u + 6]) != TRANSPARENT_COLOR) + dest[u + 6] = tbyte; + if ((tbyte = source[u + 7]) != TRANSPARENT_COLOR) + dest[u + 7] = tbyte; + } + dest += vid.rowbytes; + source += pic->width; + } + } + } + break; + case 2: + { + unsigned short *dest = (unsigned short *) vid.buffer + y * + (vid.rowbytes >> 1) + x; + + for (v = 0; v < pic->height; v++) { + for (u = 0; u < pic->width; u++) { + tbyte = source[u]; + if (tbyte != TRANSPARENT_COLOR) + dest[u] = d_8to16table[tbyte]; + } + + dest += vid.rowbytes >> 1; + source += pic->width; + } + } + break; + case 4: + { + unsigned int *dest = (unsigned int *) vid.buffer + y * + (vid.rowbytes >> 2) + x; + for (v = 0; v < pic->height; v++) { + for (u = 0; u < pic->width; u++) { + tbyte = source[u]; + if (tbyte != TRANSPARENT_COLOR) + dest[u] = d_8to24table[tbyte]; + } + dest += vid.rowbytes >> 2; + source += pic->width; + } + } + break; + default: + Sys_Error("Draw_Pic: unsupported r_pixbytes %i\n", r_pixbytes); + } +} + +void +Draw_SubPic (int x, int y, qpic_t *pic, int srcx, int srcy, int width, + int height) +{ + byte *source; + int v, u; + + if ((x < 0) || + (x + width > vid.width) || (y < 0) || (y + height > vid.height)) { + Sys_Error ("Draw_SubPic: bad coordinates"); + } + + source = pic->data + srcy * pic->width + srcx; + + switch (r_pixbytes) { + case 1: + { + byte *dest = (byte *) vid.buffer + y * vid.rowbytes + x; + + for (v = 0; v < height; v++) { + memcpy (dest, source, width); + dest += vid.rowbytes; + source += pic->width; + } + } + break; + case 2: + { + unsigned short *dest = (unsigned short *) vid.buffer + y * + (vid.rowbytes >> 1) + x; + for (v = 0; v < height; v++, dest += vid.rowbytes >> 1, + source += pic->width) + for (u = 0; u < width; u++) + dest[u] = d_8to16table[source[u]]; + } + break; + case 4: + { + unsigned int *dest = (unsigned int *) vid.buffer + y * + (vid.rowbytes >> 2) + x; + for (v = 0; v < height; v++, dest += vid.rowbytes >> 2, + source += pic->width) + for (u = 0; u < width; u++) + dest[u] = d_8to24table[source[u]]; + } + break; + default: + Sys_Error("Draw_SubPic: unsupported r_pixbytes %i\n", r_pixbytes); + } +} + +void +Draw_TransPicTranslate (int x, int y, qpic_t *pic, byte * translation) +{ + byte *source, tbyte; + int v, u; + + if (x < 0 || (unsigned int) (x + pic->width) > vid.width || y < 0 || + (unsigned int) (y + pic->height) > vid.height) { + Sys_Error ("Draw_TransPic: bad coordinates"); + } + + source = pic->data; + + switch(r_pixbytes) { + case 1: + { + byte *dest = (byte *) vid.buffer + y * vid.rowbytes + x; + + if (pic->width & 7) { // general + for (v = 0; v < pic->height; v++) { + for (u = 0; u < pic->width; u++) + if ((tbyte = source[u]) != TRANSPARENT_COLOR) + dest[u] = translation[tbyte]; + + dest += vid.rowbytes; + source += pic->width; + } + } else { // unwound + for (v = 0; v < pic->height; v++) { + for (u = 0; u < pic->width; u += 8) { + if ((tbyte = source[u]) != TRANSPARENT_COLOR) + dest[u] = translation[tbyte]; + if ((tbyte = source[u + 1]) != TRANSPARENT_COLOR) + dest[u + 1] = translation[tbyte]; + if ((tbyte = source[u + 2]) != TRANSPARENT_COLOR) + dest[u + 2] = translation[tbyte]; + if ((tbyte = source[u + 3]) != TRANSPARENT_COLOR) + dest[u + 3] = translation[tbyte]; + if ((tbyte = source[u + 4]) != TRANSPARENT_COLOR) + dest[u + 4] = translation[tbyte]; + if ((tbyte = source[u + 5]) != TRANSPARENT_COLOR) + dest[u + 5] = translation[tbyte]; + if ((tbyte = source[u + 6]) != TRANSPARENT_COLOR) + dest[u + 6] = translation[tbyte]; + if ((tbyte = source[u + 7]) != TRANSPARENT_COLOR) + dest[u + 7] = translation[tbyte]; + } + dest += vid.rowbytes; + source += pic->width; + } + } + } + break; + case 2: + { + unsigned short *dest = (unsigned short *) vid.buffer + y * + (vid.rowbytes >> 1) + x; + for (v = 0; v < pic->height; v++) { + for (u = 0; u < pic->width; u++) { + tbyte = source[u]; + if (tbyte != TRANSPARENT_COLOR) + dest[u] = d_8to16table[translation[tbyte]]; + } + dest += vid.rowbytes >> 1; + source += pic->width; + } + } + break; + case 4: + { + unsigned int *dest = (unsigned int *) vid.buffer + y * + (vid.rowbytes >> 2) + x; + for (v = 0; v < pic->height; v++) { + for (u = 0; u < pic->width; u++) { + tbyte = source[u]; + if (tbyte != TRANSPARENT_COLOR) + dest[u] = d_8to24table[translation[tbyte]]; + } + dest += vid.rowbytes >> 1; + source += pic->width; + } + } + break; + default: + Sys_Error("Draw_TransPicTranslate: unsupported r_pixbytes %i\n", + r_pixbytes); + } +} + +void +Draw_ConsoleBackground (int lines) +{ + int x, y, v; + byte *src; + int f, fstep; + qpic_t *conback; + + conback = Draw_CachePic ("gfx/conback.lmp", true); + + // draw the pic + switch(r_pixbytes) { + case 1: + { + byte *dest = vid.conbuffer; + + for (y = 0; y < lines; y++, dest += vid.conrowbytes) { + v = (vid.conheight - lines + y) * 200 / vid.conheight; + src = conback->data + v * 320; + if (vid.conwidth == 320) + memcpy (dest, src, vid.conwidth); + else { + f = 0; + fstep = 320 * 0x10000 / vid.conwidth; + for (x = 0; x < vid.conwidth; x += 4) { + dest[x] = src[f >> 16]; + f += fstep; + dest[x + 1] = src[f >> 16]; + f += fstep; + dest[x + 2] = src[f >> 16]; + f += fstep; + dest[x + 3] = src[f >> 16]; + f += fstep; + } + } + } + } + break; + case 2: + { + unsigned short *dest = (unsigned short *) vid.conbuffer; + + for (y = 0; y < lines; y++, dest += (vid.conrowbytes >> 1)) { + // FIXME: pre-expand to native format? + // FIXME: does the endian switching go away in production? + v = (vid.conheight - lines + y) * 200 / vid.conheight; + src = conback->data + v * 320; + f = 0; + fstep = 320 * 0x10000 / vid.conwidth; + for (x = 0; x < vid.conwidth; x += 4) { + dest[x] = d_8to16table[src[f >> 16]]; + f += fstep; + dest[x + 1] = d_8to16table[src[f >> 16]]; + f += fstep; + dest[x + 2] = d_8to16table[src[f >> 16]]; + f += fstep; + dest[x + 3] = d_8to16table[src[f >> 16]]; + f += fstep; + } + } + } + break; + case 4: + { + unsigned int *dest = (unsigned int *) vid.conbuffer; + for (y = 0; y < lines; y++, dest += (vid.conrowbytes >> 2)) { + v = (vid.conheight - lines + y) * 200 / vid.conheight; + src = conback->data + v * 320; + f = 0; + fstep = 320 * 0x10000 / vid.conwidth; + for (x = 0; x < vid.conwidth; x += 4) { + dest[x ] = d_8to24table[src[f >> 16]];f += fstep; + dest[x + 1] = d_8to24table[src[f >> 16]];f += fstep; + dest[x + 2] = d_8to24table[src[f >> 16]];f += fstep; + dest[x + 3] = d_8to24table[src[f >> 16]];f += fstep; + } + } + } + break; + + default: + Sys_Error("Draw_TransPicTranslate: unsupported r_pixbytes %i\n", + r_pixbytes); + } + +// if (!cls.download) + Draw_AltString (vid.conwidth - strlen (cl_verstring->string) * 8 - 11, + lines - 14, cl_verstring->string); +} + +void +R_DrawRect (vrect_t *prect, int rowbytes, byte * psrc, int transparent) +{ + switch(r_pixbytes) { + case 1: + { + byte t; + int i, j, srcdelta, destdelta; + byte *pdest; + + pdest = (byte *) vid.buffer + prect->y * vid.rowbytes + prect->x; + + srcdelta = rowbytes - prect->width; + destdelta = vid.rowbytes - prect->width; + + if (transparent) + { + for (i = 0; i < prect->height; i++) + { + for (j = 0; j < prect->width; j++) + { + t = *psrc; + if (t != TRANSPARENT_COLOR) + *pdest = t; + psrc++; + pdest++; + } + + psrc += srcdelta; + pdest += destdelta; + } + } + else + { + for (i = 0; i < prect->height; i++) + { + memcpy (pdest, psrc, prect->width); + psrc += rowbytes; + pdest += vid.rowbytes; + } + } + } + break; + case 2: + { + int i, j, srcdelta, destdelta; + unsigned short *pdest; + + pdest = (unsigned short *) vid.buffer + + (prect->y * (vid.rowbytes >> 1)) + prect->x; + + srcdelta = rowbytes - prect->width; + destdelta = (vid.rowbytes >> 1) - prect->width; + + if (transparent) { + for (i = 0; i < prect->height; i++) + { + j = prect->width; + while(j >= 8) + { + j -= 8; + if (psrc[0] != TRANSPARENT_COLOR) + pdest[0] = d_8to16table[psrc[0]]; + if (psrc[1] != TRANSPARENT_COLOR) + pdest[1] = d_8to16table[psrc[1]]; + if (psrc[2] != TRANSPARENT_COLOR) + pdest[2] = d_8to16table[psrc[2]]; + if (psrc[3] != TRANSPARENT_COLOR) + pdest[3] = d_8to16table[psrc[3]]; + if (psrc[4] != TRANSPARENT_COLOR) + pdest[4] = d_8to16table[psrc[4]]; + if (psrc[5] != TRANSPARENT_COLOR) + pdest[5] = d_8to16table[psrc[5]]; + if (psrc[6] != TRANSPARENT_COLOR) + pdest[6] = d_8to16table[psrc[6]]; + if (psrc[7] != TRANSPARENT_COLOR) + pdest[7] = d_8to16table[psrc[7]]; + psrc += 8; + pdest += 8; + } + if (j & 4) + { + if (psrc[0] != TRANSPARENT_COLOR) + pdest[0] = d_8to16table[psrc[0]]; + if (psrc[1] != TRANSPARENT_COLOR) + pdest[1] = d_8to16table[psrc[1]]; + if (psrc[2] != TRANSPARENT_COLOR) + pdest[2] = d_8to16table[psrc[2]]; + if (psrc[3] != TRANSPARENT_COLOR) + pdest[3] = d_8to16table[psrc[3]]; + psrc += 4; + pdest += 4; + } + if (j & 2) + { + if (psrc[0] != TRANSPARENT_COLOR) + pdest[0] = d_8to16table[psrc[0]]; + if (psrc[1] != TRANSPARENT_COLOR) + pdest[1] = d_8to16table[psrc[1]]; + psrc += 2; + pdest += 2; + } + if (j & 1) + { + if (psrc[0] != TRANSPARENT_COLOR) + pdest[0] = d_8to16table[psrc[0]]; + psrc++; + pdest++; + } + + psrc += srcdelta; + pdest += destdelta; + } + } else { + for (i = 0; i < prect->height; i++, psrc += srcdelta, + pdest += destdelta) + { + j = prect->width; + while(j >= 8) + { + j -= 8; + pdest[0] = d_8to16table[psrc[0]]; + pdest[1] = d_8to16table[psrc[1]]; + pdest[2] = d_8to16table[psrc[2]]; + pdest[3] = d_8to16table[psrc[3]]; + pdest[4] = d_8to16table[psrc[4]]; + pdest[5] = d_8to16table[psrc[5]]; + pdest[6] = d_8to16table[psrc[6]]; + pdest[7] = d_8to16table[psrc[7]]; + psrc += 8; + pdest += 8; + } + if (j & 4) + { + pdest[0] = d_8to16table[psrc[0]]; + pdest[1] = d_8to16table[psrc[1]]; + pdest[2] = d_8to16table[psrc[2]]; + pdest[3] = d_8to16table[psrc[3]]; + psrc += 4; + pdest += 4; + } + if (j & 2) + { + pdest[0] = d_8to16table[psrc[0]]; + pdest[1] = d_8to16table[psrc[1]]; + psrc += 2; + pdest += 2; + } + if (j & 1) + { + pdest[0] = d_8to16table[psrc[0]]; + psrc++; + pdest++; + } + } + } + } + break; + case 4: + { + int i, j, srcdelta, destdelta; + int *pdest; + + pdest = (int *) vid.buffer + prect->y * (vid.rowbytes >> 2) + prect->x; + + srcdelta = rowbytes - prect->width; + destdelta = (vid.rowbytes >> 2) - prect->width; + + if (transparent) + { + for (i = 0; i < prect->height; i++) + { + j = prect->width; + while(j >= 8) + { + j -= 8; + if (psrc[0] != TRANSPARENT_COLOR) + pdest[0] = d_8to24table[psrc[0]]; + if (psrc[1] != TRANSPARENT_COLOR) + pdest[1] = d_8to24table[psrc[1]]; + if (psrc[2] != TRANSPARENT_COLOR) + pdest[2] = d_8to24table[psrc[2]]; + if (psrc[3] != TRANSPARENT_COLOR) + pdest[3] = d_8to24table[psrc[3]]; + if (psrc[4] != TRANSPARENT_COLOR) + pdest[4] = d_8to24table[psrc[4]]; + if (psrc[5] != TRANSPARENT_COLOR) + pdest[5] = d_8to24table[psrc[5]]; + if (psrc[6] != TRANSPARENT_COLOR) + pdest[6] = d_8to24table[psrc[6]]; + if (psrc[7] != TRANSPARENT_COLOR) + pdest[7] = d_8to24table[psrc[7]]; + psrc += 8; + pdest += 8; + } + if (j & 4) + { + if (psrc[0] != TRANSPARENT_COLOR) + pdest[0] = d_8to24table[psrc[0]]; + if (psrc[1] != TRANSPARENT_COLOR) + pdest[1] = d_8to24table[psrc[1]]; + if (psrc[2] != TRANSPARENT_COLOR) + pdest[2] = d_8to24table[psrc[2]]; + if (psrc[3] != TRANSPARENT_COLOR) + pdest[3] = d_8to24table[psrc[3]]; + psrc += 4; + pdest += 4; + } + if (j & 2) + { + if (psrc[0] != TRANSPARENT_COLOR) + pdest[0] = d_8to24table[psrc[0]]; + if (psrc[1] != TRANSPARENT_COLOR) + pdest[1] = d_8to24table[psrc[1]]; + psrc += 2; + pdest += 2; + } + if (j & 1) + { + if (psrc[0] != TRANSPARENT_COLOR) + pdest[0] = d_8to24table[psrc[0]]; + psrc++; + pdest++; + } + + psrc += srcdelta; + pdest += destdelta; + } + } + else + { + for (i = 0; i < prect->height; i++, psrc += srcdelta, + pdest += destdelta) + { + j = prect->width; + while(j >= 8) + { + j -= 8; + pdest[0] = d_8to24table[psrc[0]]; + pdest[1] = d_8to24table[psrc[1]]; + pdest[2] = d_8to24table[psrc[2]]; + pdest[3] = d_8to24table[psrc[3]]; + pdest[4] = d_8to24table[psrc[4]]; + pdest[5] = d_8to24table[psrc[5]]; + pdest[6] = d_8to24table[psrc[6]]; + pdest[7] = d_8to24table[psrc[7]]; + psrc += 8; + pdest += 8; + } + if (j & 4) + { + pdest[0] = d_8to24table[psrc[0]]; + pdest[1] = d_8to24table[psrc[1]]; + pdest[2] = d_8to24table[psrc[2]]; + pdest[3] = d_8to24table[psrc[3]]; + psrc += 4; + pdest += 4; + } + if (j & 2) + { + pdest[0] = d_8to24table[psrc[0]]; + pdest[1] = d_8to24table[psrc[1]]; + psrc += 2; + pdest += 2; + } + if (j & 1) + { + pdest[0] = d_8to24table[psrc[0]]; + psrc++; + pdest++; + } + } + } + } + break; + default: + Sys_Error("R_DrawRect: unsupported r_pixbytes %i\n", r_pixbytes); + } +} + +/* + Draw_TileClear + + This repeats a 64*64 tile graphic to fill the screen around a sized down + refresh window. +*/ +void +Draw_TileClear (int x, int y, int w, int h) +{ + int width, height, tileoffsetx, tileoffsety; + byte *psrc; + vrect_t vr; + + r_rectdesc.rect.x = x; + r_rectdesc.rect.y = y; + r_rectdesc.rect.width = w; + r_rectdesc.rect.height = h; + + vr.y = r_rectdesc.rect.y; + height = r_rectdesc.rect.height; + + tileoffsety = vr.y % r_rectdesc.height; + + while (height > 0) { + vr.x = r_rectdesc.rect.x; + width = r_rectdesc.rect.width; + + if (tileoffsety != 0) + vr.height = r_rectdesc.height - tileoffsety; + else + vr.height = r_rectdesc.height; + + if (vr.height > height) + vr.height = height; + + tileoffsetx = vr.x % r_rectdesc.width; + + while (width > 0) { + if (tileoffsetx != 0) + vr.width = r_rectdesc.width - tileoffsetx; + else + vr.width = r_rectdesc.width; + + if (vr.width > width) + vr.width = width; + + psrc = r_rectdesc.ptexbytes + + (tileoffsety * r_rectdesc.rowbytes) + tileoffsetx; + + R_DrawRect (&vr, r_rectdesc.rowbytes, psrc, 0); + + vr.x += vr.width; + width -= vr.width; + tileoffsetx = 0; // only the left tile can be + // left-clipped + } + + vr.y += vr.height; + height -= vr.height; + tileoffsety = 0; // only the top tile can be + // top-clipped + } +} + +/* + Draw_Fill + + Fills a box of pixels with a single color +*/ +void +Draw_Fill (int x, int y, int w, int h, int c) +{ + int u, v; + + if (x < 0 || x + w > vid.width || y < 0 || y + h > vid.height) { + Con_Printf ("Bad Draw_Fill(%d, %d, %d, %d, %c)\n", x, y, w, h, c); + return; + } + + switch (r_pixbytes) { + case 1: + { + byte *dest = (byte *) vid.buffer + y * vid.rowbytes + x; + for (v = 0; v < h; v++, dest += vid.rowbytes) + for (u = 0; u < w; u++) + dest[u] = c; + } + break; + case 2: + { + unsigned short *dest = (unsigned short *) vid.buffer + y * + (vid.rowbytes >> 1) + x; + c = d_8to16table[c]; + for (v = 0; v < h; v++, dest += (vid.rowbytes >> 1)) + for (u = 0; u < w; u++) + dest[u] = c; + } + break; + case 4: + { + unsigned int *dest = (unsigned int *) vid.buffer + y * + (vid.rowbytes >> 2) + x; + c = d_8to24table[c]; + for (v = 0; v < h; v++, dest += (vid.rowbytes >> 2)) + for (u = 0; u < w; u++) + dest[u] = c; + } + break; + default: + Sys_Error("Draw_Fill: unsupported r_pixbytes %i\n", r_pixbytes); + } +} + +//============================================================================= + +void +Draw_FadeScreen (void) +{ + int x, y; + + VID_UnlockBuffer (); + S_ExtraUpdate (); + VID_LockBuffer (); + + switch(r_pixbytes) { + case 1: + { + for (y = 0; y < vid.height; y++) { + int t; + byte *pbuf = (byte *) ((byte *) vid.buffer + vid.rowbytes * y); + t = (y & 1) << 1; + + for (x = 0; x < vid.width; x++) { + if ((x & 3) != t) + pbuf[x] = 0; + } + } + } + break; + case 2: + { + for (y = 0; y < vid.height; y++) { + unsigned short *pbuf = (unsigned short *) + ((byte *) vid.buffer + vid.rowbytes * y); + pbuf = (unsigned short *) vid.buffer + (vid.rowbytes >> 1) * y; + for (x = 0; x < vid.width; x++) + pbuf[x] = (pbuf[x] >>= 1) & 0x7BEF; + } + } + break; + case 4: + { + for (y = 0; y < vid.height; y++) { + unsigned int *pbuf = (unsigned int *) + ((byte *) vid.buffer + vid.rowbytes * y); + for (x = 0; x < vid.width; x++) + pbuf[x] = (pbuf[x] >>= 1) & 0x7F7F7F7F; + } + } + break; + default: + Sys_Error("Draw_FadeScreen: unsupported r_pixbytes %i\n", r_pixbytes); + } + + VID_UnlockBuffer (); + S_ExtraUpdate (); + VID_LockBuffer (); +} + +//============================================================================= + +/* + Draw_BeginDisc + + Draws the little blue disc in the corner of the screen. + Call before beginning any disc IO. +*/ +void +Draw_BeginDisc (void) +{ + D_BeginDirectRect (vid.width - 24, 0, draw_disc->data, 24, 24); +} + +/* + Draw_EndDisc + + Erases the disc icon. + Call after completing any disc IO +*/ +void +Draw_EndDisc (void) +{ + D_EndDirectRect (vid.width - 24, 0, 24, 24); +} diff --git a/libs/video/renderer/sw32/screen.c b/libs/video/renderer/sw32/screen.c new file mode 100644 index 000000000..86a1f8b94 --- /dev/null +++ b/libs/video/renderer/sw32/screen.c @@ -0,0 +1,1116 @@ +/* + screen.c + + master for refresh, status bar, console, chat, notify, etc + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include + +#include "QF/cmd.h" +#include "QF/console.h" +#include "QF/cvar.h" +#include "QF/draw.h" +#include "QF/keys.h" +//#include "QF/menu.h" +#include "QF/pcx.h" +#include "QF/render.h" +#include "QF/screen.h" +#include "QF/sys.h" +#include "QF/texture.h" +#include "QF/vfs.h" +#include "QF/vid.h" + +//#include "cl_parse.h" DESPAIR +//#include "client.h" +#include "compat.h" +#include "d_iface.h" +#include "r_cvar.h" +#include "r_local.h" +#include "sbar.h" +//#include "skin.h" +#include "view.h" + +/* + background clear + rendering + turtle/net/ram icons + sbar + centerprint / slow centerprint + notify lines + intermission / finale overlay + loading plaque + console + menu + + required background clears + required update regions + + syncronous draw mode or async + One off screen buffer, with updates either copied or xblited + Need to double buffer? + + async draw will require the refresh area to be cleared, because it will be + xblited, but sync draw can just ignore it. + + sync + draw + + CenterPrint () + SlowPrint () + Screen_Update (); + Con_Printf (); + + net + turn off messages option + + the refresh is allways rendered, unless the console is full screen + + + console is: + notify lines + half + full +*/ + +// only the refresh window will be updated unless these variables are flagged +int scr_copytop; +int scr_copyeverything; + +float scr_con_current; +float scr_conlines; // lines of console to display + +int oldscreensize, oldfov; +int oldsbar; +cvar_t *scr_viewsize; +cvar_t *scr_fov; // 10 - 170 +cvar_t *scr_conspeed; +cvar_t *scr_consize; +cvar_t *scr_centertime; +cvar_t *scr_showram; +cvar_t *scr_showturtle; +cvar_t *scr_showpause; +cvar_t *scr_printspeed; +cvar_t *crosshair; +cvar_t *crosshaircolor; +cvar_t *cl_crossx; +cvar_t *cl_crossy; + +qboolean scr_initialized; // ready to draw + +qpic_t *scr_ram; +qpic_t *scr_net; +qpic_t *scr_turtle; + +int scr_fullupdate; + +int clearconsole; +int clearnotify; + +extern int sb_lines; + +viddef_t vid; // global video state + +vrect_t *pconupdate; +vrect_t scr_vrect; + +qboolean scr_disabled_for_loading; + +qboolean scr_skipupdate; + +qboolean block_drawing; + +void SCR_ScreenShot_f (void); +void SCR_RSShot_f (void); + +/* + CENTER PRINTING +*/ + +char scr_centerstring[1024]; +float scr_centertime_start; // for slow victory printing +float scr_centertime_off; +int scr_center_lines; +int scr_erase_lines; +int scr_erase_center; + + +/* + SCR_CenterPrint + + Called for important messages that should stay in the center of the screen + for a few moments +*/ +void +SCR_CenterPrint (const char *str) +{ + strncpy (scr_centerstring, str, sizeof (scr_centerstring) - 1); + scr_centertime_off = scr_centertime->value; + scr_centertime_start = r_realtime; + + // count the number of lines for centering + scr_center_lines = 1; + while (*str) { + if (*str == '\n') + scr_center_lines++; + str++; + } +} + +void +SCR_DrawCenterString (void) +{ + char *start; + int l; + int j; + int x, y; + int remaining; + + // the finale prints the characters one at a time + if (r_force_fullscreen /*FIXME*/) + remaining = scr_printspeed->value * (r_realtime - + scr_centertime_start); + else + remaining = 9999; + + scr_erase_center = 0; + start = scr_centerstring; + + if (scr_center_lines <= 4) + y = vid.height * 0.35; + else + y = 48; + + do { + // scan the width of the line + for (l = 0; l < 40; l++) + if (start[l] == '\n' || !start[l]) + break; + x = (vid.width - l * 8) / 2; + for (j = 0; j < l; j++, x += 8) { + Draw_Character (x, y, start[j]); + if (!remaining--) + return; + } + + y += 8; + + while (*start && *start != '\n') + start++; + + if (!*start) + break; + start++; // skip the \n + } while (1); +} + +void +SCR_CheckDrawCenterString (int swap) +{ + scr_copytop = 1; + if (scr_center_lines > scr_erase_lines) + scr_erase_lines = scr_center_lines; + + scr_centertime_off -= r_frametime; + + if (scr_centertime_off <= 0 && !r_force_fullscreen /*FIXME*/) + return; + if (key_dest != key_game) + return; + + SCR_DrawCenterString (); +} + +//============================================================================= + +float +CalcFov (float fov_x, float width, float height) +{ + float a; + float x; + + if (fov_x < 1 || fov_x > 179) + Sys_Error ("Bad fov: %f", fov_x); + + x = width / tan (fov_x / 360 * M_PI); + + a = (x == 0) ? 90 : atan (height / x); // 0 shouldn't happen + + a = a * 360 / M_PI; + + return a; +} + +/* + SCR_CalcRefdef + + Must be called whenever vid changes + Internal use only +*/ +static void +SCR_CalcRefdef (void) +{ + vrect_t vrect; + float size; + int h; + qboolean full = false; + + scr_fullupdate = 0; // force a background redraw + vid.recalc_refdef = 0; + + // force the status bar to redraw + Sbar_Changed (); + +//======================================== + + // bound viewsize + Cvar_SetValue (scr_viewsize, bound (30, scr_viewsize->int_val, 120)); + + // bound field of view + Cvar_SetValue (scr_fov, bound (10, scr_fov->value, 170)); + + if (scr_viewsize->int_val >= 120) + sb_lines = 0; // no status bar at all + else if (scr_viewsize->int_val >= 110) + sb_lines = 24; // no inventory + else + sb_lines = 24 + 16 + 8; + + if (scr_viewsize->int_val >= 100) { + full = true; + size = 100.0; + } else { + size = scr_viewsize->int_val; + } + // intermission is always full screen + if (r_force_fullscreen /*FIXME*/) { + full = true; + size = 100.0; + sb_lines = 0; + } + size /= 100.0; + + h = vid.height - r_lineadj; + + r_refdef.vrect.width = vid.width * size + 0.5; + if (r_refdef.vrect.width < 96) { + size = 96.0 / r_refdef.vrect.width; + r_refdef.vrect.width = 96; // min for icons + } + + r_refdef.vrect.height = vid.height * size + 0.5; + if (r_refdef.vrect.height > h) + r_refdef.vrect.height = h; + r_refdef.vrect.x = (vid.width - r_refdef.vrect.width) / 2; + if (full) + r_refdef.vrect.y = 0; + else + r_refdef.vrect.y = (h - r_refdef.vrect.height) / 2; + + r_refdef.fov_x = scr_fov->int_val; + r_refdef.fov_y = + CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height); + + scr_vrect = r_refdef.vrect; + + // these calculations mirror those in R_Init() for r_refdef, but take no + // account of water warping + vrect.x = 0; + vrect.y = 0; + vrect.width = vid.width; + vrect.height = vid.height; + + R_SetVrect (&vrect, &scr_vrect, sb_lines); + + // guard against going from one mode to another that's less than half the + // vertical resolution + if (scr_con_current > vid.height) + scr_con_current = vid.height; + + // notify the refresh of the change + R_ViewChanged (&vrect, sb_lines, vid.aspect); +} + +extern float v_blend[4]; + +void +SCR_ApplyBlend (void) +{ + int r, b, g, i; + byte *basepal, *newpal; + byte pal[768]; + +/* DESPAIR + qboolean force, new; + + force = V_CheckGamma (); + if (!new && !force && r_pixbytes == 1) + return; +*/ + + switch(r_pixbytes) { + case 1: + { + basepal = vid_basepal; + newpal = pal; + + for (i = 0; i < 256; i++) { + r = basepal[0]; + g = basepal[1]; + b = basepal[2]; + basepal += 3; + + r += (int) (v_blend[3] * (v_blend[0] * 256 - r)); + g += (int) (v_blend[3] * (v_blend[1] * 256 - g)); + b += (int) (v_blend[3] * (v_blend[2] * 256 -g)); + + newpal[0] = gammatable[r]; + newpal[1] = gammatable[g]; + newpal[2] = gammatable[b]; + newpal += 3; + } + VID_ShiftPalette (pal); + } + break; + case 2: + { + int g1, g2, x, y; + unsigned short rramp[32], gramp[64], bramp[32], *temp; + for (i = 0; i < 32; i++) { + r = i << 3; + g1 = i << 3; + g2 = g1 + 4; + b = i << 3; + + r += (int) (v_blend[3] * (v_blend[0] * 256 - r)); + g1 += (int) (v_blend[3] * (v_blend[1] - g1)); + g2 += (int) (v_blend[3] * (v_blend[1] - g2)); + b += (int) (v_blend[3] * (v_blend[2] - b)); + + rramp[i] = (gammatable[r] << 8) & 0xF800; + gramp[i*2+0] = (gammatable[g1] << 3) & 0x07E0; + gramp[i*2+1] = (gammatable[g2] << 3) & 0x07E0; + bramp[i] = (gammatable[b] >> 3) & 0x001F; + } + temp = vid.buffer; + for (y = 0;y < vid.height;y++, temp += (vid.rowbytes >> 1)) + for (x = 0;x < vid.width;x++) + temp[x] = rramp[(temp[x] & 0xF800) >> 11] + + gramp[(temp[x] & 0x07E0) >> 5] + bramp[temp[x] & 0x001F]; + } + break; + case 4: + { + int x, y; + byte ramp[256][4], *temp; + for (i = 0; i < 256; i++) { + r = i; + g = i; + b = i; + + r += (int) (v_blend[3] * (v_blend[0] * 256 - r)); + g += (int) (v_blend[3] * (v_blend[1] * 256 - g)); + b += (int) (v_blend[3] * (v_blend[2] * 256 - b)); + + ramp[i][0] = gammatable[r]; + ramp[i][1] = gammatable[g]; + ramp[i][2] = gammatable[b]; + ramp[i][3] = 0; + } + temp = vid.buffer; + for (y = 0;y < vid.height;y++, temp += vid.rowbytes) + { + for (x = 0;x < vid.width;x++) + { + temp[x*4+0] = ramp[temp[x*4+0]][0]; + temp[x*4+1] = ramp[temp[x*4+1]][1]; + temp[x*4+2] = ramp[temp[x*4+2]][2]; + temp[x*4+3] = 0; + } + } + } + break; + default: + Sys_Error("V_UpdatePalette: unsupported r_pixbytes %i\n", r_pixbytes); + } +} + +/* + SCR_SizeUp_f + + Keybinding command +*/ +void +SCR_SizeUp_f (void) +{ + if (scr_viewsize->int_val < 120) { + Cvar_SetValue (scr_viewsize, scr_viewsize->int_val + 10); + vid.recalc_refdef = 1; + } +} + +/* + SCR_SizeDown_f + + Keybinding command +*/ +void +SCR_SizeDown_f (void) +{ + Cvar_SetValue (scr_viewsize, scr_viewsize->int_val - 10); + vid.recalc_refdef = 1; +} + +//============================================================================ + +void +SCR_Init (void) +{ + // register our commands + Cmd_AddCommand ("screenshot", SCR_ScreenShot_f, "Take a screenshot and " + "write it as qfxxx.tga in the current directory"); + Cmd_AddCommand ("snap", SCR_RSShot_f, "Take a screenshot and upload it " + "to the server"); // DESPAIR + Cmd_AddCommand ("sizeup", SCR_SizeUp_f, "Increase the size of the screen"); + Cmd_AddCommand ("sizedown", SCR_SizeDown_f, "Decrease the size of the " + "screen"); + + scr_ram = Draw_PicFromWad ("ram"); + scr_net = Draw_PicFromWad ("net"); + scr_turtle = Draw_PicFromWad ("turtle"); + + scr_initialized = true; +} + +void +SCR_DrawRam (int swap) +{ + if (!scr_showram->int_val) + return; + + if (!r_cache_thrash) + return; + + Draw_Pic (scr_vrect.x + 32, scr_vrect.y, scr_ram); +} + +void +SCR_DrawTurtle (int swap) +{ + static int count; + + if (!scr_showturtle->int_val) + return; + + if (r_frametime < 0.1) { + count = 0; + return; + } + + count++; + if (count < 3) + return; + + Draw_Pic (scr_vrect.x, scr_vrect.y, scr_turtle); +} + +/* DESPAIR +void +SCR_DrawNet (void) +{ + if (cls.netchan.outgoing_sequence - cls.netchan.incoming_acknowledged < + UPDATE_BACKUP - 1) + return; + if (cls.demoplayback) + return; + + Draw_Pic (scr_vrect.x + 64, scr_vrect.y, scr_net); +} +*/ + +extern cvar_t *show_fps; +extern cvar_t *show_time; + +void +SCR_DrawFPS (int swap) +{ + static double lastframetime; + double t; + extern int fps_count; + static int lastfps; + int i, x, y; + char st[80]; + + if (!show_fps->int_val) + return; + + t = Sys_DoubleTime (); + if ((t - lastframetime) >= 1.0) { + lastfps = fps_count; + fps_count = 0; + lastframetime = t; + } + snprintf (st, sizeof (st), "%3d FPS", lastfps); + if (show_time->int_val <= 0) { + i = 8; + } else if (show_time->int_val == 1) { + i = 56; + } else { + i = 80; + } + /* Misty: New trick! (for me) the ? makes this work like a if then else - + IE: if cl_hudswap->int_val is not null, do first case, else (else is a + : here) do second case. Deek taught me this trick */ + x = swap ? vid.width - ((strlen (st) * 8) + i) : i; + y = vid.height - (sb_lines + 8); + Draw_String (x, y, st); +} + +/* + SCR_DrawTime + + Draw a clock on the screen + Written by Misty, rewritten by Deek +*/ +void +SCR_DrawTime (int swap) +{ + int x, y; + char st[80]; + + time_t utc = 0; + struct tm *local = NULL; + char *timefmt = NULL; + + // any cvar that can take multiple settings must be able to handle abuse. + if (show_time->int_val <= 0) + return; + + // Get local time + utc = time (NULL); + local = localtime (&utc); + + if (show_time->int_val == 1) { // Use international format + timefmt = "%k:%M"; + } else if (show_time->int_val >= 2) { // US AM/PM display + timefmt = "%l:%M %P"; + } + + // Print it next to the fps meter + strftime (st, sizeof (st), timefmt, local); + x = swap ? (vid.width - ((strlen (st) * 8) + 8)) : 8; + y = vid.height - (sb_lines + 8); + Draw_String (x, y, st); +} + +void +SCR_DrawPause (int swap) +{ + qpic_t *pic; + + if (!scr_showpause->int_val) // turn off for screenshots + return; + + if (!r_paused) + return; + + pic = Draw_CachePic ("gfx/pause.lmp", true); + Draw_Pic ((vid.width - pic->width) / 2, + (vid.height - 48 - pic->height) / 2, pic); +} + +//============================================================================= + +void +SCR_SetUpToDrawConsole (void) +{ + Con_CheckResize (); + + // decide on the height of the console + if (!r_active) { + scr_conlines = vid.height; // full screen + scr_con_current = scr_conlines; + } else if (key_dest == key_console) + scr_conlines = vid.height * bound (0.2, scr_consize->value, 1); + else + scr_conlines = 0; // none visible + + if (scr_conlines < scr_con_current) { + scr_con_current -= scr_conspeed->value * r_frametime; + if (scr_conlines > scr_con_current) + scr_con_current = scr_conlines; + + } else if (scr_conlines > scr_con_current) { + scr_con_current += scr_conspeed->value * r_frametime; + if (scr_conlines < scr_con_current) + scr_con_current = scr_conlines; + } + + if (clearconsole++ < vid.numpages) { + Sbar_Changed (); + } else if (clearnotify++ < vid.numpages) { + } else + con_notifylines = 0; +} + +void +SCR_DrawConsole (int swap) +{ + if (scr_con_current) { + scr_copyeverything = 1; + Con_DrawConsole (scr_con_current); + clearconsole = 0; + } else { + if (key_dest == key_game || key_dest == key_message) + Con_DrawNotify (); // only draw notify in game + } +} + +/* + SCREEN SHOTS +*/ + +void +SCR_ScreenShot_f (void) +{ + char pcxname[MAX_OSPATH]; + pcx_t *pcx; + int pcx_len; + + // find a file name to save it to + if (!COM_NextFilename (pcxname, "qf", ".pcx")) { + Con_Printf ("SCR_ScreenShot_f: Couldn't create a PCX"); + return; + } + + // enable direct drawing of console to back buffer + D_EnableBackBufferAccess (); + + // save the pcx file + switch(r_pixbytes) { + case 1: + pcx = EncodePCX (vid.buffer, vid.width, vid.height, vid.rowbytes, + vid_basepal, false, &pcx_len); + break; + case 2: + Con_Printf("SCR_ScreenShot_f: FIXME - add 16bit support\n"); + break; + case 4: + Con_Printf("SCR_ScreenShot_f: FIXME - add 32bit support\n"); + break; + default: + Sys_Error("SCR_ScreenShot_f: unsupported r_pixbytes %i\n", r_pixbytes); + } + + // for adapters that can't stay mapped in for linear writes all the time + D_DisableBackBufferAccess (); + + Con_Printf ("Wrote %s\n", pcxname); +} + +/* + Find closest color in the palette for named color +*/ +int +MipColor (int r, int g, int b) +{ + int i; + float dist; + int best = 0; + float bestdist; + int r1, g1, b1; + static int lr = -1, lg = -1, lb = -1; + static int lastbest; + + if (r == lr && g == lg && b == lb) + return lastbest; + + bestdist = 256 * 256 * 3; + + for (i = 0; i < 256; i++) { + r1 = vid_basepal[i * 3] - r; + g1 = vid_basepal[i * 3 + 1] - g; + b1 = vid_basepal[i * 3 + 2] - b; + dist = r1 * r1 + g1 * g1 + b1 * b1; + if (dist < bestdist) { + bestdist = dist; + best = i; + } + } + lr = r; + lg = g; + lb = b; + lastbest = best; + return best; +} + +// in draw.c +extern byte *draw_chars; // 8*8 graphic characters + +void +SCR_DrawCharToSnap (int num, byte * dest, int width) +{ + int row, col; + byte *source; + int drawline; + int x; + + row = num >> 4; + col = num & 15; + source = draw_chars + (row << 10) + (col << 3); + + drawline = 8; + + while (drawline--) { + for (x = 0; x < 8; x++) + if (source[x]) + dest[x] = source[x]; + else + dest[x] = 98; + source += 128; + dest += width; + } + +} + +void +SCR_DrawStringToSnap (const char *s, tex_t *tex, int x, int y) +{ + byte *buf = tex->data; + byte *dest; + const unsigned char *p; + int width = tex->width; + + dest = buf + ((y * width) + x); + + p = (const unsigned char *) s; + while (*p) { + SCR_DrawCharToSnap (*p++, dest, width); + dest += 8; + } +} + +/* +void +SCR_RSShot_f (void) +{ + int x, y; + unsigned char *dest; + char pcxname[80]; + unsigned char *newbuf; + int w, h; + int dx, dy, dex, dey, nx; + int r, b, g; + int count; + float fracw, frach; + char st[80]; + time_t now; + + if (CL_IsUploading ()) + return; // already one pending + + if (cls.state < ca_onserver) + return; // gotta be connected + + Con_Printf ("Remote screen shot requested.\n"); + + snprintf (pcxname, sizeof (pcxname), "rss.pcx"); + + // save the pcx file + D_EnableBackBufferAccess (); // enable direct drawing of console + // to back buffer + w = (vid.width < RSSHOT_WIDTH) ? vid.width : RSSHOT_WIDTH; + h = (vid.height < RSSHOT_HEIGHT) ? vid.height : RSSHOT_HEIGHT; + + fracw = (float) vid.width / (float) w; + frach = (float) vid.height / (float) h; + + newbuf = calloc (1, w * h); + + for (y = 0; y < h; y++) { + dest = newbuf + (w * y); + + for (x = 0; x < w; x++) { + r = g = b = 0; + + dx = x * fracw; + dex = (x + 1) * fracw; + if (dex == dx) + dex++; // at least one + dy = y * frach; + dey = (y + 1) * frach; + if (dey == dy) + dey++; // at least one + + count = 0; + switch(r_pixbytes) + { + case 1: + for (; dy < dey; dy++) { + byte *src = (byte *) vid.buffer + (vid.rowbytes * dy) + dx; + for (nx = dx; nx < dex; nx++) { + r += vid_basepal[*src * 3]; + g += vid_basepal[*src * 3 + 1]; + b += vid_basepal[*src * 3 + 2]; + src++; + count++; + } + } + break; + case 2: + for (;dy < dey;dy++) { + unsigned short *src = (unsigned short *) vid.buffer + + (vid.rowbytes * dy) + dx; + for (nx = dx; nx < dex; nx++) { + r += ((*src & 0xF800) >> 11) << (8 - 5); + g += ((*src & 0x07E0) >> 5) << (8 - 6); + b += ((*src & 0x001F) >> 0) << (8 - 5); + src++; + count++; + } + } + break; + case 4: + for (;dy < dey;dy++) { + unsigned int *src = (unsigned int *) vid.buffer + + (vid.rowbytes * dy) + dx; + for (nx = dx; nx < dex; nx++) { + r += ((byte *)src)[0]; + g += ((byte *)src)[1]; + b += ((byte *)src)[2]; + src++; + count++; + } + } + break; + default: + Sys_Error("SCR_RSShot_f: unsupported r_pixbytes %i\n", + r_pixbytes); + } + r /= count; + g /= count; + b /= count; + *dest++ = MipColor (r, g, b); + } + } + + time (&now); + strcpy (st, ctime (&now)); + st[strlen (st) - 1] = 0; + SCR_DrawStringToSnap (st, newbuf, w - strlen (st) * 8, 0, w); + + strncpy (st, cls.servername, sizeof (st)); + st[sizeof (st) - 1] = 0; + SCR_DrawStringToSnap (st, newbuf, w - strlen (st) * 8, 10, w); + + strncpy (st, name->string, sizeof (st)); + st[sizeof (st) - 1] = 0; + SCR_DrawStringToSnap (st, newbuf, w - strlen (st) * 8, 20, w); + + WritePCXfile (pcxname, newbuf, w, h, w, vid_basepal, true, false); + + free (newbuf); + + D_DisableBackBufferAccess (); // for adapters that can't stay mapped + // in for linear writes all the time + Con_Printf ("Wrote %s\n", pcxname); + Con_Printf ("Sending shot to server...\n"); +} +*/ + +//============================================================================= + +char *scr_notifystring; + +void +SCR_DrawNotifyString (void) +{ + char *start; + int l; + int j; + int x, y; + + start = scr_notifystring; + + y = vid.height * 0.35; + + do { + // scan the width of the line + for (l = 0; l < 40; l++) + if (start[l] == '\n' || !start[l]) + break; + x = (vid.width - l * 8) / 2; + for (j = 0; j < l; j++, x += 8) + Draw_Character (x, y, start[j]); + + y += 8; + + while (*start && *start != '\n') + start++; + + if (!*start) + break; + start++; // skip the \n + } while (1); +} + +//============================================================================= + +/* + SCR_UpdateScreen + + This is called every frame, and can also be called explicitly to flush + text to the screen. + + WARNING: be very careful calling this from elsewhere, because the refresh + needs almost the entire 256k of stack space! +*/ +void +SCR_UpdateScreen (double realtime, SCR_Func *scr_funcs, int swap) +{ + static int oldscr_viewsize; + vrect_t vrect; + + if (scr_skipupdate || block_drawing) + return; + + if (scr_disabled_for_loading) + return; + +#ifdef _WIN32 + { // don't suck up any cpu if minimized + extern qboolean Minimized; + + if (Minimized) + return; + } +#endif + + r_realtime = realtime; + + scr_copytop = 0; + scr_copyeverything = 0; + + if (!scr_initialized || !con_initialized) + return; // not initialized yet + + if (scr_viewsize->int_val != oldscr_viewsize) { + oldscr_viewsize = scr_viewsize->int_val; + vid.recalc_refdef = 1; + } + + // check for vid changes + if (oldfov != scr_fov->int_val) { + oldfov = scr_fov->int_val; + vid.recalc_refdef = true; + } + + if (oldscreensize != scr_viewsize->int_val) { + oldscreensize = scr_viewsize->int_val; + vid.recalc_refdef = true; + } + + if (vid.recalc_refdef) { + // something changed, so reorder the screen + SCR_CalcRefdef (); + } + + // do 3D refresh drawing, and then update the screen + D_EnableBackBufferAccess (); // of all overlay stuff if drawing + // directly + if (scr_fullupdate++ < vid.numpages) { // clear the entire screen + scr_copyeverything = 1; + Draw_TileClear (0, 0, vid.width, vid.height); + Sbar_Changed (); + } + + pconupdate = NULL; + + SCR_SetUpToDrawConsole (); + + D_DisableBackBufferAccess (); // for adapters that can't stay mapped + // in for linear writes all the time + VID_LockBuffer (); + V_RenderView (); + VID_UnlockBuffer (); + + D_EnableBackBufferAccess (); // of all overlay stuff if drawing + // directly + if (r_force_fullscreen /*FIXME*/ == 1 && key_dest == key_game) { + Sbar_IntermissionOverlay (); + } else if (r_force_fullscreen /*FIXME*/ == 2 && key_dest == key_game) { + Sbar_FinaleOverlay (); + SCR_CheckDrawCenterString (swap); + } else { + while (*scr_funcs) { + (*scr_funcs)(swap); + scr_funcs++; + } + } + + D_DisableBackBufferAccess (); // for adapters that can't stay mapped + // in for linear writes all the time + if (pconupdate) { + D_UpdateRects (pconupdate); + } + + SCR_ApplyBlend (); + + // update one of three areas + if (scr_copyeverything) { + vrect.x = 0; + vrect.y = 0; + vrect.width = vid.width; + vrect.height = vid.height; + vrect.pnext = 0; + + VID_Update (&vrect); + } else if (scr_copytop) { + vrect.x = 0; + vrect.y = 0; + vrect.width = vid.width; + vrect.height = vid.height - sb_lines; + vrect.pnext = 0; + + VID_Update (&vrect); + } else { + vrect.x = scr_vrect.x; + vrect.y = scr_vrect.y; + vrect.width = scr_vrect.width; + vrect.height = scr_vrect.height; + vrect.pnext = 0; + + VID_Update (&vrect); + } +} diff --git a/libs/video/renderer/sw32/sw32_graph.c b/libs/video/renderer/sw32/sw32_graph.c new file mode 100644 index 000000000..ce5a67066 --- /dev/null +++ b/libs/video/renderer/sw32/sw32_graph.c @@ -0,0 +1,101 @@ +/* + sw32_graph.c + + (description) + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_STRING_H +# include "string.h" +#endif +#ifdef HAVE_STRINGS_H +# include "strings.h" +#endif + +#include "QF/cvar.h" +#include "QF/draw.h" +#include "QF/render.h" +#include "QF/sys.h" + +#include "r_local.h" +#include "r_cvar.h" + +/* + R_LineGraph + + Only called by R_DisplayTime +*/ +void +R_LineGraph (int x, int y, int *h_vals, int count) +{ + int h, i, s, color; + +// FIXME: disable on no-buffer adapters, or put in the driver + s = r_graphheight->int_val; + + h = *h_vals++; + + if (h == 10000) + color = 0x6f; // yellow + else if (h == 9999) + color = 0x4f; // red + else if (h == 9998) + color = 0xd0; // blue + else + color = 0xfe; // white // LordHavoc: was pink (0xff) + + if (h > s) + h = s; + + switch(r_pixbytes) { + case 1: + { + byte *dest = (byte *) vid.buffer + vid.rowbytes * y + x; + for (i = 0; i < h; i++, dest -= vid.rowbytes * 2) + *dest = color; + } + break; + case 2: + { + short *dest = (short *) vid.buffer + (vid.rowbytes >> 1) * y + x; + color = d_8to16table[color]; + for (i = 0; i < h; i++, dest -= vid.rowbytes) + *dest = color; + } + break; + case 4: + { + int *dest = (int *) vid.buffer + (vid.rowbytes >> 2) * y + x; + color = d_8to24table[color]; + for (i = 0; i < h; i++, dest -= (vid.rowbytes >> 1)) + *dest = color; + } + break; + default: + Sys_Error("R_LineGraph: unsupported r_pixbytes %i\n", r_pixbytes); + } +} diff --git a/libs/video/renderer/sw32/sw32_raclip.c b/libs/video/renderer/sw32/sw32_raclip.c new file mode 100644 index 000000000..0dc5d2f1f --- /dev/null +++ b/libs/video/renderer/sw32/sw32_raclip.c @@ -0,0 +1,319 @@ +/* + r_aclip.c + + clip routines for drawing Alias models directly to the screen + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/render.h" + +#include "d_local.h" +#include "r_local.h" + +static finalvert_t fv[2][8]; +static auxvert_t av[8]; + +void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av); +void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, + finalvert_t *out); +void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1, + finalvert_t *out); +void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, + finalvert_t *out); +void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1, + finalvert_t *out); + + +/* + R_Alias_clip_z + + pfv0 is the unclipped vertex, pfv1 is the z-clipped vertex +*/ +void +R_Alias_clip_z (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) +{ + float scale; + auxvert_t *pav0, *pav1, avout; + + pav0 = &av[pfv0 - &fv[0][0]]; + pav1 = &av[pfv1 - &fv[0][0]]; + + if (pfv0->v[1] >= pfv1->v[1]) { + scale = (ALIAS_Z_CLIP_PLANE - pav0->fv[2]) / + (pav1->fv[2] - pav0->fv[2]); + + avout.fv[0] = pav0->fv[0] + (pav1->fv[0] - pav0->fv[0]) * scale; + avout.fv[1] = pav0->fv[1] + (pav1->fv[1] - pav0->fv[1]) * scale; + avout.fv[2] = ALIAS_Z_CLIP_PLANE; + + out->v[2] = pfv0->v[2] + (pfv1->v[2] - pfv0->v[2]) * scale; + out->v[3] = pfv0->v[3] + (pfv1->v[3] - pfv0->v[3]) * scale; + out->v[4] = pfv0->v[4] + (pfv1->v[4] - pfv0->v[4]) * scale; + } else { + scale = (ALIAS_Z_CLIP_PLANE - pav1->fv[2]) / + (pav0->fv[2] - pav1->fv[2]); + + avout.fv[0] = pav1->fv[0] + (pav0->fv[0] - pav1->fv[0]) * scale; + avout.fv[1] = pav1->fv[1] + (pav0->fv[1] - pav1->fv[1]) * scale; + avout.fv[2] = ALIAS_Z_CLIP_PLANE; + + out->v[2] = pfv1->v[2] + (pfv0->v[2] - pfv1->v[2]) * scale; + out->v[3] = pfv1->v[3] + (pfv0->v[3] - pfv1->v[3]) * scale; + out->v[4] = pfv1->v[4] + (pfv0->v[4] - pfv1->v[4]) * scale; + } + + R_AliasProjectFinalVert (out, &avout); + + if (out->v[0] < r_refdef.aliasvrect.x) + out->flags |= ALIAS_LEFT_CLIP; + if (out->v[1] < r_refdef.aliasvrect.y) + out->flags |= ALIAS_TOP_CLIP; + if (out->v[0] > r_refdef.aliasvrectright) + out->flags |= ALIAS_RIGHT_CLIP; + if (out->v[1] > r_refdef.aliasvrectbottom) + out->flags |= ALIAS_BOTTOM_CLIP; +} + +void +R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) +{ + float scale; + int i; + + if (pfv0->v[1] >= pfv1->v[1]) { + scale = (float) (r_refdef.aliasvrect.x - pfv0->v[0]) / + (pfv1->v[0] - pfv0->v[0]); + for (i = 0; i < 6; i++) + out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i]) * scale + 0.5; + } else { + scale = (float) (r_refdef.aliasvrect.x - pfv1->v[0]) / + (pfv0->v[0] - pfv1->v[0]); + for (i = 0; i < 6; i++) + out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i]) * scale + 0.5; + } +} + +void +R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) +{ + float scale; + int i; + + if (pfv0->v[1] >= pfv1->v[1]) { + scale = (float) (r_refdef.aliasvrectright - pfv0->v[0]) / + (pfv1->v[0] - pfv0->v[0]); + for (i = 0; i < 6; i++) + out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i]) * scale + 0.5; + } else { + scale = (float) (r_refdef.aliasvrectright - pfv1->v[0]) / + (pfv0->v[0] - pfv1->v[0]); + for (i = 0; i < 6; i++) + out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i]) * scale + 0.5; + } +} + +void +R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) +{ + float scale; + int i; + + if (pfv0->v[1] >= pfv1->v[1]) { + scale = (float) (r_refdef.aliasvrect.y - pfv0->v[1]) / + (pfv1->v[1] - pfv0->v[1]); + for (i = 0; i < 6; i++) + out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i]) * scale + 0.5; + } else { + scale = (float) (r_refdef.aliasvrect.y - pfv1->v[1]) / + (pfv0->v[1] - pfv1->v[1]); + for (i = 0; i < 6; i++) + out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i]) * scale + 0.5; + } +} + +void +R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) +{ + float scale; + int i; + + if (pfv0->v[1] >= pfv1->v[1]) { + scale = (float) (r_refdef.aliasvrectbottom - pfv0->v[1]) / + (pfv1->v[1] - pfv0->v[1]); + + for (i = 0; i < 6; i++) + out->v[i] = pfv0->v[i] + (pfv1->v[i] - pfv0->v[i]) * scale + 0.5; + } else { + scale = (float) (r_refdef.aliasvrectbottom - pfv1->v[1]) / + (pfv0->v[1] - pfv1->v[1]); + + for (i = 0; i < 6; i++) + out->v[i] = pfv1->v[i] + (pfv0->v[i] - pfv1->v[i]) * scale + 0.5; + } +} + +int +R_AliasClip (finalvert_t *in, finalvert_t *out, int flag, int count, + void (*clip) (finalvert_t *pfv0, finalvert_t *pfv1, + finalvert_t *out)) +{ + int i, j, k; + int flags, oldflags; + + j = count - 1; + k = 0; + for (i = 0; i < count; j = i, i++) { + oldflags = in[j].flags & flag; + flags = in[i].flags & flag; + + if (flags && oldflags) + continue; + if (oldflags ^ flags) { + clip (&in[j], &in[i], &out[k]); + out[k].flags = 0; + if (out[k].v[0] < r_refdef.aliasvrect.x) + out[k].flags |= ALIAS_LEFT_CLIP; + if (out[k].v[1] < r_refdef.aliasvrect.y) + out[k].flags |= ALIAS_TOP_CLIP; + if (out[k].v[0] > r_refdef.aliasvrectright) + out[k].flags |= ALIAS_RIGHT_CLIP; + if (out[k].v[1] > r_refdef.aliasvrectbottom) + out[k].flags |= ALIAS_BOTTOM_CLIP; + k++; + } + if (!flags) { + out[k] = in[i]; + k++; + } + } + + return k; +} + +void +R_AliasClipTriangle (mtriangle_t *ptri) +{ + int i, k, pingpong; + mtriangle_t mtri; + unsigned int clipflags; + + // copy vertexes and fix seam texture coordinates + if (ptri->facesfront) { + fv[0][0] = pfinalverts[ptri->vertindex[0]]; + fv[0][1] = pfinalverts[ptri->vertindex[1]]; + fv[0][2] = pfinalverts[ptri->vertindex[2]]; + } else { + for (i = 0; i < 3; i++) { + fv[0][i] = pfinalverts[ptri->vertindex[i]]; + + if (!ptri->facesfront && (fv[0][i].flags & ALIAS_ONSEAM)) + fv[0][i].v[2] += r_affinetridesc.seamfixupX16; + } + } + + // clip + clipflags = fv[0][0].flags | fv[0][1].flags | fv[0][2].flags; + + if (clipflags & ALIAS_Z_CLIP) { + for (i = 0; i < 3; i++) + av[i] = pauxverts[ptri->vertindex[i]]; + + k = R_AliasClip (fv[0], fv[1], ALIAS_Z_CLIP, 3, R_Alias_clip_z); + if (k == 0) + return; + + pingpong = 1; + clipflags = fv[1][0].flags | fv[1][1].flags | fv[1][2].flags; + } else { + pingpong = 0; + k = 3; + } + + if (clipflags & ALIAS_LEFT_CLIP) { + k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], + ALIAS_LEFT_CLIP, k, R_Alias_clip_left); + if (k == 0) + return; + + pingpong ^= 1; + } + + if (clipflags & ALIAS_RIGHT_CLIP) { + k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], + ALIAS_RIGHT_CLIP, k, R_Alias_clip_right); + if (k == 0) + return; + + pingpong ^= 1; + } + + if (clipflags & ALIAS_BOTTOM_CLIP) { + k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], + ALIAS_BOTTOM_CLIP, k, R_Alias_clip_bottom); + if (k == 0) + return; + + pingpong ^= 1; + } + + if (clipflags & ALIAS_TOP_CLIP) { + k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], + ALIAS_TOP_CLIP, k, R_Alias_clip_top); + if (k == 0) + return; + + pingpong ^= 1; + } + + for (i = 0; i < k; i++) { + if (fv[pingpong][i].v[0] < r_refdef.aliasvrect.x) + fv[pingpong][i].v[0] = r_refdef.aliasvrect.x; + else if (fv[pingpong][i].v[0] > r_refdef.aliasvrectright) + fv[pingpong][i].v[0] = r_refdef.aliasvrectright; + + if (fv[pingpong][i].v[1] < r_refdef.aliasvrect.y) + fv[pingpong][i].v[1] = r_refdef.aliasvrect.y; + else if (fv[pingpong][i].v[1] > r_refdef.aliasvrectbottom) + fv[pingpong][i].v[1] = r_refdef.aliasvrectbottom; + + fv[pingpong][i].flags = 0; + } + + // draw triangles + mtri.facesfront = ptri->facesfront; + r_affinetridesc.ptriangles = &mtri; + r_affinetridesc.pfinalverts = fv[pingpong]; + + // FIXME: do all at once as trifan? + mtri.vertindex[0] = 0; + for (i = 1; i < k - 1; i++) { + mtri.vertindex[1] = i; + mtri.vertindex[2] = i + 1; + D_PolysetDraw (); + } +} diff --git a/libs/video/renderer/sw32/sw32_ralias.c b/libs/video/renderer/sw32/sw32_ralias.c new file mode 100644 index 000000000..8ad45b710 --- /dev/null +++ b/libs/video/renderer/sw32/sw32_ralias.c @@ -0,0 +1,679 @@ +/* + sw32_ralias.c + + routines for setting up to draw alias models + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/console.h" +#include "QF/render.h" +#include "QF/skin.h" +#include "QF/sys.h" +#include "QF/texture.h" + +#include "d_ifacea.h" +#include "r_local.h" + +#define LIGHT_MIN 5 // lowest light value we'll allow, to + // avoid the need for inner-loop light + // clamping + +mtriangle_t *ptriangles; +affinetridesc_t r_affinetridesc; + +void *acolormap; // FIXME: should go away + +trivertx_t *r_apverts; + +// TODO: these probably will go away with optimized rasterization +mdl_t *pmdl; +vec3_t r_plightvec; +int r_ambientlight; +float r_shadelight; +aliashdr_t *paliashdr; +finalvert_t *pfinalverts; +auxvert_t *pauxverts; +static float ziscale; +static model_t *pmodel; + +static vec3_t alias_forward, alias_right, alias_up; + +static maliasskindesc_t *pskindesc; + +int r_amodels_drawn; +int a_skinwidth; +int r_anumverts; + +float aliastransform[3][4]; + +typedef struct { + int index0; + int index1; +} aedge_t; + +static aedge_t aedges[12] = { + {0, 1}, {1, 2}, {2, 3}, {3, 0}, + {4, 5}, {5, 6}, {6, 7}, {7, 4}, + {0, 5}, {1, 4}, {2, 7}, {3, 6} +}; + +#define NUMVERTEXNORMALS 162 + +float r_avertexnormals[NUMVERTEXNORMALS][3] = { +#include "anorms.h" +}; + +void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv, + stvert_t *pstverts); +void R_AliasSetUpTransform (int trivial_accept); +void R_AliasTransformVector (vec3_t in, vec3_t out); +void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av, + trivertx_t *pverts, stvert_t *pstverts); +void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av); + + +qboolean +R_AliasCheckBBox (void) +{ + int i, flags, frame, numv; + aliashdr_t *pahdr; + float zi, basepts[8][3], v0, v1, frac; + finalvert_t *pv0, *pv1, viewpts[16]; + auxvert_t *pa0, *pa1, viewaux[16]; + maliasframedesc_t *pframedesc; + qboolean zclipped, zfullyclipped; + unsigned int anyclip, allclip; + int minz; + + // expand, rotate, and translate points into worldspace + + currententity->trivial_accept = 0; + pmodel = currententity->model; + pahdr = Mod_Extradata (pmodel); + pmdl = (mdl_t *) ((byte *) pahdr + pahdr->model); + + R_AliasSetUpTransform (0); + + // construct the base bounding box for this frame + frame = currententity->frame; +// TODO: don't repeat this check when drawing? + if ((frame >= pmdl->numframes) || (frame < 0)) { + Con_DPrintf ("No such frame %d %s\n", frame, pmodel->name); + frame = 0; + } + + pframedesc = &pahdr->frames[frame]; + + // x worldspace coordinates + basepts[0][0] = basepts[1][0] = basepts[2][0] = basepts[3][0] = + (float) pframedesc->bboxmin.v[0]; + basepts[4][0] = basepts[5][0] = basepts[6][0] = basepts[7][0] = + (float) pframedesc->bboxmax.v[0]; + + // y worldspace coordinates + basepts[0][1] = basepts[3][1] = basepts[5][1] = basepts[6][1] = + (float) pframedesc->bboxmin.v[1]; + basepts[1][1] = basepts[2][1] = basepts[4][1] = basepts[7][1] = + (float) pframedesc->bboxmax.v[1]; + + // z worldspace coordinates + basepts[0][2] = basepts[1][2] = basepts[4][2] = basepts[5][2] = + (float) pframedesc->bboxmin.v[2]; + basepts[2][2] = basepts[3][2] = basepts[6][2] = basepts[7][2] = + (float) pframedesc->bboxmax.v[2]; + + zclipped = false; + zfullyclipped = true; + + minz = 9999; + for (i = 0; i < 8; i++) { + R_AliasTransformVector (&basepts[i][0], &viewaux[i].fv[0]); + + if (viewaux[i].fv[2] < ALIAS_Z_CLIP_PLANE) { + // we must clip points that are closer than the near clip plane + viewpts[i].flags = ALIAS_Z_CLIP; + zclipped = true; + } else { + if (viewaux[i].fv[2] < minz) + minz = viewaux[i].fv[2]; + viewpts[i].flags = 0; + zfullyclipped = false; + } + } + + if (zfullyclipped) { + return false; // everything was near-z-clipped + } + + numv = 8; + + if (zclipped) { + // organize points by edges, use edges to get new points (possible + // trivial reject) + for (i = 0; i < 12; i++) { + // edge endpoints + pv0 = &viewpts[aedges[i].index0]; + pv1 = &viewpts[aedges[i].index1]; + pa0 = &viewaux[aedges[i].index0]; + pa1 = &viewaux[aedges[i].index1]; + + // if one end is clipped and the other isn't, make a new point + if (pv0->flags ^ pv1->flags) { + frac = (ALIAS_Z_CLIP_PLANE - pa0->fv[2]) / + (pa1->fv[2] - pa0->fv[2]); + viewaux[numv].fv[0] = pa0->fv[0] + + (pa1->fv[0] - pa0->fv[0]) * frac; + viewaux[numv].fv[1] = pa0->fv[1] + + (pa1->fv[1] - pa0->fv[1]) * frac; + viewaux[numv].fv[2] = ALIAS_Z_CLIP_PLANE; + viewpts[numv].flags = 0; + numv++; + } + } + } + // project the vertices that remain after clipping + anyclip = 0; + allclip = ALIAS_XY_CLIP_MASK; + +// TODO: probably should do this loop in ASM, especially if we use floats + for (i = 0; i < numv; i++) { + // we don't need to bother with vertices that were z-clipped + if (viewpts[i].flags & ALIAS_Z_CLIP) + continue; + + zi = 1.0 / viewaux[i].fv[2]; + + // FIXME: do with chop mode in ASM, or convert to float + v0 = (viewaux[i].fv[0] * xscale * zi) + xcenter; + v1 = (viewaux[i].fv[1] * yscale * zi) + ycenter; + + flags = 0; + + if (v0 < r_refdef.fvrectx) + flags |= ALIAS_LEFT_CLIP; + if (v1 < r_refdef.fvrecty) + flags |= ALIAS_TOP_CLIP; + if (v0 > r_refdef.fvrectright) + flags |= ALIAS_RIGHT_CLIP; + if (v1 > r_refdef.fvrectbottom) + flags |= ALIAS_BOTTOM_CLIP; + + anyclip |= flags; + allclip &= flags; + } + + if (allclip) + return false; // trivial reject off one side + + currententity->trivial_accept = !anyclip & !zclipped; + + if (currententity->trivial_accept) { + if (minz > (r_aliastransition + (pmdl->size * r_resfudge))) { + currententity->trivial_accept |= 2; + } + } + + return true; +} + +void +R_AliasTransformVector (vec3_t in, vec3_t out) +{ + out[0] = DotProduct (in, aliastransform[0]) + aliastransform[0][3]; + out[1] = DotProduct (in, aliastransform[1]) + aliastransform[1][3]; + out[2] = DotProduct (in, aliastransform[2]) + aliastransform[2][3]; +} + +/* + R_AliasPreparePoints + + General clipped case +*/ +void +R_AliasPreparePoints (void) +{ + int i; + stvert_t *pstverts; + finalvert_t *fv; + auxvert_t *av; + mtriangle_t *ptri; + finalvert_t *pfv[3]; + + pstverts = (stvert_t *) ((byte *) paliashdr + paliashdr->stverts); + r_anumverts = pmdl->numverts; + fv = pfinalverts; + av = pauxverts; + + for (i = 0; i < r_anumverts; i++, fv++, av++, r_apverts++, pstverts++) { + R_AliasTransformFinalVert (fv, av, r_apverts, pstverts); + if (av->fv[2] < ALIAS_Z_CLIP_PLANE) + fv->flags |= ALIAS_Z_CLIP; + else { + R_AliasProjectFinalVert (fv, av); + + if (fv->v[0] < r_refdef.aliasvrect.x) + fv->flags |= ALIAS_LEFT_CLIP; + if (fv->v[1] < r_refdef.aliasvrect.y) + fv->flags |= ALIAS_TOP_CLIP; + if (fv->v[0] > r_refdef.aliasvrectright) + fv->flags |= ALIAS_RIGHT_CLIP; + if (fv->v[1] > r_refdef.aliasvrectbottom) + fv->flags |= ALIAS_BOTTOM_CLIP; + } + } + + // clip and draw all triangles + r_affinetridesc.numtriangles = 1; + + ptri = (mtriangle_t *) ((byte *) paliashdr + paliashdr->triangles); + for (i = 0; i < pmdl->numtris; i++, ptri++) { + pfv[0] = &pfinalverts[ptri->vertindex[0]]; + pfv[1] = &pfinalverts[ptri->vertindex[1]]; + pfv[2] = &pfinalverts[ptri->vertindex[2]]; + + if (pfv[0]->flags & pfv[1]->flags & pfv[2]-> + flags & (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP)) + continue; // completely clipped + + if (!((pfv[0]->flags | pfv[1]->flags | pfv[2]->flags) & + (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP))) { // totally unclipped + r_affinetridesc.pfinalverts = pfinalverts; + r_affinetridesc.ptriangles = ptri; + D_PolysetDraw (); + } else { // partially clipped + R_AliasClipTriangle (ptri); + } + } +} + +void +R_AliasSetUpTransform (int trivial_accept) +{ + int i; + float rotationmatrix[3][4], t2matrix[3][4]; + static float tmatrix[3][4]; + static float viewmatrix[3][4]; + vec3_t angles; + +// TODO: should really be stored with the entity instead of being reconstructed +// TODO: should use a look-up table +// TODO: could cache lazily, stored in the entity + + angles[ROLL] = currententity->angles[ROLL]; + angles[PITCH] = -currententity->angles[PITCH]; + angles[YAW] = currententity->angles[YAW]; + AngleVectors (angles, alias_forward, alias_right, alias_up); + + tmatrix[0][0] = pmdl->scale[0]; + tmatrix[1][1] = pmdl->scale[1]; + tmatrix[2][2] = pmdl->scale[2]; + + tmatrix[0][3] = pmdl->scale_origin[0]; + tmatrix[1][3] = pmdl->scale_origin[1]; + tmatrix[2][3] = pmdl->scale_origin[2]; + +// TODO: can do this with simple matrix rearrangement + + for (i = 0; i < 3; i++) { + t2matrix[i][0] = alias_forward[i]; + t2matrix[i][1] = -alias_right[i]; + t2matrix[i][2] = alias_up[i]; + } + + t2matrix[0][3] = -modelorg[0]; + t2matrix[1][3] = -modelorg[1]; + t2matrix[2][3] = -modelorg[2]; + +// FIXME: can do more efficiently than full concatenation + R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix); + +// TODO: should be global, set when vright, etc., set + VectorCopy (vright, viewmatrix[0]); + VectorCopy (vup, viewmatrix[1]); + VectorInverse (viewmatrix[1]); + VectorCopy (vpn, viewmatrix[2]); + +// viewmatrix[0][3] = 0; +// viewmatrix[1][3] = 0; +// viewmatrix[2][3] = 0; + + R_ConcatTransforms (viewmatrix, rotationmatrix, aliastransform); + +// do the scaling up of x and y to screen coordinates as part of the transform +// for the unclipped case (it would mess up clipping in the clipped case). +// Also scale down z, so 1/z is scaled 31 bits for free, and scale down x and y +// correspondingly so the projected x and y come out right +// FIXME: make this work for clipped case too? + if (trivial_accept) { + for (i = 0; i < 4; i++) { + aliastransform[0][i] *= aliasxscale * + (1.0 / ((float) 0x8000 * 0x10000)); + aliastransform[1][i] *= aliasyscale * + (1.0 / ((float) 0x8000 * 0x10000)); + aliastransform[2][i] *= 1.0 / ((float) 0x8000 * 0x10000); + } + } +} + +void +R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av, + trivertx_t *pverts, stvert_t *pstverts) +{ + int temp; + float lightcos, *plightnormal; + + av->fv[0] = DotProduct (pverts->v, aliastransform[0]) + + aliastransform[0][3]; + av->fv[1] = DotProduct (pverts->v, aliastransform[1]) + + aliastransform[1][3]; + av->fv[2] = DotProduct (pverts->v, aliastransform[2]) + + aliastransform[2][3]; + + fv->v[2] = pstverts->s; + fv->v[3] = pstverts->t; + + fv->flags = pstverts->onseam; + + // lighting + // LordHavoc: flipped lightcos so it is + for bright, not - + plightnormal = r_avertexnormals[pverts->lightnormalindex]; + lightcos = -DotProduct (plightnormal, r_plightvec); + temp = r_ambientlight; + + if (lightcos > 0) { + temp += (int) (r_shadelight * lightcos); + + // clamp; because we limited the minimum ambient and shading light, + // we don't have to clamp low light, just bright + if (temp < 0) + temp = 0; + } + + fv->v[4] = temp; +} + +void +R_AliasTransformAndProjectFinalVerts (finalvert_t *fv, stvert_t *pstverts) +{ + int i, temp; + float lightcos, *plightnormal, zi; + trivertx_t *pverts; + + pverts = r_apverts; + + for (i = 0; i < r_anumverts; i++, fv++, pverts++, pstverts++) { + // transform and project + zi = 1.0 / (DotProduct (pverts->v, aliastransform[2]) + + aliastransform[2][3]); + + // x, y, and z are scaled down by 1/2**31 in the transform, so 1/z is + // scaled up by 1/2**31, and the scaling cancels out for x and y in + // the projection + fv->v[5] = zi; + + fv->v[0] = ((DotProduct (pverts->v, aliastransform[0]) + + aliastransform[0][3]) * zi) + aliasxcenter; + fv->v[1] = ((DotProduct (pverts->v, aliastransform[1]) + + aliastransform[1][3]) * zi) + aliasycenter; + + fv->v[2] = pstverts->s; + fv->v[3] = pstverts->t; + fv->flags = pstverts->onseam; + + // lighting + // LordHavoc: flipped lightcos so it is + for bright, not - + plightnormal = r_avertexnormals[pverts->lightnormalindex]; + lightcos = -DotProduct (plightnormal, r_plightvec); + temp = r_ambientlight; + + if (lightcos > 0) { + temp += (int) (r_shadelight * lightcos); + + // clamp; because we limited the minimum ambient and shading + // light, we don't have to clamp low light, just bright + if (temp < 0) + temp = 0; + } + + fv->v[4] = temp; + } +} + +void +R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av) +{ + float zi; + + // project points + zi = 1.0 / av->fv[2]; + + fv->v[5] = zi * ziscale; + + fv->v[0] = (av->fv[0] * aliasxscale * zi) + aliasxcenter; + fv->v[1] = (av->fv[1] * aliasyscale * zi) + aliasycenter; +} + +void +R_AliasPrepareUnclippedPoints (void) +{ + stvert_t *pstverts; + + pstverts = (stvert_t *) ((byte *) paliashdr + paliashdr->stverts); + r_anumverts = pmdl->numverts; + + R_AliasTransformAndProjectFinalVerts (pfinalverts, pstverts); + + r_affinetridesc.pfinalverts = pfinalverts; + r_affinetridesc.ptriangles = (mtriangle_t *) + ((byte *) paliashdr + paliashdr->triangles); + r_affinetridesc.numtriangles = pmdl->numtris; + + D_PolysetDraw (); +} + +void +R_AliasSetupSkin (void) +{ + int skinnum; + int i, numskins; + maliasskingroup_t *paliasskingroup; + float *pskinintervals, fullskininterval; + float skintargettime, skintime; + + skinnum = currententity->skinnum; + if ((skinnum >= pmdl->numskins) || (skinnum < 0)) { + Con_DPrintf ("R_AliasSetupSkin: no such skin # %d\n", skinnum); + skinnum = 0; + } + + pskindesc = ((maliasskindesc_t *) + ((byte *) paliashdr + paliashdr->skindesc)) + skinnum; + a_skinwidth = pmdl->skinwidth; + + if (pskindesc->type == ALIAS_SKIN_GROUP) { + paliasskingroup = (maliasskingroup_t *) ((byte *) paliashdr + + pskindesc->skin); + pskinintervals = (float *) + ((byte *) paliashdr + paliasskingroup->intervals); + numskins = paliasskingroup->numskins; + fullskininterval = pskinintervals[numskins - 1]; + + skintime = r_realtime + currententity->syncbase; + + // when loading in Mod_LoadAliasSkinGroup, we guaranteed all interval + // values are positive, so we don't have to worry about division by 0 + skintargettime = skintime - + ((int) (skintime / fullskininterval)) * fullskininterval; + + for (i = 0; i < (numskins - 1); i++) { + if (pskinintervals[i] > skintargettime) + break; + } + + pskindesc = &paliasskingroup->skindescs[i]; + } + + r_affinetridesc.pskindesc = pskindesc; + r_affinetridesc.pskin = (void *) ((byte *) paliashdr + pskindesc->skin); + r_affinetridesc.skinwidth = a_skinwidth; + r_affinetridesc.seamfixupX16 = (a_skinwidth >> 1) << 16; + r_affinetridesc.skinheight = pmdl->skinheight; + + if (currententity->skin) { + tex_t *base; + + base = currententity->skin->data.texels; + if (base) { + r_affinetridesc.pskin = base->data; + r_affinetridesc.skinwidth = base->width; + r_affinetridesc.skinheight = base->height; + } + } +} + +void +R_AliasSetupLighting (alight_t *plighting) +{ + // guarantee that no vertex will ever be lit below LIGHT_MIN, so we don't + // have to clamp off the bottom + r_ambientlight = plighting->ambientlight; + + if (r_ambientlight < LIGHT_MIN) + r_ambientlight = LIGHT_MIN; + + r_ambientlight = (/*255 -*/ r_ambientlight) << VID_CBITS; + +// if (r_ambientlight < LIGHT_MIN) +// r_ambientlight = LIGHT_MIN; + + r_shadelight = plighting->shadelight; + + if (r_shadelight < 0) + r_shadelight = 0; + + r_shadelight *= VID_GRADES; + + // rotate the lighting vector into the model's frame of reference + r_plightvec[0] = DotProduct (plighting->plightvec, alias_forward); + r_plightvec[1] = -DotProduct (plighting->plightvec, alias_right); + r_plightvec[2] = DotProduct (plighting->plightvec, alias_up); +} + +/* + R_AliasSetupFrame + + set r_apverts +*/ +void +R_AliasSetupFrame (void) +{ + int frame; + int i, numframes; + maliasgroup_t *paliasgroup; + float *pintervals, fullinterval, targettime, time; + + frame = currententity->frame; + if ((frame >= pmdl->numframes) || (frame < 0)) { + Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame); + frame = 0; + } + + if (paliashdr->frames[frame].type == ALIAS_SINGLE) { + r_apverts = (trivertx_t *) + ((byte *) paliashdr + paliashdr->frames[frame].frame); + return; + } + + paliasgroup = (maliasgroup_t *) + ((byte *) paliashdr + paliashdr->frames[frame].frame); + pintervals = (float *) ((byte *) paliashdr + paliasgroup->intervals); + numframes = paliasgroup->numframes; + fullinterval = pintervals[numframes - 1]; + + time = r_realtime + currententity->syncbase; + + // when loading in Mod_LoadAliasGroup, we guaranteed all interval values + // are positive, so we don't have to worry about division by 0 + targettime = time - ((int) (time / fullinterval)) * fullinterval; + + for (i = 0; i < (numframes - 1); i++) { + if (pintervals[i] > targettime) + break; + } + + r_apverts = (trivertx_t *) + ((byte *) paliashdr + paliasgroup->frames[i].frame); +} + +void +R_AliasDrawModel (alight_t *plighting) +{ + finalvert_t finalverts[MAXALIASVERTS + + ((CACHE_SIZE - 1) / sizeof (finalvert_t)) + 1]; + auxvert_t auxverts[MAXALIASVERTS]; + + r_amodels_drawn++; + + // cache align + pfinalverts = (finalvert_t *) + (((long) &finalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); + pauxverts = &auxverts[0]; + + paliashdr = (aliashdr_t *) Mod_Extradata (currententity->model); + pmdl = (mdl_t *) ((byte *) paliashdr + paliashdr->model); + + R_AliasSetupSkin (); + R_AliasSetUpTransform (currententity->trivial_accept); + R_AliasSetupLighting (plighting); + R_AliasSetupFrame (); + + if (!currententity->colormap) + Sys_Error ("R_AliasDrawModel: !currententity->colormap"); + + acolormap = currententity->colormap; + if (acolormap == &vid.colormap8 && r_pixbytes != 1) + { + if (r_pixbytes == 2) + acolormap = vid.colormap16; + else if (r_pixbytes == 4) + acolormap = vid.colormap32; + else + Sys_Error("R_AliasDrawmodel: unsupported r_pixbytes %i\n", + r_pixbytes); + } + + if (currententity != r_view_model) + ziscale = (float) 0x8000 *(float) 0x10000; + else + ziscale = (float) 0x8000 *(float) 0x10000 *3.0; + + if (currententity->trivial_accept) + R_AliasPrepareUnclippedPoints (); + else + R_AliasPreparePoints (); +} diff --git a/libs/video/renderer/sw32/sw32_rbsp.c b/libs/video/renderer/sw32/sw32_rbsp.c new file mode 100644 index 000000000..15193bdb6 --- /dev/null +++ b/libs/video/renderer/sw32/sw32_rbsp.c @@ -0,0 +1,579 @@ +/* + sw32_r_bsp.c + + (description) + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "QF/console.h" +#include "QF/render.h" +#include "QF/sys.h" + +#include "r_local.h" + +// current entity info +qboolean insubmodel; +entity_t *currententity; +vec3_t modelorg; // modelorg is the viewpoint relative to + // the currently rendering entity +vec3_t base_modelorg; +vec3_t r_worldmodelorg; +vec3_t r_entorigin; // the currently rendering entity in world + // coordinates +float entity_rotation[3][3]; + +int r_currentbkey; + +typedef enum { touchessolid, drawnode, nodrawnode } solidstate_t; + +#define MAX_BMODEL_VERTS 500 // 6K +#define MAX_BMODEL_EDGES 1000 // 12K + +static mvertex_t *pbverts; +static bedge_t *pbedges; +static int numbverts, numbedges; + +static mvertex_t *pfrontenter, *pfrontexit; + +static qboolean makeclippededge; + + +void +R_EntityRotate (vec3_t vec) +{ + vec3_t tvec; + + VectorCopy (vec, tvec); + vec[0] = DotProduct (entity_rotation[0], tvec); + vec[1] = DotProduct (entity_rotation[1], tvec); + vec[2] = DotProduct (entity_rotation[2], tvec); +} + +void +R_RotateBmodel (void) +{ + float angle, s, c, temp1[3][3], temp2[3][3], temp3[3][3]; + +// TODO: should use a look-up table +// TODO: should really be stored with the entity instead of being reconstructed +// TODO: could cache lazily, stored in the entity +// TODO: share work with R_SetUpAliasTransform + + // yaw + angle = currententity->angles[YAW]; + angle = angle * M_PI * 2 / 360; + s = sin (angle); + c = cos (angle); + + temp1[0][0] = c; + temp1[0][1] = s; + temp1[0][2] = 0; + temp1[1][0] = -s; + temp1[1][1] = c; + temp1[1][2] = 0; + temp1[2][0] = 0; + temp1[2][1] = 0; + temp1[2][2] = 1; + + // pitch + angle = currententity->angles[PITCH]; + angle = angle * M_PI * 2 / 360; + s = sin (angle); + c = cos (angle); + + temp2[0][0] = c; + temp2[0][1] = 0; + temp2[0][2] = -s; + temp2[1][0] = 0; + temp2[1][1] = 1; + temp2[1][2] = 0; + temp2[2][0] = s; + temp2[2][1] = 0; + temp2[2][2] = c; + + R_ConcatRotations (temp2, temp1, temp3); + + // roll + angle = currententity->angles[ROLL]; + angle = angle * M_PI * 2 / 360; + s = sin (angle); + c = cos (angle); + + temp1[0][0] = 1; + temp1[0][1] = 0; + temp1[0][2] = 0; + temp1[1][0] = 0; + temp1[1][1] = c; + temp1[1][2] = s; + temp1[2][0] = 0; + temp1[2][1] = -s; + temp1[2][2] = c; + + R_ConcatRotations (temp1, temp3, entity_rotation); + + // rotate modelorg and the transformation matrix + R_EntityRotate (modelorg); + R_EntityRotate (vpn); + R_EntityRotate (vright); + R_EntityRotate (vup); + + R_TransformFrustum (); +} + +void +R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf) +{ + bedge_t *psideedges[2], *pnextedge, *ptedge; + int i, side, lastside; + float dist, frac, lastdist; + mplane_t *splitplane, tplane; + mvertex_t *pvert, *plastvert, *ptvert; + mnode_t *pn; + + psideedges[0] = psideedges[1] = NULL; + + makeclippededge = false; + + // transform the BSP plane into model space + // FIXME: cache these? + splitplane = pnode->plane; + tplane.dist = splitplane->dist - + DotProduct (r_entorigin, splitplane->normal); + tplane.normal[0] = DotProduct (entity_rotation[0], splitplane->normal); + tplane.normal[1] = DotProduct (entity_rotation[1], splitplane->normal); + tplane.normal[2] = DotProduct (entity_rotation[2], splitplane->normal); + + // clip edges to BSP plane + for (; pedges; pedges = pnextedge) { + pnextedge = pedges->pnext; + + // set the status for the last point as the previous point + // FIXME: cache this stuff somehow? + plastvert = pedges->v[0]; + lastdist = DotProduct (plastvert->position, tplane.normal) - + tplane.dist; + + if (lastdist > 0) + lastside = 0; + else + lastside = 1; + + pvert = pedges->v[1]; + + dist = DotProduct (pvert->position, tplane.normal) - tplane.dist; + + if (dist > 0) + side = 0; + else + side = 1; + + if (side != lastside) { + // clipped + if (numbverts >= MAX_BMODEL_VERTS) + return; + + // generate the clipped vertex + frac = lastdist / (lastdist - dist); + ptvert = &pbverts[numbverts++]; + ptvert->position[0] = plastvert->position[0] + + frac * (pvert->position[0] - plastvert->position[0]); + ptvert->position[1] = plastvert->position[1] + + frac * (pvert->position[1] - plastvert->position[1]); + ptvert->position[2] = plastvert->position[2] + + frac * (pvert->position[2] - plastvert->position[2]); + + // split into two edges, one on each side, and remember entering + // and exiting points + // FIXME: share the clip edge by having a winding direction flag? + if (numbedges >= (MAX_BMODEL_EDGES - 1)) { + Con_Printf ("Out of edges for bmodel\n"); + return; + } + + ptedge = &pbedges[numbedges]; + ptedge->pnext = psideedges[lastside]; + psideedges[lastside] = ptedge; + ptedge->v[0] = plastvert; + ptedge->v[1] = ptvert; + + ptedge = &pbedges[numbedges + 1]; + ptedge->pnext = psideedges[side]; + psideedges[side] = ptedge; + ptedge->v[0] = ptvert; + ptedge->v[1] = pvert; + + numbedges += 2; + + if (side == 0) { + // entering for front, exiting for back + pfrontenter = ptvert; + makeclippededge = true; + } else { + pfrontexit = ptvert; + makeclippededge = true; + } + } else { + // add the edge to the appropriate side + pedges->pnext = psideedges[side]; + psideedges[side] = pedges; + } + } + + // if anything was clipped, reconstitute and add the edges along the clip + // plane to both sides (but in opposite directions) + if (makeclippededge) { + if (numbedges >= (MAX_BMODEL_EDGES - 2)) { + Con_Printf ("Out of edges for bmodel\n"); + return; + } + + ptedge = &pbedges[numbedges]; + ptedge->pnext = psideedges[0]; + psideedges[0] = ptedge; + ptedge->v[0] = pfrontexit; + ptedge->v[1] = pfrontenter; + + ptedge = &pbedges[numbedges + 1]; + ptedge->pnext = psideedges[1]; + psideedges[1] = ptedge; + ptedge->v[0] = pfrontenter; + ptedge->v[1] = pfrontexit; + + numbedges += 2; + } + // draw or recurse further + for (i = 0; i < 2; i++) { + if (psideedges[i]) { + // draw if we've reached a non-solid leaf, done if all that's + // left is a + // solid leaf, and continue down the tree if it's not a leaf + pn = pnode->children[i]; + + // we're done with this branch if the node or leaf isn't in the + // PVS + if (pn->visframe == r_visframecount) { + if (pn->contents < 0) { + if (pn->contents != CONTENTS_SOLID) { + r_currentbkey = ((mleaf_t *) pn)->key; + R_RenderBmodelFace (psideedges[i], psurf); + } + } else { + R_RecursiveClipBPoly (psideedges[i], pnode->children[i], + psurf); + } + } + } + } +} + +void +R_DrawSolidClippedSubmodelPolygons (model_t *pmodel) +{ + int i, j, lindex; + vec_t dot; + msurface_t *psurf; + int numsurfaces; + mplane_t *pplane; + mvertex_t bverts[MAX_BMODEL_VERTS]; + bedge_t bedges[MAX_BMODEL_EDGES], *pbedge; + medge_t *pedge, *pedges; + + // FIXME: use bounding-box-based frustum clipping info? + + psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; + numsurfaces = pmodel->nummodelsurfaces; + pedges = pmodel->edges; + + for (i = 0; i < numsurfaces; i++, psurf++) { + // find which side of the node we are on + pplane = psurf->plane; + + dot = DotProduct (modelorg, pplane->normal) - pplane->dist; + + // draw the polygon + if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || + (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { + // FIXME: use bounding-box-based frustum clipping info? + + // copy the edges to bedges, flipping if necessary so always + // clockwise winding + // FIXME: if edges and vertices get caches, these assignments + // must move + // outside the loop, and overflow checking must be done here + pbverts = bverts; + pbedges = bedges; + numbverts = numbedges = 0; + + if (psurf->numedges > 0) { + pbedge = &bedges[numbedges]; + numbedges += psurf->numedges; + + for (j = 0; j < psurf->numedges; j++) { + lindex = pmodel->surfedges[psurf->firstedge + j]; + + if (lindex > 0) { + pedge = &pedges[lindex]; + pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[0]]; + pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[1]]; + } else { + lindex = -lindex; + pedge = &pedges[lindex]; + pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[1]]; + pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[0]]; + } + + pbedge[j].pnext = &pbedge[j + 1]; + } + + pbedge[j - 1].pnext = NULL; // mark end of edges + + R_RecursiveClipBPoly (pbedge, currententity->topnode, psurf); + } else { + Sys_Error ("no edges in bmodel"); + } + } + } +} + +void +R_DrawSubmodelPolygons (model_t *pmodel, int clipflags) +{ + int i; + vec_t dot; + msurface_t *psurf; + int numsurfaces; + mplane_t *pplane; + + // FIXME: use bounding-box-based frustum clipping info? + + psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; + numsurfaces = pmodel->nummodelsurfaces; + + for (i = 0; i < numsurfaces; i++, psurf++) { + // find which side of the node we are on + pplane = psurf->plane; + + dot = DotProduct (modelorg, pplane->normal) - pplane->dist; + + // draw the polygon + if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || + (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { + r_currentkey = ((mleaf_t *) currententity->topnode)->key; + + // FIXME: use bounding-box-based frustum clipping info? + R_RenderFace (psurf, clipflags); + } + } +} + +void +R_RecursiveWorldNode (mnode_t *node, int clipflags) +{ + int i, c, side, *pindex; + vec3_t acceptpt, rejectpt; + mplane_t *plane; + msurface_t *surf, **mark; + mleaf_t *pleaf; + double d, dot; + + if (node->contents == CONTENTS_SOLID) + return; // solid + + if (node->visframe != r_visframecount) + return; + + // cull the clipping planes if not trivial accept + // FIXME: the compiler is doing a lousy job of optimizing here; it could be + // twice as fast in ASM + if (clipflags) { + for (i = 0; i < 4; i++) { + if (!(clipflags & (1 << i))) + continue; // don't need to clip against it + + // generate accept and reject points + // FIXME: do with fast look-ups or integer tests based on the + // sign bit of the floating point values + + pindex = pfrustum_indexes[i]; + + rejectpt[0] = (float) node->minmaxs[pindex[0]]; + rejectpt[1] = (float) node->minmaxs[pindex[1]]; + rejectpt[2] = (float) node->minmaxs[pindex[2]]; + + d = DotProduct (rejectpt, view_clipplanes[i].normal); + d -= view_clipplanes[i].dist; + + if (d <= 0) + return; + + acceptpt[0] = (float) node->minmaxs[pindex[3 + 0]]; + acceptpt[1] = (float) node->minmaxs[pindex[3 + 1]]; + acceptpt[2] = (float) node->minmaxs[pindex[3 + 2]]; + + d = DotProduct (acceptpt, view_clipplanes[i].normal); + d -= view_clipplanes[i].dist; + + if (d >= 0) + clipflags &= ~(1 << i); // node is entirely on screen + } + } + // if a leaf node, draw stuff + if (node->contents < 0) { + pleaf = (mleaf_t *) node; + + mark = pleaf->firstmarksurface; + c = pleaf->nummarksurfaces; + + if (c) { + do { + (*mark)->visframe = r_framecount; + mark++; + } while (--c); + } + // deal with model fragments in this leaf + if (pleaf->efrags) { + R_StoreEfrags (&pleaf->efrags); + } + + pleaf->key = r_currentkey; + r_currentkey++; // all bmodels in a leaf share the + // same key + } else { + // node is just a decision point, so go down the apropriate sides + + // find which side of the node we are on + plane = node->plane; + + switch (plane->type) { + case PLANE_X: + dot = modelorg[0] - plane->dist; + break; + case PLANE_Y: + dot = modelorg[1] - plane->dist; + break; + case PLANE_Z: + dot = modelorg[2] - plane->dist; + break; + default: + dot = DotProduct (modelorg, plane->normal) - plane->dist; + break; + } + + if (dot >= 0) + side = 0; + else + side = 1; + + // recurse down the children, front side first + R_RecursiveWorldNode (node->children[side], clipflags); + + // draw stuff + c = node->numsurfaces; + + if (c) { + surf = r_worldentity.model->surfaces + node->firstsurface; + + if (dot < -BACKFACE_EPSILON) { + do { + if ((surf->flags & SURF_PLANEBACK) && + (surf->visframe == r_framecount)) { + if (r_drawpolys) { + if (r_worldpolysbacktofront) { + if (numbtofpolys < MAX_BTOFPOLYS) { + pbtofpolys[numbtofpolys].clipflags = + clipflags; + pbtofpolys[numbtofpolys].psurf = surf; + numbtofpolys++; + } + } else { + R_RenderPoly (surf, clipflags); + } + } else { + R_RenderFace (surf, clipflags); + } + } + + surf++; + } while (--c); + } else if (dot > BACKFACE_EPSILON) { + do { + if (!(surf->flags & SURF_PLANEBACK) && + (surf->visframe == r_framecount)) { + if (r_drawpolys) { + if (r_worldpolysbacktofront) { + if (numbtofpolys < MAX_BTOFPOLYS) { + pbtofpolys[numbtofpolys].clipflags = + clipflags; + pbtofpolys[numbtofpolys].psurf = surf; + numbtofpolys++; + } + } else { + R_RenderPoly (surf, clipflags); + } + } else { + R_RenderFace (surf, clipflags); + } + } + + surf++; + } while (--c); + } + // all surfaces on the same node share the same sequence number + r_currentkey++; + } + // recurse down the back side + R_RecursiveWorldNode (node->children[!side], clipflags); + } +} + +void +R_RenderWorld (void) +{ + int i; + model_t *clmodel; + btofpoly_t btofpolys[MAX_BTOFPOLYS]; + + pbtofpolys = btofpolys; + + currententity = &r_worldentity; + VectorCopy (r_origin, modelorg); + clmodel = currententity->model; + r_pcurrentvertbase = clmodel->vertexes; + + R_RecursiveWorldNode (clmodel->nodes, 15); + + // if the driver wants the polygons back to front, play the visible ones + // back in that order + if (r_worldpolysbacktofront) { + for (i = numbtofpolys - 1; i >= 0; i--) { + R_RenderPoly (btofpolys[i].psurf, btofpolys[i].clipflags); + } + } +} diff --git a/libs/video/renderer/sw32/sw32_rdraw.c b/libs/video/renderer/sw32/sw32_rdraw.c new file mode 100644 index 000000000..4f719a7bb --- /dev/null +++ b/libs/video/renderer/sw32/sw32_rdraw.c @@ -0,0 +1,796 @@ +/* + sw32_r_draw.c + + (description) + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/render.h" + +#include "r_local.h" + +#define MAXLEFTCLIPEDGES 100 + +// !!! if these are changed, they must be changed in asm_draw.h too !!! +#define FULLY_CLIPPED_CACHED 0x80000000 +#define FRAMECOUNT_MASK 0x7FFFFFFF + +unsigned int cacheoffset; + +int c_faceclip; // number of faces clipped + +zpointdesc_t r_zpointdesc; + +polydesc_t r_polydesc; + + + +clipplane_t *entity_clipplanes; +clipplane_t view_clipplanes[4]; +clipplane_t world_clipplanes[16]; + +medge_t *r_pedge; + +qboolean r_leftclipped, r_rightclipped; +static qboolean makeleftedge, makerightedge; +qboolean r_nearzionly; + +int sintable[SIN_BUFFER_SIZE]; +int intsintable[SIN_BUFFER_SIZE]; + +mvertex_t r_leftenter, r_leftexit; +mvertex_t r_rightenter, r_rightexit; + +typedef struct { + float u, v; + int ceilv; +} evert_t; + +int r_emitted; +float r_nearzi; +float r_u1, r_v1, r_lzi1; +int r_ceilv1; + +qboolean r_lastvertvalid; + + +void +R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) +{ + edge_t *edge, *pcheck; + int u_check; + float u, u_step; + vec3_t local, transformed; + float *world; + int v, v2, ceilv0; + float scale, lzi0, u0, v0; + int side; + + if (r_lastvertvalid) { + u0 = r_u1; + v0 = r_v1; + lzi0 = r_lzi1; + ceilv0 = r_ceilv1; + } else { + world = &pv0->position[0]; + + // transform and project + VectorSubtract (world, modelorg, local); + TransformVector (local, transformed); + + if (transformed[2] < NEAR_CLIP) + transformed[2] = NEAR_CLIP; + + lzi0 = 1.0 / transformed[2]; + + // FIXME: build x/yscale into transform? + scale = xscale * lzi0; + u0 = (xcenter + scale * transformed[0]); + if (u0 < r_refdef.fvrectx_adj) + u0 = r_refdef.fvrectx_adj; + if (u0 > r_refdef.fvrectright_adj) + u0 = r_refdef.fvrectright_adj; + + scale = yscale * lzi0; + v0 = (ycenter - scale * transformed[1]); + if (v0 < r_refdef.fvrecty_adj) + v0 = r_refdef.fvrecty_adj; + if (v0 > r_refdef.fvrectbottom_adj) + v0 = r_refdef.fvrectbottom_adj; + + ceilv0 = (int) ceil (v0); + } + + world = &pv1->position[0]; + + // transform and project + VectorSubtract (world, modelorg, local); + TransformVector (local, transformed); + + if (transformed[2] < NEAR_CLIP) + transformed[2] = NEAR_CLIP; + + r_lzi1 = 1.0 / transformed[2]; + + scale = xscale * r_lzi1; + r_u1 = (xcenter + scale * transformed[0]); + if (r_u1 < r_refdef.fvrectx_adj) + r_u1 = r_refdef.fvrectx_adj; + if (r_u1 > r_refdef.fvrectright_adj) + r_u1 = r_refdef.fvrectright_adj; + + scale = yscale * r_lzi1; + r_v1 = (ycenter - scale * transformed[1]); + if (r_v1 < r_refdef.fvrecty_adj) + r_v1 = r_refdef.fvrecty_adj; + if (r_v1 > r_refdef.fvrectbottom_adj) + r_v1 = r_refdef.fvrectbottom_adj; + + if (r_lzi1 > lzi0) + lzi0 = r_lzi1; + + if (lzi0 > r_nearzi) // for mipmap finding + r_nearzi = lzi0; + + // for right edges, all we want is the effect on 1/z + if (r_nearzionly) + return; + + r_emitted = 1; + + r_ceilv1 = (int) ceil (r_v1); + + + // create the edge + if (ceilv0 == r_ceilv1) { + // we cache unclipped horizontal edges as fully clipped + if (cacheoffset != 0x7FFFFFFF) { + cacheoffset = FULLY_CLIPPED_CACHED | + (r_framecount & FRAMECOUNT_MASK); + } + + return; // horizontal edge + } + + side = ceilv0 > r_ceilv1; + + edge = edge_p++; + + edge->owner = r_pedge; + + edge->nearzi = lzi0; + + if (side == 0) { + // trailing edge (go from p1 to p2) + v = ceilv0; + v2 = r_ceilv1 - 1; + + edge->surfs[0] = surface_p - surfaces; + edge->surfs[1] = 0; + + u_step = ((r_u1 - u0) / (r_v1 - v0)); + u = u0 + ((float) v - v0) * u_step; + } else { + // leading edge (go from p2 to p1) + v2 = ceilv0 - 1; + v = r_ceilv1; + + edge->surfs[0] = 0; + edge->surfs[1] = surface_p - surfaces; + + u_step = ((u0 - r_u1) / (v0 - r_v1)); + u = r_u1 + ((float) v - r_v1) * u_step; + } + + edge->u_step = u_step * 0x100000; + edge->u = u * 0x100000 + 0xFFFFF; + +// we need to do this to avoid stepping off the edges if a very nearly +// horizontal edge is less than epsilon above a scan, and numeric error causes +// it to incorrectly extend to the scan, and the extension of the line goes off +// the edge of the screen + // FIXME: is this actually needed? + if (edge->u < r_refdef.vrect_x_adj_shift20) + edge->u = r_refdef.vrect_x_adj_shift20; + if (edge->u > r_refdef.vrectright_adj_shift20) + edge->u = r_refdef.vrectright_adj_shift20; + + // sort the edge in normally + u_check = edge->u; + if (edge->surfs[0]) + u_check++; // sort trailers after leaders + + if (!newedges[v] || newedges[v]->u >= u_check) { + edge->next = newedges[v]; + newedges[v] = edge; + } else { + pcheck = newedges[v]; + while (pcheck->next && pcheck->next->u < u_check) + pcheck = pcheck->next; + edge->next = pcheck->next; + pcheck->next = edge; + } + + edge->nextremove = removeedges[v2]; + removeedges[v2] = edge; +} + +void +R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip) +{ + float d0, d1, f; + mvertex_t clipvert; + + if (clip) { + do { + d0 = DotProduct (pv0->position, clip->normal) - clip->dist; + d1 = DotProduct (pv1->position, clip->normal) - clip->dist; + + if (d0 >= 0) { + // point 0 is unclipped + if (d1 >= 0) { + // both points are unclipped + continue; + } + // only point 1 is clipped + + // we don't cache clipped edges + cacheoffset = 0x7FFFFFFF; + + f = d0 / (d0 - d1); + clipvert.position[0] = pv0->position[0] + + f * (pv1->position[0] - pv0->position[0]); + clipvert.position[1] = pv0->position[1] + + f * (pv1->position[1] - pv0->position[1]); + clipvert.position[2] = pv0->position[2] + + f * (pv1->position[2] - pv0->position[2]); + + if (clip->leftedge) { + r_leftclipped = true; + r_leftexit = clipvert; + } else if (clip->rightedge) { + r_rightclipped = true; + r_rightexit = clipvert; + } + + R_ClipEdge (pv0, &clipvert, clip->next); + return; + } else { + // point 0 is clipped + if (d1 < 0) { + // both points are clipped + // we do cache fully clipped edges + if (!r_leftclipped) + cacheoffset = FULLY_CLIPPED_CACHED | + (r_framecount & FRAMECOUNT_MASK); + return; + } + // only point 0 is clipped + r_lastvertvalid = false; + + // we don't cache partially clipped edges + cacheoffset = 0x7FFFFFFF; + + f = d0 / (d0 - d1); + clipvert.position[0] = pv0->position[0] + + f * (pv1->position[0] - pv0->position[0]); + clipvert.position[1] = pv0->position[1] + + f * (pv1->position[1] - pv0->position[1]); + clipvert.position[2] = pv0->position[2] + + f * (pv1->position[2] - pv0->position[2]); + + if (clip->leftedge) { + r_leftclipped = true; + r_leftenter = clipvert; + } else if (clip->rightedge) { + r_rightclipped = true; + r_rightenter = clipvert; + } + + R_ClipEdge (&clipvert, pv1, clip->next); + return; + } + } while ((clip = clip->next) != NULL); + } + // add the edge + R_EmitEdge (pv0, pv1); +} + +void +R_EmitCachedEdge (void) +{ + edge_t *pedge_t; + + pedge_t = (edge_t *) ((unsigned long) r_edges + r_pedge->cachededgeoffset); + + if (!pedge_t->surfs[0]) + pedge_t->surfs[0] = surface_p - surfaces; + else + pedge_t->surfs[1] = surface_p - surfaces; + + if (pedge_t->nearzi > r_nearzi) // for mipmap finding + r_nearzi = pedge_t->nearzi; + + r_emitted = 1; +} + +void +R_RenderFace (msurface_t *fa, int clipflags) +{ + int i, lindex; + unsigned int mask; + mplane_t *pplane; + float distinv; + vec3_t p_normal; + medge_t *pedges, tedge; + clipplane_t *pclip; + + // skip out if no more surfs + if ((surface_p) >= surf_max) { + r_outofsurfaces++; + return; + } + // ditto if not enough edges left, or switch to auxedges if possible + if ((edge_p + fa->numedges + 4) >= edge_max) { + r_outofedges += fa->numedges; + return; + } + + c_faceclip++; + + // set up clip planes + pclip = NULL; + + for (i = 3, mask = 0x08; i >= 0; i--, mask >>= 1) { + if (clipflags & mask) { + view_clipplanes[i].next = pclip; + pclip = &view_clipplanes[i]; + } + } + + // push the edges through + r_emitted = 0; + r_nearzi = 0; + r_nearzionly = false; + makeleftedge = makerightedge = false; + pedges = currententity->model->edges; + r_lastvertvalid = false; + + for (i = 0; i < fa->numedges; i++) { + lindex = currententity->model->surfedges[fa->firstedge + i]; + + if (lindex > 0) { + r_pedge = &pedges[lindex]; + + // if the edge is cached, we can just reuse the edge + if (!insubmodel) { + if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED) { + if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) == + r_framecount) { + r_lastvertvalid = false; + continue; + } + } else { + if ((((unsigned long) edge_p - (unsigned long) r_edges) > + r_pedge->cachededgeoffset) && + (((edge_t *) ((unsigned long) r_edges + + r_pedge->cachededgeoffset))->owner == + r_pedge)) { + R_EmitCachedEdge (); + r_lastvertvalid = false; + continue; + } + } + } + // assume it's cacheable + cacheoffset = (byte *) edge_p - (byte *) r_edges; + r_leftclipped = r_rightclipped = false; + R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[0]], + &r_pcurrentvertbase[r_pedge->v[1]], pclip); + r_pedge->cachededgeoffset = cacheoffset; + + if (r_leftclipped) + makeleftedge = true; + if (r_rightclipped) + makerightedge = true; + r_lastvertvalid = true; + } else { + lindex = -lindex; + r_pedge = &pedges[lindex]; + // if the edge is cached, we can just reuse the edge + if (!insubmodel) { + if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED) { + if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) == + r_framecount) { + r_lastvertvalid = false; + continue; + } + } else { + // it's cached if the cached edge is valid and is owned + // by this medge_t + if ((((unsigned long) edge_p - (unsigned long) r_edges) > + r_pedge->cachededgeoffset) && + (((edge_t *) ((unsigned long) r_edges + + r_pedge->cachededgeoffset))->owner == + r_pedge)) { + R_EmitCachedEdge (); + r_lastvertvalid = false; + continue; + } + } + } + // assume it's cacheable + cacheoffset = (byte *) edge_p - (byte *) r_edges; + r_leftclipped = r_rightclipped = false; + R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[1]], + &r_pcurrentvertbase[r_pedge->v[0]], pclip); + r_pedge->cachededgeoffset = cacheoffset; + + if (r_leftclipped) + makeleftedge = true; + if (r_rightclipped) + makerightedge = true; + r_lastvertvalid = true; + } + } + + // if there was a clip off the left edge, add that edge too + // FIXME: faster to do in screen space? + // FIXME: share clipped edges? + if (makeleftedge) { + r_pedge = &tedge; + r_lastvertvalid = false; + R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next); + } + // if there was a clip off the right edge, get the right r_nearzi + if (makerightedge) { + r_pedge = &tedge; + r_lastvertvalid = false; + r_nearzionly = true; + R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next); + } + // if no edges made it out, return without posting the surface + if (!r_emitted) + return; + + r_polycount++; + + surface_p->data = (void *) fa; + surface_p->nearzi = r_nearzi; + surface_p->flags = fa->flags; + surface_p->insubmodel = insubmodel; + surface_p->spanstate = 0; + surface_p->entity = currententity; + surface_p->key = r_currentkey++; + surface_p->spans = NULL; + + pplane = fa->plane; +// FIXME: cache this? + TransformVector (pplane->normal, p_normal); +// FIXME: cache this? + distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal)); + + surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv; + surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv; + surface_p->d_ziorigin = p_normal[2] * distinv - + xcenter * surface_p->d_zistepu - ycenter * surface_p->d_zistepv; + +//JDC VectorCopy (r_worldmodelorg, surface_p->modelorg); + surface_p++; +} + +void +R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf) +{ + int i; + unsigned int mask; + mplane_t *pplane; + float distinv; + vec3_t p_normal; + medge_t tedge; + clipplane_t *pclip; + + // skip out if no more surfs + if (surface_p >= surf_max) { + r_outofsurfaces++; + return; + } + // ditto if not enough edges left, or switch to auxedges if possible + if ((edge_p + psurf->numedges + 4) >= edge_max) { + r_outofedges += psurf->numedges; + return; + } + + c_faceclip++; + + // this is a dummy to give the caching mechanism someplace to write to + r_pedge = &tedge; + + // set up clip planes + pclip = NULL; + + for (i = 3, mask = 0x08; i >= 0; i--, mask >>= 1) { + if (r_clipflags & mask) { + view_clipplanes[i].next = pclip; + pclip = &view_clipplanes[i]; + } + } + + // push the edges through + r_emitted = 0; + r_nearzi = 0; + r_nearzionly = false; + makeleftedge = makerightedge = false; + // FIXME: keep clipped bmodel edges in clockwise order so last vertex + // caching can be used? + r_lastvertvalid = false; + + for (; pedges; pedges = pedges->pnext) { + r_leftclipped = r_rightclipped = false; + R_ClipEdge (pedges->v[0], pedges->v[1], pclip); + + if (r_leftclipped) + makeleftedge = true; + if (r_rightclipped) + makerightedge = true; + } + + // if there was a clip off the left edge, add that edge too + // FIXME: faster to do in screen space? + // FIXME: share clipped edges? + if (makeleftedge) { + r_pedge = &tedge; + R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next); + } + // if there was a clip off the right edge, get the right r_nearzi + if (makerightedge) { + r_pedge = &tedge; + r_nearzionly = true; + R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next); + } + // if no edges made it out, return without posting the surface + if (!r_emitted) + return; + + r_polycount++; + + surface_p->data = (void *) psurf; + surface_p->nearzi = r_nearzi; + surface_p->flags = psurf->flags; + surface_p->insubmodel = true; + surface_p->spanstate = 0; + surface_p->entity = currententity; + surface_p->key = r_currentbkey; + surface_p->spans = NULL; + + pplane = psurf->plane; +// FIXME: cache this? + TransformVector (pplane->normal, p_normal); +// FIXME: cache this? + distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal)); + + surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv; + surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv; + surface_p->d_ziorigin = p_normal[2] * distinv - + xcenter * surface_p->d_zistepu - ycenter * surface_p->d_zistepv; + +//JDC VectorCopy (r_worldmodelorg, surface_p->modelorg); + surface_p++; +} + +void +R_RenderPoly (msurface_t *fa, int clipflags) +{ + int i, lindex, lnumverts, s_axis, t_axis; + float dist, lastdist, lzi, scale, u, v, frac; + unsigned int mask; + vec3_t local, transformed; + clipplane_t *pclip; + medge_t *pedges; + mplane_t *pplane; + mvertex_t verts[2][100]; // FIXME: do real number + polyvert_t pverts[100]; // FIXME: do real number, safely + int vertpage, newverts, newpage, lastvert; + qboolean visible; + + // FIXME: clean this up and make it faster + // FIXME: guard against running out of vertices + + s_axis = t_axis = 0; // keep compiler happy + + // set up clip planes + pclip = NULL; + + for (i = 3, mask = 0x08; i >= 0; i--, mask >>= 1) { + if (clipflags & mask) { + view_clipplanes[i].next = pclip; + pclip = &view_clipplanes[i]; + } + } + + // reconstruct the polygon + // FIXME: these should be precalculated and loaded off disk + pedges = currententity->model->edges; + lnumverts = fa->numedges; + vertpage = 0; + + for (i = 0; i < lnumverts; i++) { + lindex = currententity->model->surfedges[fa->firstedge + i]; + + if (lindex > 0) { + r_pedge = &pedges[lindex]; + verts[0][i] = r_pcurrentvertbase[r_pedge->v[0]]; + } else { + r_pedge = &pedges[-lindex]; + verts[0][i] = r_pcurrentvertbase[r_pedge->v[1]]; + } + } + + // clip the polygon, done if not visible + while (pclip) { + lastvert = lnumverts - 1; + lastdist = DotProduct (verts[vertpage][lastvert].position, + pclip->normal) - pclip->dist; + + visible = false; + newverts = 0; + newpage = vertpage ^ 1; + + for (i = 0; i < lnumverts; i++) { + dist = DotProduct (verts[vertpage][i].position, pclip->normal) - + pclip->dist; + + if ((lastdist > 0) != (dist > 0)) { + frac = dist / (dist - lastdist); + verts[newpage][newverts].position[0] = + verts[vertpage][i].position[0] + + ((verts[vertpage][lastvert].position[0] - + verts[vertpage][i].position[0]) * frac); + verts[newpage][newverts].position[1] = + verts[vertpage][i].position[1] + + ((verts[vertpage][lastvert].position[1] - + verts[vertpage][i].position[1]) * frac); + verts[newpage][newverts].position[2] = + verts[vertpage][i].position[2] + + ((verts[vertpage][lastvert].position[2] - + verts[vertpage][i].position[2]) * frac); + newverts++; + } + + if (dist >= 0) { + verts[newpage][newverts] = verts[vertpage][i]; + newverts++; + visible = true; + } + + lastvert = i; + lastdist = dist; + } + + if (!visible || (newverts < 3)) + return; + + lnumverts = newverts; + vertpage ^= 1; + pclip = pclip->next; + } + + // transform and project, remembering the z values at the vertices and + // r_nearzi, and extract the s and t coordinates at the vertices + pplane = fa->plane; + switch (pplane->type) { + case PLANE_X: + case PLANE_ANYX: + s_axis = 1; + t_axis = 2; + break; + case PLANE_Y: + case PLANE_ANYY: + s_axis = 0; + t_axis = 2; + break; + case PLANE_Z: + case PLANE_ANYZ: + s_axis = 0; + t_axis = 1; + break; + } + + r_nearzi = 0; + + for (i = 0; i < lnumverts; i++) { + // transform and project + VectorSubtract (verts[vertpage][i].position, modelorg, local); + TransformVector (local, transformed); + + if (transformed[2] < NEAR_CLIP) + transformed[2] = NEAR_CLIP; + + lzi = 1.0 / transformed[2]; + + if (lzi > r_nearzi) // for mipmap finding + r_nearzi = lzi; + + // FIXME: build x/yscale into transform? + scale = xscale * lzi; + u = (xcenter + scale * transformed[0]); + if (u < r_refdef.fvrectx_adj) + u = r_refdef.fvrectx_adj; + if (u > r_refdef.fvrectright_adj) + u = r_refdef.fvrectright_adj; + + scale = yscale * lzi; + v = (ycenter - scale * transformed[1]); + if (v < r_refdef.fvrecty_adj) + v = r_refdef.fvrecty_adj; + if (v > r_refdef.fvrectbottom_adj) + v = r_refdef.fvrectbottom_adj; + + pverts[i].u = u; + pverts[i].v = v; + pverts[i].zi = lzi; + pverts[i].s = verts[vertpage][i].position[s_axis]; + pverts[i].t = verts[vertpage][i].position[t_axis]; + } + + // build the polygon descriptor, including fa, r_nearzi, and u, v, s, t, + // and z for each vertex + r_polydesc.numverts = lnumverts; + r_polydesc.nearzi = r_nearzi; + r_polydesc.pcurrentface = fa; + r_polydesc.pverts = pverts; + + // draw the polygon + D_DrawPoly (); +} + +void +R_ZDrawSubmodelPolys (model_t *pmodel) +{ + int i, numsurfaces; + msurface_t *psurf; + float dot; + mplane_t *pplane; + + psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; + numsurfaces = pmodel->nummodelsurfaces; + + for (i = 0; i < numsurfaces; i++, psurf++) { + // find which side of the node we are on + pplane = psurf->plane; + + dot = DotProduct (modelorg, pplane->normal) - pplane->dist; + + // draw the polygon + if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || + (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { + // FIXME: use bounding-box-based frustum clipping info? + R_RenderPoly (psurf, 15); + } + } +} diff --git a/libs/video/renderer/sw32/sw32_redge.c b/libs/video/renderer/sw32/sw32_redge.c new file mode 100644 index 000000000..903e9bd32 --- /dev/null +++ b/libs/video/renderer/sw32/sw32_redge.c @@ -0,0 +1,665 @@ +/* + sw32_redge.c + + (description) + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/render.h" +#include "QF/sound.h" + +#include "d_ifacea.h" +#include "r_local.h" + +/* + FIXME + the complex cases add new polys on most lines, + so dont optimize for keeping them the same have multiple free span lists to + try to get better coherence ? low depth complexity-- 1 to 3 or so this + breaks spans at every edge, even hidden ones (bad) + have a sentinal at both ends ? +*/ + +edge_t *auxedges; +edge_t *r_edges, *edge_p, *edge_max; + +surf_t *surfaces, *surface_p, *surf_max; + +/* + surfaces are generated in back to front order by the bsp, so if a surf + pointer is greater than another one, it should be drawn in front + surfaces[1] is the background, and is used as the active surface stack +*/ + +edge_t *newedges[MAXHEIGHT]; +edge_t *removeedges[MAXHEIGHT]; + +espan_t *span_p, *max_span_p; + +int r_currentkey; + +extern int screenwidth; + +int current_iv; + +int edge_head_u_shift20, edge_tail_u_shift20; + +static void (*pdrawfunc) (void); + +edge_t edge_head; +edge_t edge_tail; +edge_t edge_aftertail; +edge_t edge_sentinel; + +float fv; + +void +R_GenerateSpans (void); +void +R_GenerateSpansBackward (void); + +void +R_LeadingEdge (edge_t *edge); +void +R_LeadingEdgeBackwards (edge_t *edge); +void +R_TrailingEdge (surf_t *surf, edge_t *edge); + + +void +R_DrawCulledPolys (void) +{ + surf_t *s; + msurface_t *pface; + + currententity = &r_worldentity; + + if (r_worldpolysbacktofront) { + for (s = surface_p - 1; s > &surfaces[1]; s--) { + if (!s->spans) + continue; + + if (!(s->flags & SURF_DRAWBACKGROUND)) { + pface = (msurface_t *) s->data; + R_RenderPoly (pface, 15); + } + } + } else { + for (s = &surfaces[1]; s < surface_p; s++) { + if (!s->spans) + continue; + + if (!(s->flags & SURF_DRAWBACKGROUND)) { + pface = (msurface_t *) s->data; + R_RenderPoly (pface, 15); + } + } + } +} + +void +R_BeginEdgeFrame (void) +{ + int v; + + edge_p = r_edges; + edge_max = &r_edges[r_numallocatededges]; + + surface_p = &surfaces[2]; // background is surface 1, + // surface 0 is a dummy + surfaces[1].spans = NULL; // no background spans yet + surfaces[1].flags = SURF_DRAWBACKGROUND; + + // put the background behind everything in the world +/* + if (r_draworder->int_val) { + pdrawfunc = R_GenerateSpansBackward; + surfaces[1].key = 0; + r_currentkey = 1; + } else { +*/ + pdrawfunc = R_GenerateSpans; + surfaces[1].key = 0x7FFFFFFF; + r_currentkey = 0; +// } + + // FIXME: set with memset + for (v = r_refdef.vrect.y; v < r_refdef.vrectbottom; v++) { + newedges[v] = removeedges[v] = NULL; + } +} + +/* + R_InsertNewEdges + + Adds the edges in the linked list edgestoadd, adding them to the edges + in the linked list edgelist. edgestoadd is assumed to be sorted on u, + and non-empty (this is actually newedges[v]). edgelist is assumed to + be sorted on u, with a sentinel at the end (actually, this is the + active edge table starting at edge_head.next). +*/ +void +R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist) +{ + edge_t *next_edge; + + do { + next_edge = edgestoadd->next; + edgesearch: + if (edgelist->u >= edgestoadd->u) + goto addedge; + edgelist = edgelist->next; + if (edgelist->u >= edgestoadd->u) + goto addedge; + edgelist = edgelist->next; + if (edgelist->u >= edgestoadd->u) + goto addedge; + edgelist = edgelist->next; + if (edgelist->u >= edgestoadd->u) + goto addedge; + edgelist = edgelist->next; + goto edgesearch; + + // insert edgestoadd before edgelist + addedge: + edgestoadd->next = edgelist; + edgestoadd->prev = edgelist->prev; + edgelist->prev->next = edgestoadd; + edgelist->prev = edgestoadd; + } while ((edgestoadd = next_edge) != NULL); +} + +void +R_RemoveEdges (edge_t *pedge) +{ + + do { + pedge->next->prev = pedge->prev; + pedge->prev->next = pedge->next; + } while ((pedge = pedge->nextremove) != NULL); +} + +void +R_StepActiveU (edge_t *pedge) +{ + edge_t *pnext_edge, *pwedge; + + while (1) { + nextedge: + pedge->u += pedge->u_step; + if (pedge->u < pedge->prev->u) + goto pushback; + pedge = pedge->next; + + pedge->u += pedge->u_step; + if (pedge->u < pedge->prev->u) + goto pushback; + pedge = pedge->next; + + pedge->u += pedge->u_step; + if (pedge->u < pedge->prev->u) + goto pushback; + pedge = pedge->next; + + pedge->u += pedge->u_step; + if (pedge->u < pedge->prev->u) + goto pushback; + pedge = pedge->next; + + goto nextedge; + + pushback: + if (pedge == &edge_aftertail) + return; + + // push it back to keep it sorted + pnext_edge = pedge->next; + + // pull the edge out of the edge list + pedge->next->prev = pedge->prev; + pedge->prev->next = pedge->next; + + // find out where the edge goes in the edge list + pwedge = pedge->prev->prev; + + while (pwedge->u > pedge->u) { + pwedge = pwedge->prev; + } + + // put the edge back into the edge list + pedge->next = pwedge->next; + pedge->prev = pwedge; + pedge->next->prev = pedge; + pwedge->next = pedge; + + pedge = pnext_edge; + if (pedge == &edge_tail) + return; + } +} + +void +R_CleanupSpan (void) +{ + surf_t *surf; + int iu; + espan_t *span; + + // now that we've reached the right edge of the screen, we're done with any + // unfinished surfaces, so emit a span for whatever's on top + surf = surfaces[1].next; + iu = edge_tail_u_shift20; + if (iu > surf->last_u) { + span = span_p++; + span->u = surf->last_u; + span->count = iu - span->u; + span->v = current_iv; + span->pnext = surf->spans; + surf->spans = span; + } + // reset spanstate for all surfaces in the surface stack + do { + surf->spanstate = 0; + surf = surf->next; + } while (surf != &surfaces[1]); +} + +void +R_LeadingEdgeBackwards (edge_t *edge) +{ + espan_t *span; + surf_t *surf, *surf2; + int iu; + + // it's adding a new surface in, so find the correct place + surf = &surfaces[edge->surfs[1]]; + + // don't start a span if this is an inverted span, with the end edge + // preceding the start edge (that is, we've already seen the end edge) + if (++surf->spanstate == 1) { + surf2 = surfaces[1].next; + + if (surf->key > surf2->key) + goto newtop; + + // if it's two surfaces on the same plane, the one that's already + // active is in front, so keep going unless it's a bmodel + if (surf->insubmodel && (surf->key == surf2->key)) { + // must be two bmodels in the same leaf; don't care, because + // they'll never be farthest anyway + goto newtop; + } + + continue_search: + + do { + surf2 = surf2->next; + } while (surf->key < surf2->key); + + if (surf->key == surf2->key) { + // if it's two surfaces on the same plane, the one that's already + // active is in front, so keep going unless it's a bmodel + if (!surf->insubmodel) + goto continue_search; + + // must be two bmodels in the same leaf; don't care which is + // really in front, because they'll never be farthest anyway + } + + goto gotposition; + + newtop: + // emit a span (obscures current top) + iu = edge->u >> 20; + + if (iu > surf2->last_u) { + span = span_p++; + span->u = surf2->last_u; + span->count = iu - span->u; + span->v = current_iv; + span->pnext = surf2->spans; + surf2->spans = span; + } + // set last_u on the new span + surf->last_u = iu; + + gotposition: + // insert before surf2 + surf->next = surf2; + surf->prev = surf2->prev; + surf2->prev->next = surf; + surf2->prev = surf; + } +} + +void +R_TrailingEdge (surf_t *surf, edge_t *edge) +{ + espan_t *span; + int iu; + + // don't generate a span if this is an inverted span, with the end edge + // preceding the start edge (that is, we haven't seen the start edge yet) + if (--surf->spanstate == 0) { + if (surf->insubmodel) + r_bmodelactive--; + + if (surf == surfaces[1].next) { + // emit a span (current top going away) + iu = edge->u >> 20; + if (iu > surf->last_u) { + span = span_p++; + span->u = surf->last_u; + span->count = iu - span->u; + span->v = current_iv; + span->pnext = surf->spans; + surf->spans = span; + } + // set last_u on the surface below + surf->next->last_u = iu; + } + + surf->prev->next = surf->next; + surf->next->prev = surf->prev; + } +} + +void +R_LeadingEdge (edge_t *edge) +{ + espan_t *span; + surf_t *surf, *surf2; + int iu; + double fu, newzi, testzi, newzitop, newzibottom; + + if (edge->surfs[1]) { + // it's adding a new surface in, so find the correct place + surf = &surfaces[edge->surfs[1]]; + + // don't start a span if this is an inverted span, with the end edge + // preceding the start edge (that is, we've already seen the end edge) + if (++surf->spanstate == 1) { + if (surf->insubmodel) + r_bmodelactive++; + + surf2 = surfaces[1].next; + + if (surf->key < surf2->key) + goto newtop; + + // if it's two surfaces on the same plane, the one that's already + // active is in front, so keep going unless it's a bmodel + if (surf->insubmodel && (surf->key == surf2->key)) { + // must be two bmodels in the same leaf; sort on 1/z + fu = (float) (edge->u - 0xFFFFF) * (1.0 / 0x100000); + newzi = surf->d_ziorigin + fv * surf->d_zistepv + + fu * surf->d_zistepu; + newzibottom = newzi * 0.99; + + testzi = surf2->d_ziorigin + fv * surf2->d_zistepv + + fu * surf2->d_zistepu; + + if (newzibottom >= testzi) { + goto newtop; + } + + newzitop = newzi * 1.01; + if (newzitop >= testzi) { + if (surf->d_zistepu >= surf2->d_zistepu) { + goto newtop; + } + } + } + + continue_search: + + do { + surf2 = surf2->next; + } while (surf->key > surf2->key); + + if (surf->key == surf2->key) { + // if it's two surfaces on the same plane, the already active + // one is in front, so keep going unless it's abmodel + if (!surf->insubmodel) + goto continue_search; + + // must be two bmodels in the same leaf; sort on 1/z + fu = (float) (edge->u - 0xFFFFF) * (1.0 / 0x100000); + newzi = surf->d_ziorigin + fv * surf->d_zistepv + + fu * surf->d_zistepu; + newzibottom = newzi * 0.99; + + testzi = surf2->d_ziorigin + fv * surf2->d_zistepv + + fu * surf2->d_zistepu; + + if (newzibottom >= testzi) { + goto gotposition; + } + + newzitop = newzi * 1.01; + if (newzitop >= testzi) { + if (surf->d_zistepu >= surf2->d_zistepu) { + goto gotposition; + } + } + + goto continue_search; + } + + goto gotposition; + + newtop: + // emit a span (obscures current top) + iu = edge->u >> 20; + + if (iu > surf2->last_u) { + span = span_p++; + span->u = surf2->last_u; + span->count = iu - span->u; + span->v = current_iv; + span->pnext = surf2->spans; + surf2->spans = span; + } + // set last_u on the new span + surf->last_u = iu; + + gotposition: + // insert before surf2 + surf->next = surf2; + surf->prev = surf2->prev; + surf2->prev->next = surf; + surf2->prev = surf; + } + } +} + +void +R_GenerateSpans (void) +{ + edge_t *edge; + surf_t *surf; + + r_bmodelactive = 0; + + // clear active surfaces to just the background surface + surfaces[1].next = surfaces[1].prev = &surfaces[1]; + surfaces[1].last_u = edge_head_u_shift20; + + // generate spans + for (edge = edge_head.next; edge != &edge_tail; edge = edge->next) { + if (edge->surfs[0]) { + // it has a left surface, so a surface is going away for this span + surf = &surfaces[edge->surfs[0]]; + + R_TrailingEdge (surf, edge); + + if (!edge->surfs[1]) + continue; + } + + R_LeadingEdge (edge); + } + + R_CleanupSpan (); +} + +void +R_GenerateSpansBackward (void) +{ + edge_t *edge; + + r_bmodelactive = 0; + + // clear active surfaces to just the background surface + surfaces[1].next = surfaces[1].prev = &surfaces[1]; + surfaces[1].last_u = edge_head_u_shift20; + + // generate spans + for (edge = edge_head.next; edge != &edge_tail; edge = edge->next) { + if (edge->surfs[0]) + R_TrailingEdge (&surfaces[edge->surfs[0]], edge); + + if (edge->surfs[1]) + R_LeadingEdgeBackwards (edge); + } + + R_CleanupSpan (); +} + +/* + R_ScanEdges + + Input: + newedges[] array + this has links to edges, which have links to surfaces + + Output: + Each surface has a linked list of its visible spans +*/ +void +R_ScanEdges (void) +{ + int iv, bottom; + byte basespans[MAXSPANS * sizeof (espan_t) + CACHE_SIZE]; + espan_t *basespan_p; + surf_t *s; + + basespan_p = (espan_t *) + ((long) (basespans + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); + max_span_p = &basespan_p[MAXSPANS - r_refdef.vrect.width]; + + span_p = basespan_p; + + // clear active edges to just the background edges around the whole screen + // FIXME: most of this only needs to be set up once + edge_head.u = r_refdef.vrect.x << 20; + edge_head_u_shift20 = edge_head.u >> 20; + edge_head.u_step = 0; + edge_head.prev = NULL; + edge_head.next = &edge_tail; + edge_head.surfs[0] = 0; + edge_head.surfs[1] = 1; + + edge_tail.u = (r_refdef.vrectright << 20) + 0xFFFFF; + edge_tail_u_shift20 = edge_tail.u >> 20; + edge_tail.u_step = 0; + edge_tail.prev = &edge_head; + edge_tail.next = &edge_aftertail; + edge_tail.surfs[0] = 1; + edge_tail.surfs[1] = 0; + + edge_aftertail.u = -1; // force a move + edge_aftertail.u_step = 0; + edge_aftertail.next = &edge_sentinel; + edge_aftertail.prev = &edge_tail; + + // FIXME: do we need this now that we clamp x in r_draw.c? + edge_sentinel.u = 2000 << 24; // make sure nothing sorts past this + edge_sentinel.prev = &edge_aftertail; + + // process all scan lines + bottom = r_refdef.vrectbottom - 1; + + for (iv = r_refdef.vrect.y; iv < bottom; iv++) { + current_iv = iv; + fv = (float) iv; + + // mark that the head (background start) span is pre-included + surfaces[1].spanstate = 1; + + if (newedges[iv]) { + R_InsertNewEdges (newedges[iv], edge_head.next); + } + + (*pdrawfunc) (); + + // flush the span list if we can't be sure we have enough spans left + // for the next scan + if (span_p > max_span_p) { + VID_UnlockBuffer (); + S_ExtraUpdate (); // don't let sound get messed up if + // going slow + VID_LockBuffer (); + + if (r_drawculledpolys) + R_DrawCulledPolys (); + else + D_DrawSurfaces (); + + // clear the surface span pointers + for (s = &surfaces[1]; s < surface_p; s++) + s->spans = NULL; + + span_p = basespan_p; + } + + if (removeedges[iv]) + R_RemoveEdges (removeedges[iv]); + + if (edge_head.next != &edge_tail) + R_StepActiveU (edge_head.next); + } + + // do the last scan (no need to step or sort or remove on the last scan) + current_iv = iv; + fv = (float) iv; + + // mark that the head (background start) span is pre-included + surfaces[1].spanstate = 1; + + if (newedges[iv]) + R_InsertNewEdges (newedges[iv], edge_head.next); + + (*pdrawfunc) (); + + // draw whatever's left in the span list + if (r_drawculledpolys) + R_DrawCulledPolys (); + else + D_DrawSurfaces (); +} diff --git a/libs/video/renderer/sw32/sw32_rlight.c b/libs/video/renderer/sw32/sw32_rlight.c new file mode 100644 index 000000000..299055842 --- /dev/null +++ b/libs/video/renderer/sw32/sw32_rlight.c @@ -0,0 +1,313 @@ +/* + sw32_rlight.c + + (description) + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/render.h" + +#include "r_local.h" + +//int r_dlightframecount; + + +void +R_AnimateLight (void) +{ + int i, j, k; + + // light animations + // 'm' is normal light, 'a' is no light, 'z' is double bright + i = (int) (r_realtime * 10); + for (j = 0; j < MAX_LIGHTSTYLES; j++) { + if (!r_lightstyle[j].length) { + d_lightstylevalue[j] = 256; + continue; + } + k = i % r_lightstyle[j].length; + k = r_lightstyle[j].map[k] - 'a'; + k = k * 22; + d_lightstylevalue[j] = k; + } +} + +/* + DYNAMIC LIGHTS +*/ + +static void +mark_surfaces (msurface_t *surf, vec3_t lightorigin, dlight_t *light, + int bit) +{ + float dist; +#if 1 + float dist2, d; + float maxdist = light->radius * light->radius; + vec3_t impact; +#endif + + dist = PlaneDiff(lightorigin, surf->plane); + if (surf->flags & SURF_PLANEBACK) + dist = -dist; + if ((dist < -0.25f && !(surf->flags & SURF_LIGHTBOTHSIDES)) + || dist > light->radius) + return; +#if 1 + dist2 = dist * dist; + dist = -dist; + VectorMA (light->origin, dist, surf->plane->normal, impact); + + d = DotProduct (impact, surf->texinfo->vecs[0]) + + surf->texinfo->vecs[0][3] - surf->texturemins[0]; + if (d < 0) { + dist2 += d * d; + if (dist2 >= maxdist) + return; + } else { + d -= surf->extents[0] + 16; + if (d > 0) { + dist2 += d * d; + if (dist2 >= maxdist) + return; + } + } + d = DotProduct (impact, surf->texinfo->vecs[1]) + + surf->texinfo->vecs[1][3] - surf->texturemins[1]; + if (d < 0) { + dist2 += d * d; + if (dist2 >= maxdist) + return; + } else { + d -= surf->extents[1] + 16; + if (d > 0) { + dist2 += d * d; + if (dist2 >= maxdist) + return; + } + } +#endif + if (surf->dlightframe != r_framecount) { + surf->dlightbits = 0; + surf->dlightframe = r_framecount; + } + surf->dlightbits |= bit; +} + + +void +R_MarkLights (vec3_t lightorigin, dlight_t *light, int bit, model_t *model) +{ + mleaf_t *pvsleaf = Mod_PointInLeaf (lightorigin, model); + + if (!pvsleaf->compressed_vis) { + mnode_t *node = model->nodes + model->hulls[0].firstclipnode; + R_RecursiveMarkLights (lightorigin, light, bit, node); + } else { + float radius = light->radius; + vec3_t mins, maxs; + int leafnum = 0; + byte *in = pvsleaf->compressed_vis; + byte vis_bits; + + mins[0] = lightorigin[0] - radius; + mins[1] = lightorigin[1] - radius; + mins[2] = lightorigin[2] - radius; + maxs[0] = lightorigin[0] + radius; + maxs[1] = lightorigin[1] + radius; + maxs[2] = lightorigin[2] + radius; + while (leafnum < model->numleafs) { + int i; + if (!(vis_bits = *in++)) { + leafnum += (*in++) * 8; + continue; + } + for (i = 0; i < 8 && leafnum < model->numleafs; i++, leafnum++) { + int m; + mleaf_t *leaf = &model->leafs[leafnum + 1]; + if (!(vis_bits & (1 << i))) + continue; + if (leaf->visframe != r_visframecount) + continue; + if (leaf->mins[0] > maxs[0] || leaf->maxs[0] < mins[0] + || leaf->mins[1] > maxs[1] || leaf->maxs[1] < mins[1] + || leaf->mins[2] > maxs[2] || leaf->maxs[2] < mins[2]) + continue; + if (leaf->dlightframe != r_framecount) { + leaf->dlightbits = 0; + leaf->dlightframe = r_framecount; + } + leaf->dlightbits |= bit; + for (m = 0; m < leaf->nummarksurfaces; m++) { + msurface_t *surf = leaf->firstmarksurface[m]; + if (surf->visframe != r_visframecount) + continue; + mark_surfaces (surf, lightorigin, light, bit); + } + } + } + } +} + +void +R_PushDlights (vec3_t entorigin) +{ + int i; + dlight_t *l; + vec3_t lightorigin; + + l = r_dlights; + + for (i = 0; i < MAX_DLIGHTS; i++, l++) { + if (l->die < r_realtime || !l->radius) + continue; + VectorSubtract (l->origin, entorigin, lightorigin); + R_MarkLights (lightorigin, l, 1 << i, r_worldentity.model); + } +} + +/* + LIGHT SAMPLING +*/ + +int +RecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end) +{ + int r; + float front, back, frac; + int side; + mplane_t *plane; + vec3_t mid; + msurface_t *surf; + int s, t, ds, dt; + int i; + mtexinfo_t *tex; + byte *lightmap; + unsigned int scale; + int maps; + + if (node->contents < 0) + return -1; // didn't hit anything + + // calculate mid point + // FIXME: optimize for axial + plane = node->plane; + front = DotProduct (start, plane->normal) - plane->dist; + back = DotProduct (end, plane->normal) - plane->dist; + side = front < 0; + + if ((back < 0) == side) + return RecursiveLightPoint (node->children[side], start, end); + + frac = front / (front - back); + mid[0] = start[0] + (end[0] - start[0]) * frac; + mid[1] = start[1] + (end[1] - start[1]) * frac; + mid[2] = start[2] + (end[2] - start[2]) * frac; + + // go down front side + r = RecursiveLightPoint (node->children[side], start, mid); + if (r >= 0) + return r; // hit something + + if ((back < 0) == side) + return -1; // didn't hit anything + + // check for impact on this node + + surf = r_worldentity.model->surfaces + node->firstsurface; + for (i = 0; i < node->numsurfaces; i++, surf++) { + if (surf->flags & SURF_DRAWTILED) + continue; // no lightmaps + + tex = surf->texinfo; + + s = DotProduct (mid, tex->vecs[0]) + tex->vecs[0][3]; + t = DotProduct (mid, tex->vecs[1]) + tex->vecs[1][3];; + + if (s < surf->texturemins[0] || t < surf->texturemins[1]) + continue; + + ds = s - surf->texturemins[0]; + dt = t - surf->texturemins[1]; + + if (ds > surf->extents[0] || dt > surf->extents[1]) + continue; + + if (!surf->samples) + return 0; + + ds >>= 4; + dt >>= 4; + + lightmap = surf->samples; + r = 0; + if (lightmap) { + + lightmap += dt * ((surf->extents[0] >> 4) + 1) + ds; + + for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; + maps++) { + scale = d_lightstylevalue[surf->styles[maps]]; + r += *lightmap * scale; + lightmap += ((surf->extents[0] >> 4) + 1) * + ((surf->extents[1] >> 4) + 1); + } + + r >>= 8; + } + + return r; + } + + // go down back side + return RecursiveLightPoint (node->children[!side], mid, end); +} + +int +R_LightPoint (vec3_t p) +{ + vec3_t end; + int r; + + if (!r_worldentity.model->lightdata) + return 255; + + end[0] = p[0]; + end[1] = p[1]; + end[2] = p[2] - 2048; + + r = RecursiveLightPoint (r_worldentity.model->nodes, p, end); + + if (r == -1) + r = 0; + + if (r < r_refdef.ambientlight) + r = r_refdef.ambientlight; + + return r; +} diff --git a/libs/video/renderer/sw32/sw32_rmain.c b/libs/video/renderer/sw32/sw32_rmain.c new file mode 100644 index 000000000..7db30dfd2 --- /dev/null +++ b/libs/video/renderer/sw32/sw32_rmain.c @@ -0,0 +1,997 @@ +/* + sw32_rmain.c + + (description) + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include + +#include "QF/cmd.h" +#include "QF/console.h" +#include "QF/cvar.h" +#include "QF/locs.h" +#include "QF/mathlib.h" +#include "QF/render.h" +#include "QF/screen.h" +#include "QF/sound.h" +#include "QF/sys.h" + +//#include "d_iface.h" +#include "r_cvar.h" +#include "r_dynamic.h" +#include "r_local.h" +#include "view.h" + +//define PASSAGES + +void *colormap; +vec3_t viewlightvec; +alight_t r_viewlighting = { 128, 192, viewlightvec }; +float r_time1; +int r_numallocatededges; +qboolean r_drawpolys; +qboolean r_drawculledpolys; +qboolean r_worldpolysbacktofront; +int r_pixbytes = 1; +float r_aliasuvscale = 1.0; +int r_outofsurfaces; +int r_outofedges; + +qboolean r_dowarp, r_dowarpold, r_viewchanged; + +int numbtofpolys; +btofpoly_t *pbtofpolys; +mvertex_t *r_pcurrentvertbase; + +int c_surf; +int r_maxsurfsseen, r_maxedgesseen, r_cnumsurfs; +qboolean r_surfsonstack; +int r_clipflags; + +byte *r_warpbuffer; + +byte *r_stack_start; + +qboolean r_fov_greater_than_90; + +entity_t r_worldentity; + +mplane_t frustum[4]; + +// view origin +vec3_t vup, base_vup; +vec3_t vpn, base_vpn; +vec3_t vright, base_vright; +vec3_t r_origin; + +// screen size info +refdef_t r_refdef; +float xcenter, ycenter; +float xscale, yscale; +float xscaleinv, yscaleinv; +float xscaleshrink, yscaleshrink; +float aliasxscale, aliasyscale, aliasxcenter, aliasycenter; + +int screenwidth; + +float pixelAspect; +float screenAspect; +float verticalFieldOfView; +float xOrigin, yOrigin; + +mplane_t screenedge[4]; + +// refresh flags +int r_framecount = 1; // so frame counts initialized to 0 don't match +int r_visframecount; +int d_spanpixcount; +int r_polycount; +int r_drawnpolycount; +int r_wholepolycount; + +int *pfrustum_indexes[4]; +int r_frustum_indexes[4 * 6]; + +int reinit_surfcache = 1; // if 1, surface cache is currently empty + // and must be reinitialized for current + // cache size + +mleaf_t *r_viewleaf, *r_oldviewleaf; + +float r_aliastransition, r_resfudge; + +int d_lightstylevalue[256]; // 8.8 fraction of base light value + +float dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2; +float se_time1, se_time2, de_time1, de_time2, dv_time1, dv_time2; + +void R_MarkLeaves (void); + +void CreatePassages (void); +void SetVisibilityByPassages (void); + +void R_NetGraph (void); +void R_ZGraph (void); + +cvar_t *r_draworder; + +extern cvar_t *scr_fov; + + +void R_LoadSky_f (void); + +void +R_Textures_Init (void) +{ + int x, y, m; + byte *dest; + + // create a simple checkerboard texture for the default + r_notexture_mip = + Hunk_AllocName (sizeof (texture_t) + 16 * 16 + 8 * 8 + 4 * 4 + 2 * 2, + "notexture"); + + r_notexture_mip->width = r_notexture_mip->height = 16; + r_notexture_mip->offsets[0] = sizeof (texture_t); + + r_notexture_mip->offsets[1] = r_notexture_mip->offsets[0] + 16 * 16; + r_notexture_mip->offsets[2] = r_notexture_mip->offsets[1] + 8 * 8; + r_notexture_mip->offsets[3] = r_notexture_mip->offsets[2] + 4 * 4; + + for (m = 0; m < 4; m++) { + dest = (byte *) r_notexture_mip + r_notexture_mip->offsets[m]; + for (y = 0; y < (16 >> m); y++) + for (x = 0; x < (16 >> m); x++) { + if ((y < (8 >> m)) ^ (x < (8 >> m))) + *dest++ = 0; + else + *dest++ = 0xff; + } + } +} + +void +R_Init (void) +{ + int dummy; + +// allowskybox = false; // server decides this --KB + + // get stack position so we can guess if we are going to overflow + r_stack_start = (byte *) & dummy; + + R_InitTurb (); + + Cmd_AddCommand ("timerefresh", R_TimeRefresh_f, "Tests the current " + "refresh rate for the current location"); + Cmd_AddCommand ("pointfile", R_ReadPointFile_f, "Load a pointfile to " + "determine map leaks"); + Cmd_AddCommand ("loadsky", R_LoadSky_f, "Load a skybox"); + + Cvar_SetValue (r_maxedges, (float) NUMSTACKEDGES); + Cvar_SetValue (r_maxsurfs, (float) NUMSTACKSURFACES); + + view_clipplanes[0].leftedge = true; + view_clipplanes[1].rightedge = true; + view_clipplanes[1].leftedge = view_clipplanes[2].leftedge = + view_clipplanes[3].leftedge = false; + view_clipplanes[0].rightedge = view_clipplanes[2].rightedge = + view_clipplanes[3].rightedge = false; + + r_refdef.xOrigin = XCENTERING; + r_refdef.yOrigin = YCENTERING; + + R_InitParticles (); + + D_Init (); +} + +/* +void +R_Init_Cvars (void) +{ + D_Init_Cvars (); + +// r_draworder = Cvar_Get ("r_draworder", "0", CVAR_NONE, "Toggles drawing " +// "order"); +} +*/ + +void +R_NewMap (model_t *worldmodel, struct model_s **models, int num_models) +{ + int i; + + memset (&r_worldentity, 0, sizeof (r_worldentity)); + r_worldentity.model = worldmodel; + + // clear out efrags in case the level hasn't been reloaded + // FIXME: is this one short? + for (i = 0; i < worldmodel->numleafs; i++) + worldmodel->leafs[i].efrags = NULL; + + r_viewleaf = NULL; + R_ClearParticles (); + + r_cnumsurfs = r_maxsurfs->int_val; + + if (r_cnumsurfs <= MINSURFACES) + r_cnumsurfs = MINSURFACES; + + if (r_cnumsurfs > NUMSTACKSURFACES) { + surfaces = Hunk_AllocName (r_cnumsurfs * sizeof (surf_t), "surfaces"); + + surface_p = surfaces; + surf_max = &surfaces[r_cnumsurfs]; + r_surfsonstack = false; + // surface 0 doesn't really exist; it's just a dummy because index 0 + // is used to indicate no edge attached to surface + surfaces--; + R_SurfacePatch (); + } else { + r_surfsonstack = true; + } + + r_maxedgesseen = 0; + r_maxsurfsseen = 0; + + r_numallocatededges = r_maxedges->int_val; + + if (r_numallocatededges < MINEDGES) + r_numallocatededges = MINEDGES; + + if (r_numallocatededges <= NUMSTACKEDGES) { + auxedges = NULL; + } else { + auxedges = Hunk_AllocName (r_numallocatededges * sizeof (edge_t), + "edges"); + } + + r_dowarpold = false; + r_viewchanged = false; +} + +void +R_SetVrect (vrect_t *pvrectin, vrect_t *pvrect, int lineadj) +{ + int h; + float size; + qboolean full = false; + + if (scr_viewsize->int_val >= 100) { + size = 100.0; + full = true; + lineadj = 0; + } else + size = scr_viewsize->int_val; + + if (r_force_fullscreen) { + full = true; + size = 100.0; + lineadj = 0; + } + size /= 100.0; + + h = pvrectin->height - lineadj; + + if (full) { + pvrect->width = pvrectin->width; + } else { + pvrect->width = pvrectin->width - size; + } + + if (pvrect->width < 96) { + size = 96.0 / pvrectin->width; + pvrect->width = 96; // min for icons + } + pvrect->width &= ~7; + pvrect->height = pvrectin->height * size; + + if (pvrect->height > h) + pvrect->height = h; + + pvrect->height &= ~1; + + pvrect->x = (pvrectin->width - pvrect->width) / 2; + if (full) + pvrect->y = 0; + else + pvrect->y = (h - pvrect->height) / 2; +} + +/* + R_ViewChanged + + Called every time the vid structure or r_refdef changes. + Guaranteed to be called before the first refresh +*/ +void +R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect) +{ + int i; + float res_scale; + + r_viewchanged = true; + + R_SetVrect (pvrect, &r_refdef.vrect, lineadj); + + r_refdef.horizontalFieldOfView = 2.0 * tan (r_refdef.fov_x / 360 * M_PI); + r_refdef.fvrectx = (float) r_refdef.vrect.x; + r_refdef.fvrectx_adj = (float) r_refdef.vrect.x - 0.5; + r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x << 20) + (1 << 19) - 1; + r_refdef.fvrecty = (float) r_refdef.vrect.y; + r_refdef.fvrecty_adj = (float) r_refdef.vrect.y - 0.5; + r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width; + r_refdef.vrectright_adj_shift20 = + (r_refdef.vrectright << 20) + (1 << 19) - 1; + r_refdef.fvrectright = (float) r_refdef.vrectright; + r_refdef.fvrectright_adj = (float) r_refdef.vrectright - 0.5; + r_refdef.vrectrightedge = (float) r_refdef.vrectright - 0.99; + r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height; + r_refdef.fvrectbottom = (float) r_refdef.vrectbottom; + r_refdef.fvrectbottom_adj = (float) r_refdef.vrectbottom - 0.5; + + r_refdef.aliasvrect.x = (int) (r_refdef.vrect.x * r_aliasuvscale); + r_refdef.aliasvrect.y = (int) (r_refdef.vrect.y * r_aliasuvscale); + r_refdef.aliasvrect.width = (int) (r_refdef.vrect.width * r_aliasuvscale); + r_refdef.aliasvrect.height = (int) (r_refdef.vrect.height * + r_aliasuvscale); + r_refdef.aliasvrectright = r_refdef.aliasvrect.x + + r_refdef.aliasvrect.width; + r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y + + r_refdef.aliasvrect.height; + + pixelAspect = aspect; + xOrigin = r_refdef.xOrigin; + yOrigin = r_refdef.yOrigin; + + screenAspect = r_refdef.vrect.width * pixelAspect / r_refdef.vrect.height; +// 320*200 1.0 pixelAspect = 1.6 screenAspect +// 320*240 1.0 pixelAspect = 1.3333 screenAspect +// proper 320*200 pixelAspect = 0.8333333 + + verticalFieldOfView = r_refdef.horizontalFieldOfView / screenAspect; + +// values for perspective projection +// if math were exact, the values would range from 0.5 to to range+0.5 +// hopefully they wll be in the 0.000001 to range+.999999 and truncate +// the polygon rasterization will never render in the first row or column +// but will definately render in the [range] row and column, so adjust the +// buffer origin to get an exact edge to edge fill + xcenter = ((float) r_refdef.vrect.width * XCENTERING) + + r_refdef.vrect.x - 0.5; + aliasxcenter = xcenter * r_aliasuvscale; + ycenter = ((float) r_refdef.vrect.height * YCENTERING) + + r_refdef.vrect.y - 0.5; + aliasycenter = ycenter * r_aliasuvscale; + + xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView; + aliasxscale = xscale * r_aliasuvscale; + xscaleinv = 1.0 / xscale; + yscale = xscale * pixelAspect; + aliasyscale = yscale * r_aliasuvscale; + yscaleinv = 1.0 / yscale; + xscaleshrink = (r_refdef.vrect.width - 6) / r_refdef.horizontalFieldOfView; + yscaleshrink = xscaleshrink * pixelAspect; + +// left side clip + screenedge[0].normal[0] = -1.0 / (xOrigin * + r_refdef.horizontalFieldOfView); + screenedge[0].normal[1] = 0; + screenedge[0].normal[2] = 1; + screenedge[0].type = PLANE_ANYZ; + +// right side clip + screenedge[1].normal[0] = 1.0 / ((1.0 - xOrigin) * + r_refdef.horizontalFieldOfView); + screenedge[1].normal[1] = 0; + screenedge[1].normal[2] = 1; + screenedge[1].type = PLANE_ANYZ; + +// top side clip + screenedge[2].normal[0] = 0; + screenedge[2].normal[1] = -1.0 / (yOrigin * verticalFieldOfView); + screenedge[2].normal[2] = 1; + screenedge[2].type = PLANE_ANYZ; + +// bottom side clip + screenedge[3].normal[0] = 0; + screenedge[3].normal[1] = 1.0 / ((1.0 - yOrigin) * verticalFieldOfView); + screenedge[3].normal[2] = 1; + screenedge[3].type = PLANE_ANYZ; + + for (i = 0; i < 4; i++) + VectorNormalize (screenedge[i].normal); + + res_scale = sqrt ((double) (r_refdef.vrect.width * r_refdef.vrect.height) / + (320.0 * 152.0)) * (2.0 / + r_refdef.horizontalFieldOfView); + r_aliastransition = r_aliastransbase->value * res_scale; + r_resfudge = r_aliastransadj->value * res_scale; + + if (scr_fov->value <= 90.0) + r_fov_greater_than_90 = false; + else + r_fov_greater_than_90 = true; + + D_ViewChanged (); +} + +void +R_MarkLeaves (void) +{ + byte *vis; + mnode_t *node; + int i; + + if (r_oldviewleaf == r_viewleaf) + return; + + r_visframecount++; + r_oldviewleaf = r_viewleaf; + + vis = Mod_LeafPVS (r_viewleaf, r_worldentity.model); + + for (i = 0; i < r_worldentity.model->numleafs; i++) { + if (vis[i >> 3] & (1 << (i & 7))) { + node = (mnode_t *) &r_worldentity.model->leafs[i + 1]; + do { + if (node->visframe == r_visframecount) + break; + node->visframe = r_visframecount; + node = node->parent; + } while (node); + } + } +} + +static void +R_ShowNearestLoc (void) +{ + location_t *nearloc; + vec3_t trueloc; + dlight_t *dl; + + if (r_drawentities->int_val) + return; + nearloc = locs_find (r_origin); + if (nearloc) { + dl = R_AllocDlight (4096); + VectorCopy (nearloc->loc, dl->origin); + dl->radius = 200; + dl->die = r_realtime + 0.1; + dl->color[1]=1; + + VectorCopy(nearloc->loc,trueloc); + R_RunParticleEffect(trueloc,252,10); + } +} + +void +R_DrawEntitiesOnList (void) +{ + int i, j; + int lnum; + alight_t lighting; + + // FIXME: remove and do real lighting + float lightvec[3] = { -1, 0, 0 }; + vec3_t dist; + float add; + + if (!r_drawentities->int_val) { + R_ShowNearestLoc(); + return; + } + + for (i = 0; i < r_numvisedicts; i++) { + currententity = r_visedicts[i]; + + switch (currententity->model->type) { + case mod_sprite: + VectorCopy (currententity->origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); + R_DrawSprite (); + break; + + case mod_alias: + VectorCopy (currententity->origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); + + // see if the bounding box lets us trivially reject, also + // sets trivial accept status + if (R_AliasCheckBBox ()) { + j = R_LightPoint (currententity->origin); + + lighting.ambientlight = j; + lighting.shadelight = j; + + lighting.plightvec = lightvec; + + for (lnum = 0; lnum < MAX_DLIGHTS; lnum++) { + if (r_dlights[lnum].die >= r_realtime) { + VectorSubtract (currententity->origin, + r_dlights[lnum].origin, dist); + add = r_dlights[lnum].radius - Length (dist); + + if (add > 0) + lighting.ambientlight += add; + } + } + + // clamp lighting so it doesn't overbright as much + if (lighting.ambientlight > 128) + lighting.ambientlight = 128; + if (lighting.ambientlight + lighting.shadelight > 192) + lighting.shadelight = 192 - lighting.ambientlight; + + R_AliasDrawModel (&lighting); + } + + break; + + default: + break; + } + } +} + +void +R_DrawViewModel (void) +{ + // FIXME: remove and do real lighting + float lightvec[3] = { -1, 0, 0 }; + int j; + int lnum; + vec3_t dist; + float add; + dlight_t *dl; + + if (!r_inhibit_viewmodel + || !r_drawviewmodel->int_val + || !r_drawentities->int_val) + return; + + currententity = r_view_model; + if (!currententity->model) + return; + + VectorCopy (currententity->origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); + + VectorCopy (vup, viewlightvec); + VectorInverse (viewlightvec); + + j = R_LightPoint (currententity->origin); + + if (j < 24) + j = 24; // always give some light on gun + r_viewlighting.ambientlight = j; + r_viewlighting.shadelight = j; + + // add dynamic lights + for (lnum = 0; lnum < MAX_DLIGHTS; lnum++) { + dl = &r_dlights[lnum]; + if (!dl->radius) + continue; + if (!dl->radius) + continue; + if (dl->die < r_realtime) + continue; + + VectorSubtract (currententity->origin, dl->origin, dist); + add = dl->radius - Length (dist); + if (add > 0) + r_viewlighting.ambientlight += add; + } + + // clamp lighting so it doesn't overbright as much + if (r_viewlighting.ambientlight > 128) + r_viewlighting.ambientlight = 128; + if (r_viewlighting.ambientlight + r_viewlighting.shadelight > 192) + r_viewlighting.shadelight = 192 - r_viewlighting.ambientlight; + + r_viewlighting.plightvec = lightvec; + + R_AliasDrawModel (&r_viewlighting); +} + +int +R_BmodelCheckBBox (model_t *clmodel, float *minmaxs) +{ + int i, *pindex, clipflags; + vec3_t acceptpt, rejectpt; + double d; + + clipflags = 0; + + if (currententity->angles[0] || currententity->angles[1] + || currententity->angles[2]) { + for (i = 0; i < 4; i++) { + d = DotProduct (currententity->origin, view_clipplanes[i].normal); + d -= view_clipplanes[i].dist; + + if (d <= -clmodel->radius) + return BMODEL_FULLY_CLIPPED; + + if (d <= clmodel->radius) + clipflags |= (1 << i); + } + } else { + for (i = 0; i < 4; i++) { + // generate accept and reject points + // FIXME: do with fast look-ups or integer tests based on the + // sign bit of the floating point values + + pindex = pfrustum_indexes[i]; + + rejectpt[0] = minmaxs[pindex[0]]; + rejectpt[1] = minmaxs[pindex[1]]; + rejectpt[2] = minmaxs[pindex[2]]; + + d = DotProduct (rejectpt, view_clipplanes[i].normal); + d -= view_clipplanes[i].dist; + + if (d <= 0) + return BMODEL_FULLY_CLIPPED; + + acceptpt[0] = minmaxs[pindex[3 + 0]]; + acceptpt[1] = minmaxs[pindex[3 + 1]]; + acceptpt[2] = minmaxs[pindex[3 + 2]]; + + d = DotProduct (acceptpt, view_clipplanes[i].normal); + d -= view_clipplanes[i].dist; + + if (d <= 0) + clipflags |= (1 << i); + } + } + + return clipflags; +} + +void +R_DrawBEntitiesOnList (void) +{ + int i, j, k, clipflags; + vec3_t oldorigin; + model_t *clmodel; + float minmaxs[6]; + + if (!r_drawentities->int_val) + return; + + VectorCopy (modelorg, oldorigin); + insubmodel = true; + + for (i = 0; i < r_numvisedicts; i++) { + currententity = r_visedicts[i]; + + switch (currententity->model->type) { + case mod_brush: + clmodel = currententity->model; + + // see if the bounding box lets us trivially reject, also + // sets trivial accept status + for (j = 0; j < 3; j++) { + minmaxs[j] = currententity->origin[j] + clmodel->mins[j]; + minmaxs[3 + j] = currententity->origin[j] + clmodel->maxs[j]; + } + + clipflags = R_BmodelCheckBBox (clmodel, minmaxs); + + if (clipflags != BMODEL_FULLY_CLIPPED) { + VectorCopy (currententity->origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); + +// FIXME: is this needed? + VectorCopy (modelorg, r_worldmodelorg); + r_pcurrentvertbase = clmodel->vertexes; + +// FIXME: stop transforming twice + R_RotateBmodel (); + + // calculate dynamic lighting for bmodel if it's not an + // instanced model + if (clmodel->firstmodelsurface != 0) { + vec3_t lightorigin; + + for (k = 0; k < MAX_DLIGHTS; k++) { + if ((r_dlights[k].die < r_realtime) || + (!r_dlights[k].radius)) continue; + + VectorSubtract (r_dlights[k].origin, + currententity->origin, + lightorigin); + R_RecursiveMarkLights + (lightorigin, &r_dlights[k], 1 << k, + clmodel->nodes + clmodel->hulls[0].firstclipnode); + } + } + // if the driver wants polygons, deliver those. + // Z-buffering is on at this point, so no clipping to the + // world tree is needed, just frustum clipping + if (r_drawpolys | r_drawculledpolys) { + R_ZDrawSubmodelPolys (clmodel); + } else { + r_pefragtopnode = NULL; + + for (j = 0; j < 3; j++) { + r_emins[j] = minmaxs[j]; r_emaxs[j] = minmaxs[3 + j]; + } + + R_SplitEntityOnNode2 (r_worldentity.model->nodes); + + if (r_pefragtopnode) { + currententity->topnode = r_pefragtopnode; + + if (r_pefragtopnode->contents >= 0) { + // not a leaf; has to be clipped to the world + // BSP + r_clipflags = clipflags; + R_DrawSolidClippedSubmodelPolygons (clmodel); + } else { + // falls entirely in one leaf, so we just put + // all the edges in the edge list and let 1/z + // sorting handle drawing order + R_DrawSubmodelPolygons (clmodel, clipflags); + } + + currententity->topnode = NULL; + } + } + + // put back world rotation and frustum clipping +// FIXME: R_RotateBmodel should just work off base_vxx + VectorCopy (base_vpn, vpn); + VectorCopy (base_vup, vup); + VectorCopy (base_vright, vright); + VectorCopy (base_modelorg, modelorg); + VectorCopy (oldorigin, modelorg); + R_TransformFrustum (); + } + break; + default: + break; + } + } + + insubmodel = false; +} + +void +R_EdgeDrawing (void) +{ + edge_t ledges[NUMSTACKEDGES + + + ((CACHE_SIZE - 1) / sizeof (edge_t)) + 1]; + surf_t lsurfs[NUMSTACKSURFACES + + + ((CACHE_SIZE - 1) / sizeof (surf_t)) + 1]; + + if (auxedges) { + r_edges = auxedges; + } else { + r_edges = (edge_t *) + (((long) &ledges[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); + } + + if (r_surfsonstack) { + surfaces = (surf_t *) + (((long) &lsurfs[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); + surf_max = &surfaces[r_cnumsurfs]; + // surface 0 doesn't really exist; it's just a dummy because index 0 + // is used to indicate no edge attached to surface + surfaces--; + R_SurfacePatch (); + } + + R_BeginEdgeFrame (); + + if (r_dspeeds->int_val) { + rw_time1 = Sys_DoubleTime (); + } + + R_RenderWorld (); + + if (r_drawculledpolys) + R_ScanEdges (); + + // only the world can be drawn back to front with no z reads or compares, + // just z writes, so have the driver turn z compares on now + D_TurnZOn (); + + if (r_dspeeds->int_val) { + rw_time2 = Sys_DoubleTime (); + db_time1 = rw_time2; + } + + R_DrawBEntitiesOnList (); + + if (r_dspeeds->int_val) { + db_time2 = Sys_DoubleTime (); + se_time1 = db_time2; + } + + if (!r_dspeeds->int_val) { + VID_UnlockBuffer (); + S_ExtraUpdate (); // don't let sound get messed up if + // going slow + VID_LockBuffer (); + } + + if (!(r_drawpolys | r_drawculledpolys)) + R_ScanEdges (); +} + +// LordHavoc: took out of stack and made 4x size for 32bit capacity +byte warpbuffer[WARP_WIDTH * WARP_HEIGHT * 4]; + +/* + R_RenderView + + r_refdef must be set before the first call +*/ +void +R_RenderView_ (void) +{ + r_warpbuffer = warpbuffer; + + if (r_timegraph->int_val || r_speeds->int_val || r_dspeeds->int_val) + r_time1 = Sys_DoubleTime (); + + R_SetupFrame (); + +#ifdef PASSAGES + SetVisibilityByPassages (); +#else + R_MarkLeaves (); // done here so we know if we're in + // water +#endif + +// make FDIV fast. This reduces timing precision after we've been running for a +// while, so we don't do it globally. This also sets chop mode, and we do it +// here so that setup stuff like the refresh area calculations match what's +// done in screen.c +// Sys_LowFPPrecision (); // LordHavoc: no assembly + + if (!r_worldentity.model) + Sys_Error ("R_RenderView: NULL worldmodel"); + + if (!r_dspeeds->int_val) { + VID_UnlockBuffer (); + S_ExtraUpdate (); // don't let sound get messed up if going slow + VID_LockBuffer (); + } + + R_EdgeDrawing (); + + if (!r_dspeeds->int_val) { + VID_UnlockBuffer (); + S_ExtraUpdate (); // don't let sound get messed up if + // going slow + VID_LockBuffer (); + } + + if (r_dspeeds->int_val) { + se_time2 = Sys_DoubleTime (); + de_time1 = se_time2; + } + + R_DrawEntitiesOnList (); + + if (r_dspeeds->int_val) { + de_time2 = Sys_DoubleTime (); + dv_time1 = de_time2; + } + + R_DrawViewModel (); + + if (r_dspeeds->int_val) { + dv_time2 = Sys_DoubleTime (); + dp_time1 = Sys_DoubleTime (); + } + + R_DrawParticles (); + + if (r_dspeeds->int_val) + dp_time2 = Sys_DoubleTime (); + + if (r_dowarp) + D_WarpScreen (); + + V_SetContentsColor (r_viewleaf->contents); + + if (r_timegraph->int_val) + R_TimeGraph (); + + if (r_netgraph->int_val) + R_NetGraph (); + + if (r_zgraph->int_val) + R_ZGraph (); + + if (r_aliasstats->int_val) + R_PrintAliasStats (); + + if (r_speeds->int_val) + R_PrintTimes (); + + if (r_dspeeds->int_val) + R_PrintDSpeeds (); + + if (r_reportsurfout->int_val && r_outofsurfaces) + Con_Printf ("Short %d surfaces\n", r_outofsurfaces); + + if (r_reportedgeout->int_val && r_outofedges) + Con_Printf ("Short roughly %d edges\n", r_outofedges * 2 / 3); + + // back to high floating-point precision + // Sys_HighFPPrecision (); // LordHavoc: no assembly +} + +void +R_RenderView (void) +{ + int dummy; + int delta; + + delta = (byte *) & dummy - r_stack_start; + if (delta < -10000 || delta > 10000) + Sys_Error ("R_RenderView: called without enough stack"); + + if (Hunk_LowMark () & 3) + Sys_Error ("Hunk is missaligned"); + + if ((long) (&dummy) & 3) + Sys_Error ("Stack is missaligned"); + + if ((long) (&r_warpbuffer) & 3) + Sys_Error ("Globals are missaligned"); + + R_RenderView_ (); +} + +void +R_InitTurb (void) +{ + int i; + + for (i = 0; i < 1280; i++) { + sintable[i] = AMP + sin (i * 3.14159 * 2 / CYCLE) * AMP; + intsintable[i] = AMP2 + sin (i * 3.14159 * 2 / CYCLE) * AMP2; + // AMP2 not 20 + } +} diff --git a/libs/video/renderer/sw32/sw32_rmisc.c b/libs/video/renderer/sw32/sw32_rmisc.c new file mode 100644 index 000000000..1be2ac91e --- /dev/null +++ b/libs/video/renderer/sw32/sw32_rmisc.c @@ -0,0 +1,385 @@ +/* + sw32_rmisc.c + + (description) + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/cmd.h" +#include "QF/console.h" +#include "QF/cvar.h" +#include "QF/draw.h" +#include "QF/render.h" +#include "QF/sys.h" + +#include "compat.h" +#include "r_local.h" + +qboolean allowskybox; // whether or not to allow skyboxes --KB + + +void +R_CheckVariables (void) +{ +} + +/* + Show + + Debugging use +*/ +void +Show (void) +{ + vrect_t vr; + + vr.x = vr.y = 0; + vr.width = vid.width; + vr.height = vid.height; + vr.pnext = NULL; + VID_Update (&vr); +} + +/* + R_TimeRefresh_f + + For program optimization +*/ +void +R_TimeRefresh_f (void) +{ + int i; + float start, stop, time; + int startangle; + vrect_t vr; + + startangle = r_refdef.viewangles[1]; + + start = Sys_DoubleTime (); + for (i = 0; i < 128; i++) { + r_refdef.viewangles[1] = i / 128.0 * 360.0; + + VID_LockBuffer (); + + R_RenderView (); + + VID_UnlockBuffer (); + + vr.x = r_refdef.vrect.x; + vr.y = r_refdef.vrect.y; + vr.width = r_refdef.vrect.width; + vr.height = r_refdef.vrect.height; + vr.pnext = NULL; + VID_Update (&vr); + } + stop = Sys_DoubleTime (); + time = stop - start; + Con_Printf ("%f seconds (%f fps)\n", time, 128 / time); + + r_refdef.viewangles[1] = startangle; +} + +void +R_LoadSky_f (void) +{ + if (Cmd_Argc () != 2) { + Con_Printf ("loadsky : load a skybox\n"); + return; + } + + R_LoadSkys (Cmd_Argv (1)); +} + +void +R_PrintTimes (void) +{ + float r_time2; + float ms; + + r_time2 = Sys_DoubleTime (); + + ms = 1000 * (r_time2 - r_time1); + + Con_Printf ("%5.1f ms %3i/%3i/%3i poly %3i surf\n", + ms, c_faceclip, r_polycount, r_drawnpolycount, c_surf); + c_surf = 0; +} + +void +R_PrintDSpeeds (void) +{ + float ms, dp_time, r_time2, rw_time, db_time, se_time, de_time, + + dv_time; + + r_time2 = Sys_DoubleTime (); + + dp_time = (dp_time2 - dp_time1) * 1000; + rw_time = (rw_time2 - rw_time1) * 1000; + db_time = (db_time2 - db_time1) * 1000; + se_time = (se_time2 - se_time1) * 1000; + de_time = (de_time2 - de_time1) * 1000; + dv_time = (dv_time2 - dv_time1) * 1000; + ms = (r_time2 - r_time1) * 1000; + + Con_Printf ("%3i %4.1fp %3iw %4.1fb %3is %4.1fe %4.1fv\n", + (int) ms, dp_time, (int) rw_time, db_time, (int) se_time, + de_time, dv_time); +} + +void +R_PrintAliasStats (void) +{ + Con_Printf ("%3i polygon model drawn\n", r_amodels_drawn); +} + +void +WarpPalette (void) +{ + int i, j; + byte newpalette[768]; + int basecolor[3]; + + basecolor[0] = 130; + basecolor[1] = 80; + basecolor[2] = 50; + + // pull the colors halfway to bright brown + for (i = 0; i < 256; i++) { + for (j = 0; j < 3; j++) { + newpalette[i * 3 + j] = + (vid_basepal[i * 3 + j] + basecolor[j]) / 2; + } + } + + VID_ShiftPalette (newpalette); +} + +void +R_TransformFrustum (void) +{ + int i; + vec3_t v, v2; + + for (i = 0; i < 4; i++) { + v[0] = screenedge[i].normal[2]; + v[1] = -screenedge[i].normal[0]; + v[2] = screenedge[i].normal[1]; + + v2[0] = v[1] * vright[0] + v[2] * vup[0] + v[0] * vpn[0]; + v2[1] = v[1] * vright[1] + v[2] * vup[1] + v[0] * vpn[1]; + v2[2] = v[1] * vright[2] + v[2] * vup[2] + v[0] * vpn[2]; + + VectorCopy (v2, view_clipplanes[i].normal); + + view_clipplanes[i].dist = DotProduct (modelorg, v2); + } +} + +void +TransformVector (vec3_t in, vec3_t out) +{ + out[0] = DotProduct (in, vright); + out[1] = DotProduct (in, vup); + out[2] = DotProduct (in, vpn); +} + +void +R_TransformPlane (mplane_t *p, float *normal, float *dist) +{ + float d; + + d = DotProduct (r_origin, p->normal); + *dist = p->dist - d; +// TODO: when we have rotating entities, this will need to use the view matrix + TransformVector (p->normal, normal); +} + +void +R_SetUpFrustumIndexes (void) +{ + int i, j, *pindex; + + pindex = r_frustum_indexes; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 3; j++) { + if (view_clipplanes[i].normal[j] < 0) { + pindex[j] = j; + pindex[j + 3] = j + 3; + } else { + pindex[j] = j + 3; + pindex[j + 3] = j; + } + } + + // FIXME: do just once at start + pfrustum_indexes[i] = pindex; + pindex += 6; + } +} + +void +R_SetupFrame (void) +{ + int edgecount; + vrect_t vrect; + float w, h; + + // don't allow cheats in multiplayer +// Cvar_SetValue (r_draworder, 0); + Cvar_SetValue (r_ambient, 0); + Cvar_SetValue (r_drawflat, 0); + + if (r_numsurfs->int_val) { + if ((surface_p - surfaces) > r_maxsurfsseen) + r_maxsurfsseen = surface_p - surfaces; + + Con_Printf ("Used %d of %d surfs; %d max\n", surface_p - surfaces, + surf_max - surfaces, r_maxsurfsseen); + } + + if (r_numedges->int_val) { + edgecount = edge_p - r_edges; + + if (edgecount > r_maxedgesseen) + r_maxedgesseen = edgecount; + + Con_Printf ("Used %d of %d edges; %d max\n", edgecount, + r_numallocatededges, r_maxedgesseen); + } + + r_refdef.ambientlight = max (r_ambient->value, 0); + + Cvar_SetValue (r_draworder, 0); + + R_CheckVariables (); + + R_AnimateLight (); + + r_framecount++; + + numbtofpolys = 0; + + // debugging +#if 0 + r_refdef.vieworg[0] = 80; + r_refdef.vieworg[1] = 64; + r_refdef.vieworg[2] = 40; + r_refdef.viewangles[0] = 0; + r_refdef.viewangles[1] = 46.763641357; + r_refdef.viewangles[2] = 0; +#endif + + // build the transformation matrix for the given view angles + VectorCopy (r_refdef.vieworg, modelorg); + VectorCopy (r_refdef.vieworg, r_origin); + + AngleVectors (r_refdef.viewangles, vpn, vright, vup); + + // current viewleaf + r_oldviewleaf = r_viewleaf; + r_viewleaf = Mod_PointInLeaf (r_origin, r_worldentity.model); + + r_dowarpold = r_dowarp; + r_dowarp = r_waterwarp->int_val && (r_viewleaf->contents <= + CONTENTS_WATER); + + if ((r_dowarp != r_dowarpold) || r_viewchanged) { + if (r_dowarp) { + if ((vid.width <= vid.maxwarpwidth) && + (vid.height <= vid.maxwarpheight)) { + vrect.x = 0; + vrect.y = 0; + vrect.width = vid.width; + vrect.height = vid.height; + + R_ViewChanged (&vrect, r_lineadj, vid.aspect); + } else { + w = vid.width; + h = vid.height; + + if (w > vid.maxwarpwidth) { + h *= (float) vid.maxwarpwidth / w; + w = vid.maxwarpwidth; + } + + if (h > vid.maxwarpheight) { + h = vid.maxwarpheight; + w *= (float) vid.maxwarpheight / h; + } + + vrect.x = 0; + vrect.y = 0; + vrect.width = (int) w; + vrect.height = (int) h; + + R_ViewChanged (&vrect, + (int) ((float) r_lineadj * + (h / (float) vid.height)), + vid.aspect * (h / w) * ((float) vid.width / + (float) vid.height)); + } + } else { + vrect.x = 0; + vrect.y = 0; + vrect.width = vid.width; + vrect.height = vid.height; + + R_ViewChanged (&vrect, r_lineadj, vid.aspect); + } + + r_viewchanged = false; + } + // start off with just the four screen edge clip planes + R_TransformFrustum (); + + // save base values + VectorCopy (vpn, base_vpn); + VectorCopy (vright, base_vright); + VectorCopy (vup, base_vup); + VectorCopy (modelorg, base_modelorg); + + R_SetSkyFrame (); + + R_SetUpFrustumIndexes (); + + r_cache_thrash = false; + + // clear frame counts + c_faceclip = 0; + d_spanpixcount = 0; + r_polycount = 0; + r_drawnpolycount = 0; + r_wholepolycount = 0; + r_amodels_drawn = 0; + r_outofsurfaces = 0; + r_outofedges = 0; + + D_SetupFrame (); +} diff --git a/libs/video/renderer/sw32/sw32_rpart.c b/libs/video/renderer/sw32/sw32_rpart.c new file mode 100644 index 000000000..e0d804e0c --- /dev/null +++ b/libs/video/renderer/sw32/sw32_rpart.c @@ -0,0 +1,546 @@ +/* + sw32_rpart.c + + (description) + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "QF/console.h" +#include "QF/cvar.h" +#include "QF/qargs.h" +#include "QF/vfs.h" +#include "QF/render.h" + +#include "compat.h" +#include "r_cvar.h" +#include "r_dynamic.h" +#include "r_local.h" + +#define MAX_PARTICLES 2048 // default max # of particles at one + // time +#define ABSOLUTE_MIN_PARTICLES 512 // no fewer than this no matter what's + // on the command line + +int ramp1[8] = { 0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61 }; +int ramp2[8] = { 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66 }; +int ramp3[8] = { 0x6d, 0x6b, 6, 5, 4, 3 }; + +particle_t *active_particles, *free_particles; + +particle_t *particles; +int r_numparticles; + +vec3_t r_pright, r_pup, r_ppn; +cvar_t *r_particles; + + +void +R_InitParticles (void) +{ + int i; + + i = COM_CheckParm ("-particles"); + + if (i) { + r_numparticles = (int) (atoi (com_argv[i + 1])); + if (r_numparticles < ABSOLUTE_MIN_PARTICLES) + r_numparticles = ABSOLUTE_MIN_PARTICLES; + } else { + r_numparticles = MAX_PARTICLES; + } + + particles = (particle_t *) + Hunk_AllocName (r_numparticles * sizeof (particle_t), "particles"); +} + +void +R_ClearParticles (void) +{ + int i; + + free_particles = &particles[0]; + active_particles = NULL; + + for (i = 0; i < r_numparticles; i++) + particles[i].next = &particles[i + 1]; + particles[r_numparticles - 1].next = NULL; +} + +void +R_ReadPointFile_f (void) +{ + VFile *f; + vec3_t org; + int r; + int c; + particle_t *p; + char name[MAX_OSPATH]; + + // FIXME snprintf (name, sizeof (name), "maps/%s.pts", sv.name); + + COM_FOpenFile (name, &f); + if (!f) { + Con_Printf ("couldn't open %s\n", name); + return; + } + + Con_Printf ("Reading %s...\n", name); + c = 0; + for (;;) { + char buf[64]; + + Qgets (f, buf, sizeof (buf)); + r = sscanf (buf, "%f %f %f\n", &org[0], &org[1], &org[2]); + if (r != 3) + break; + c++; + + if (!free_particles) { + Con_Printf ("Not enough free particles\n"); + break; + } + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = 99999; + p->color = (-c) & 15; + p->type = pt_static; + VectorCopy (vec3_origin, p->vel); + VectorCopy (org, p->org); + } + + Qclose (f); + Con_Printf ("%i points read\n", c); +} + +void +R_RunSpikeEffect (vec3_t pos, particle_effect_t type) +{ + switch (type) { + case PE_WIZSPIKE: + R_RunParticleEffect (pos, 20, 30); + break; + case PE_KNIGHTSPIKE: + R_RunParticleEffect (pos, 226, 20); + break; + case PE_SPIKE: + R_RunParticleEffect (pos, 0, 10); + break; + case PE_SUPERSPIKE: + R_RunParticleEffect (pos, 0, 20); + break; + } +} + +void +R_RunPuffEffect (vec3_t pos, particle_effect_t type, byte cnt) +{ + if (!r_particles->int_val) + return; + + switch (type) { + case PE_GUNSHOT: + R_RunParticleEffect (pos, 0, 20 * cnt); + break; + case PE_BLOOD: + R_RunParticleEffect (pos, 73, 20 * cnt); + break; + case PE_LIGHTNINGBLOOD: + R_RunParticleEffect (pos, 225, 50); + break; + } +} + +void +R_ParticleExplosion (vec3_t org) +{ + int i, j; + particle_t *p; + + if (!r_particles->int_val) + return; + + for (i = 0; i < 1024; i++) { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = r_realtime + 5; + p->color = ramp1[0]; + p->ramp = rand () & 3; + if (i & 1) { + p->type = pt_explode; + for (j = 0; j < 3; j++) { + p->org[j] = org[j] + ((rand () % 32) - 16); + p->vel[j] = (rand () % 512) - 256; + } + } else { + p->type = pt_explode2; + for (j = 0; j < 3; j++) { + p->org[j] = org[j] + ((rand () % 32) - 16); + p->vel[j] = (rand () % 512) - 256; + } + } + } +} + +void +R_BlobExplosion (vec3_t org) +{ + int i, j; + particle_t *p; + + if (!r_particles->int_val) + return; + + for (i = 0; i < 1024; i++) { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = r_realtime + 1 + (rand () & 8) * 0.05; + + if (i & 1) { + p->type = pt_blob; + p->color = 66 + rand () % 6; + for (j = 0; j < 3; j++) { + p->org[j] = org[j] + ((rand () % 32) - 16); + p->vel[j] = (rand () % 512) - 256; + } + } else { + p->type = pt_blob2; + p->color = 150 + rand () % 6; + for (j = 0; j < 3; j++) { + p->org[j] = org[j] + ((rand () % 32) - 16); + p->vel[j] = (rand () % 512) - 256; + } + } + } +} + +void +R_RunParticleEffect (vec3_t org, int color, int count) +{ + int i, j; + particle_t *p; + int scale; + + if (!r_particles->int_val) + return; + + if (count > 130) + scale = 3; + else if (count > 20) + scale = 2; + else + scale = 1; + + for (i = 0; i < count; i++) { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = r_realtime + 0.1 * (rand () % 5); + p->color = (color & ~7) + (rand () & 7); + p->type = pt_grav; + for (j = 0; j < 3; j++) { + p->org[j] = org[j] + scale * ((rand () & 15) - 8); + p->vel[j] = vec3_origin[j]; // + (rand()%300)-150; + } + } +} + +void +R_LavaSplash (vec3_t org) +{ + int i, j, k; + particle_t *p; + float vel; + vec3_t dir; + + if (!r_particles->int_val) + return; + + for (i = -16; i < 16; i++) + for (j = -16; j < 16; j++) + for (k = 0; k < 1; k++) { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = r_realtime + 2 + (rand () & 31) * 0.02; + p->color = 224 + (rand () & 7); + p->type = pt_grav; + + dir[0] = j * 8 + (rand () & 7); + dir[1] = i * 8 + (rand () & 7); + dir[2] = 256; + + p->org[0] = org[0] + dir[0]; + p->org[1] = org[1] + dir[1]; + p->org[2] = org[2] + (rand () & 63); + + VectorNormalize (dir); + vel = 50 + (rand () & 63); + VectorScale (dir, vel, p->vel); + } +} + +void +R_TeleportSplash (vec3_t org) +{ + int i, j, k; + particle_t *p; + float vel; + vec3_t dir; + + if (!r_particles->int_val) + return; + + for (i = -16; i < 16; i += 4) + for (j = -16; j < 16; j += 4) + for (k = -24; k < 32; k += 4) { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = r_realtime + 0.2 + (rand () & 7) * 0.02; + p->color = 7 + (rand () & 7); + p->type = pt_grav; + + dir[0] = j * 8; + dir[1] = i * 8; + dir[2] = k * 8; + + p->org[0] = org[0] + i + (rand () & 3); + p->org[1] = org[1] + j + (rand () & 3); + p->org[2] = org[2] + k + (rand () & 3); + + VectorNormalize (dir); + vel = 50 + (rand () & 63); + VectorScale (dir, vel, p->vel); + } +} + +void +R_RocketTrail (int type, entity_t *ent) +{ + vec3_t vec; + float len; + int j; + particle_t *p; + + if (!r_particles->int_val) + return; + + VectorSubtract (ent->origin, ent->old_origin, vec); + len = VectorNormalize (vec); + while (len > 0) { + len -= 3; + + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + VectorCopy (vec3_origin, p->vel); + p->die = r_realtime + 2; + + if (type == 4) { // slight blood + p->type = pt_slowgrav; + p->color = 67 + (rand () & 3); + for (j = 0; j < 3; j++) + p->org[j] = ent->old_origin[j] + ((rand () % 6) - 3); + len -= 3; + } else if (type == 2) { // blood + p->type = pt_slowgrav; + p->color = 67 + (rand () & 3); + for (j = 0; j < 3; j++) + p->org[j] = ent->old_origin[j] + ((rand () % 6) - 3); + } else if (type == 6) { // voor trail + p->color = 9 * 16 + 8 + (rand () & 3); + p->type = pt_static; + p->die = r_realtime + 0.3; + for (j = 0; j < 3; j++) + p->org[j] = ent->old_origin[j] + ((rand () & 15) - 8); + } else if (type == 1) { // smoke smoke + p->ramp = (rand () & 3) + 2; + p->color = ramp3[(int) p->ramp]; + p->type = pt_fire; + for (j = 0; j < 3; j++) + p->org[j] = ent->old_origin[j] + ((rand () % 6) - 3); + } else if (type == 0) { // rocket trail + p->ramp = (rand () & 3); + p->color = ramp3[(int) p->ramp]; + p->type = pt_fire; + for (j = 0; j < 3; j++) + p->org[j] = ent->old_origin[j] + ((rand () % 6) - 3); + } else if (type == 3 || type == 5) { // tracer + static int tracercount; + + p->die = r_realtime + 0.5; + p->type = pt_static; + if (type == 3) + p->color = 52 + ((tracercount & 4) << 1); + else + p->color = 230 + ((tracercount & 4) << 1); + + tracercount++; + + VectorCopy (ent->old_origin, p->org); + if (tracercount & 1) { + p->vel[0] = 30 * vec[1]; + p->vel[1] = 30 * -vec[0]; + } else { + p->vel[0] = 30 * -vec[1]; + p->vel[1] = 30 * vec[0]; + } + + } + + VectorAdd (ent->old_origin, vec, ent->old_origin); + } +} + +void +R_DrawParticles (void) +{ + particle_t *p, **particle; + float grav; + int i; + float time2, time3; + float time1; + float dvel; + float frametime; + + D_StartParticles (); + + VectorScale (vright, xscaleshrink, r_pright); + VectorScale (vup, yscaleshrink, r_pup); + VectorCopy (vpn, r_ppn); + + frametime = r_frametime; + time3 = frametime * 15; + time2 = frametime * 10; // 15; + time1 = frametime * 5; + grav = frametime * 800 * 0.05; + dvel = 4 * frametime; + + for (particle = &active_particles; *particle;) { + if ((*particle)->die < r_realtime) { + p = (*particle)->next; + (*particle)->next = free_particles; + free_particles = (*particle); + (*particle) = p; + } else { + p = *particle; + particle = &(*particle)->next; + + D_DrawParticle (p); + + p->org[0] += p->vel[0] * frametime; + p->org[1] += p->vel[1] * frametime; + p->org[2] += p->vel[2] * frametime; + + switch (p->type) { + case pt_static: + break; + case pt_fire: + p->ramp += time1; + if (p->ramp >= 6) + p->die = -1; + else + p->color = ramp3[(int) p->ramp]; + p->vel[2] += grav; + break; + + case pt_explode: + p->ramp += time2; + if (p->ramp >= 8) + p->die = -1; + else + p->color = ramp1[(int) p->ramp]; + for (i = 0; i < 3; i++) + p->vel[i] += p->vel[i] * dvel; + p->vel[2] -= grav; + break; + + case pt_explode2: + p->ramp += time3; + if (p->ramp >= 8) + p->die = -1; + else + p->color = ramp2[(int) p->ramp]; + for (i = 0; i < 3; i++) + p->vel[i] -= p->vel[i] * frametime; + p->vel[2] -= grav; + break; + + case pt_blob: + for (i = 0; i < 3; i++) + p->vel[i] += p->vel[i] * dvel; + p->vel[2] -= grav; + break; + + case pt_blob2: + for (i = 0; i < 2; i++) + p->vel[i] -= p->vel[i] * dvel; + p->vel[2] -= grav; + break; + + case pt_slowgrav: + case pt_grav: + p->vel[2] -= grav; + break; + } + } + } + + D_EndParticles (); +} diff --git a/libs/video/renderer/sw32/sw32_rsky.c b/libs/video/renderer/sw32/sw32_rsky.c new file mode 100644 index 000000000..943a99c02 --- /dev/null +++ b/libs/video/renderer/sw32/sw32_rsky.c @@ -0,0 +1,270 @@ +/* + r_sky.c + + (description) + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_STRING_H +# include "string.h" +#endif +#ifdef HAVE_STRINGS_H +# include "strings.h" +#endif + +#include "QF/sys.h" + +#include "r_local.h" + + +int iskyspeed = 8; +int iskyspeed2 = 2; +float skyspeed, skyspeed2; + +float skytime; + +byte *r_skysource; + +int r_skymade; +int r_skydirect; // not used? + + +// TODO: clean up these routines + +/* +byte bottomsky[128 * 131]; +byte bottommask[128 * 131]; +byte newsky[128 * 256]; // newsky and topsky both pack in here, + // 128 bytes of newsky on the left of + // each scan, 128 bytes of topsky on + // the right, because the low-level + // drawers need 256-byte scan widths +*/ +byte skydata[128*256]; // sky layers for making skytex +byte skytex[128*256*4]; // current sky texture + + +/* + R_InitSky + + A sky texture is 256*128, with the right side being a masked overlay +*/ +void +R_InitSky (texture_t *mt) +{ + /* + int i, j; + byte *src; + + src = (byte *) mt + mt->offsets[0]; + + for (i = 0; i < 128; i++) + for (j = 0; j < 128; j++) + newsky[(i * 256) + j + 128] = src[i * 256 + j + 128]; + + for (i = 0; i < 128; i++) { + for (j = 0; j < 131; j++) { + if (src[i * 256 + (j & 0x7F)]) { + bottomsky[(i * 131) + j] = src[i * 256 + (j & 0x7F)]; + bottommask[(i * 131) + j] = 0; + } else { + bottomsky[(i * 131) + j] = 0; + bottommask[(i * 131) + j] = 0xff; + } + } + } + + r_skysource = newsky; + */ + + // LordHavoc: save sky for use + memcpy(skydata, (byte *) mt + mt->offsets[0], 128*256); + r_skysource = skytex; +} + +void +R_MakeSky (void) +{ + int x, y, xshift1, yshift1, xshift2, yshift2; + byte *base1, *base2; + static int xlast = -1, ylast = -1; + + xshift2 = skytime * skyspeed * 2.0f; + yshift2 = skytime * skyspeed * 2.0f; + + if ((xshift2 == xlast) && (yshift2 == ylast)) + return; + + xlast = xshift2; + ylast = yshift2; + xshift1 = xshift2 >> 1; + yshift1 = yshift2 >> 1; + + switch(r_pixbytes) + { + case 1: + { + byte *out = (byte *) skytex; + for (y = 0;y < 128;y++) + { + base1 = &skydata[((y + yshift1) & 127) * 256]; + base2 = &skydata[((y + yshift2) & 127) * 256 + 128]; + for (x = 0;x < 128;x++) + { + if (base1[(x + xshift1) & 127]) + *out = base1[(x + xshift1) & 127]; + else + *out = base2[(x + xshift2) & 127]; + out++; + } + out += 128; + } + } + break; + case 2: + { + unsigned short *out = (unsigned short *) skytex; + for (y = 0;y < 128;y++) + { + base1 = &skydata[((y + yshift1) & 127) * 256]; + base2 = &skydata[((y + yshift2) & 127) * 256 + 128]; + for (x = 0;x < 128;x++) + { + if (base1[(x + xshift1) & 127]) + *out = d_8to16table[base1[(x + xshift1) & 127]]; + else + *out = d_8to16table[base2[(x + xshift2) & 127]]; + out++; + } + out += 128; + } + } + break; + case 4: + { + unsigned int *out = (unsigned int *) skytex; + for (y = 0;y < 128;y++) + { + base1 = &skydata[((y + yshift1) & 127) * 256]; + base2 = &skydata[((y + yshift2) & 127) * 256 + 128]; + for (x = 0;x < 128;x++) + { + if (base1[(x + xshift1) & 127]) + *out = d_8to24table[base1[(x + xshift1) & 127]]; + else + *out = d_8to24table[base2[(x + xshift2) & 127]]; + out++; + } + out += 128; + } + } + break; + default: + Sys_Error("R_MakeSky: unsupported r_pixbytes %i\n", r_pixbytes); + } + /* + int x, y; + int ofs, baseofs; + int xshift, yshift; + unsigned int *pnewsky; + static int xlast = -1, ylast = -1; + + xshift = skytime * skyspeed; + yshift = skytime * skyspeed; + + if ((xshift == xlast) && (yshift == ylast)) + return; + + xlast = xshift; + ylast = yshift; + + pnewsky = (unsigned int *) &newsky[0]; + + for (y = 0; y < SKYSIZE; y++) { + baseofs = ((y + yshift) & SKYMASK) * 131; + +// FIXME: clean this up +#if UNALIGNED_OK + for (x = 0; x < SKYSIZE; x += 4) { + ofs = baseofs + ((x + xshift) & SKYMASK); + + // PORT: unaligned dword access to bottommask and bottomsky + + *pnewsky = (*(pnewsky + (128 / sizeof (unsigned int))) & + *(unsigned int *) &bottommask[ofs]) | + *(unsigned int *) &bottomsky[ofs]; + + pnewsky++; + } +#else + for (x = 0; x < SKYSIZE; x++) { + ofs = baseofs + ((x + xshift) & SKYMASK); + + *(byte *) pnewsky = (*((byte *) pnewsky + 128) & + *(byte *) & bottommask[ofs]) | + *(byte *) & bottomsky[ofs]; + pnewsky = (unsigned int *) ((byte *) pnewsky + 1); + } +#endif + + pnewsky += 128 / sizeof (unsigned int); + } + */ + + r_skymade = 1; +} + +void +R_SetSkyFrame (void) +{ + int g, s1, s2; + float temp; + + skyspeed = iskyspeed; + skyspeed2 = iskyspeed2; + + g = GreatestCommonDivisor (iskyspeed, iskyspeed2); + s1 = iskyspeed / g; + s2 = iskyspeed2 / g; + temp = SKYSIZE * s1 * s2; + + skytime = r_realtime - ((int) (r_realtime / temp) * temp); + + + r_skymade = 0; +} + +/* + R_LoadSkys + + Stub function for loading a skybox. Currently we only have support for + skyboxes in GL targets, so we just do nothing here. --KB +*/ +void +R_LoadSkys (const char *name) +{ +} diff --git a/libs/video/renderer/sw32/sw32_rsprite.c b/libs/video/renderer/sw32/sw32_rsprite.c new file mode 100644 index 000000000..200bad7b5 --- /dev/null +++ b/libs/video/renderer/sw32/sw32_rsprite.c @@ -0,0 +1,381 @@ +/* + sw32_rsprite.c + + (description) + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include + +#include "QF/console.h" +#include "QF/render.h" +#include "QF/sys.h" + +#include "r_local.h" + +static int clip_current; +static vec5_t clip_verts[2][MAXWORKINGVERTS]; +static int sprite_width, sprite_height; + +spritedesc_t r_spritedesc; + + +void +R_RotateSprite (float beamlength) +{ + vec3_t vec; + + if (beamlength == 0.0) + return; + + VectorScale (r_spritedesc.vpn, -beamlength, vec); + VectorAdd (r_entorigin, vec, r_entorigin); + VectorSubtract (modelorg, vec, modelorg); +} + +/* + R_ClipSpriteFace + + Clips the winding at clip_verts[clip_current] and changes clip_current + Throws out the back side +*/ +int +R_ClipSpriteFace (int nump, clipplane_t *pclipplane) +{ + int i, outcount; + float dists[MAXWORKINGVERTS + 1]; + float frac, clipdist, *pclipnormal; + float *in, *instep, *outstep, *vert2; + + clipdist = pclipplane->dist; + pclipnormal = pclipplane->normal; + +// calc dists + if (clip_current) { + in = clip_verts[1][0]; + outstep = clip_verts[0][0]; + clip_current = 0; + } else { + in = clip_verts[0][0]; + outstep = clip_verts[1][0]; + clip_current = 1; + } + + instep = in; + for (i = 0; i < nump; i++, instep += sizeof (vec5_t) / sizeof (float)) { + dists[i] = DotProduct (instep, pclipnormal) - clipdist; + } + + // handle wraparound case + dists[nump] = dists[0]; + memcpy (instep, in, sizeof (vec5_t)); + + // clip the winding + instep = in; + outcount = 0; + + for (i = 0; i < nump; i++, instep += sizeof (vec5_t) / sizeof (float)) { + if (dists[i] >= 0) { + memcpy (outstep, instep, sizeof (vec5_t)); + outstep += sizeof (vec5_t) / sizeof (float); + + outcount++; + } + + if (dists[i] == 0 || dists[i + 1] == 0) + continue; + + if ((dists[i] > 0) == (dists[i + 1] > 0)) + continue; + + // split it into a new vertex + frac = dists[i] / (dists[i] - dists[i + 1]); + + vert2 = instep + sizeof (vec5_t) / sizeof (float); + + outstep[0] = instep[0] + frac * (vert2[0] - instep[0]); + outstep[1] = instep[1] + frac * (vert2[1] - instep[1]); + outstep[2] = instep[2] + frac * (vert2[2] - instep[2]); + outstep[3] = instep[3] + frac * (vert2[3] - instep[3]); + outstep[4] = instep[4] + frac * (vert2[4] - instep[4]); + + outstep += sizeof (vec5_t) / sizeof (float); + + outcount++; + } + + return outcount; +} + +void +R_SetupAndDrawSprite (void) +{ + int i, nump; + float dot, scale, *pv; + vec5_t *pverts; + vec3_t left, up, right, down, transformed, local; + emitpoint_t outverts[MAXWORKINGVERTS + 1], *pout; + + dot = DotProduct (r_spritedesc.vpn, modelorg); + + // backface cull + if (dot >= 0) + return; + + // build the sprite poster in worldspace + VectorScale (r_spritedesc.vright, r_spritedesc.pspriteframe->right, right); + VectorScale (r_spritedesc.vup, r_spritedesc.pspriteframe->up, up); + VectorScale (r_spritedesc.vright, r_spritedesc.pspriteframe->left, left); + VectorScale (r_spritedesc.vup, r_spritedesc.pspriteframe->down, down); + + pverts = clip_verts[0]; + + pverts[0][0] = r_entorigin[0] + up[0] + left[0]; + pverts[0][1] = r_entorigin[1] + up[1] + left[1]; + pverts[0][2] = r_entorigin[2] + up[2] + left[2]; + pverts[0][3] = 0; + pverts[0][4] = 0; + + pverts[1][0] = r_entorigin[0] + up[0] + right[0]; + pverts[1][1] = r_entorigin[1] + up[1] + right[1]; + pverts[1][2] = r_entorigin[2] + up[2] + right[2]; + pverts[1][3] = sprite_width; + pverts[1][4] = 0; + + pverts[2][0] = r_entorigin[0] + down[0] + right[0]; + pverts[2][1] = r_entorigin[1] + down[1] + right[1]; + pverts[2][2] = r_entorigin[2] + down[2] + right[2]; + pverts[2][3] = sprite_width; + pverts[2][4] = sprite_height; + + pverts[3][0] = r_entorigin[0] + down[0] + left[0]; + pverts[3][1] = r_entorigin[1] + down[1] + left[1]; + pverts[3][2] = r_entorigin[2] + down[2] + left[2]; + pverts[3][3] = 0; + pverts[3][4] = sprite_height; + + // clip to the frustum in worldspace + nump = 4; + clip_current = 0; + + for (i = 0; i < 4; i++) { + nump = R_ClipSpriteFace (nump, &view_clipplanes[i]); + if (nump < 3) + return; + if (nump >= MAXWORKINGVERTS) + Sys_Error ("R_SetupAndDrawSprite: too many points"); + } + + // transform vertices into viewspace and project + pv = &clip_verts[clip_current][0][0]; + r_spritedesc.nearzi = -999999; + + for (i = 0; i < nump; i++) { + VectorSubtract (pv, r_origin, local); + TransformVector (local, transformed); + + if (transformed[2] < NEAR_CLIP) + transformed[2] = NEAR_CLIP; + + pout = &outverts[i]; + pout->zi = 1.0 / transformed[2]; + if (pout->zi > r_spritedesc.nearzi) + r_spritedesc.nearzi = pout->zi; + + pout->s = pv[3]; + pout->t = pv[4]; + + scale = xscale * pout->zi; + pout->u = (xcenter + scale * transformed[0]); + + scale = yscale * pout->zi; + pout->v = (ycenter - scale * transformed[1]); + + pv += sizeof (vec5_t) / sizeof (*pv); + } + + // draw it + r_spritedesc.nump = nump; + r_spritedesc.pverts = outverts; + D_DrawSprite (); +} + +mspriteframe_t * +R_GetSpriteframe (msprite_t *psprite) +{ + mspritegroup_t *pspritegroup; + mspriteframe_t *pspriteframe; + int i, numframes, frame; + float *pintervals, fullinterval, targettime, time; + + frame = currententity->frame; + + if ((frame >= psprite->numframes) || (frame < 0)) { + Con_Printf ("R_DrawSprite: no such frame %d\n", frame); + frame = 0; + } + + if (psprite->frames[frame].type == SPR_SINGLE) { + pspriteframe = psprite->frames[frame].frameptr; + } else { + pspritegroup = (mspritegroup_t *) psprite->frames[frame].frameptr; + pintervals = pspritegroup->intervals; + numframes = pspritegroup->numframes; + fullinterval = pintervals[numframes - 1]; + + time = r_realtime + currententity->syncbase; + + // when loading in Mod_LoadSpriteGroup, we guaranteed all interval + // values + // are positive, so we don't have to worry about division by 0 + targettime = time - ((int) (time / fullinterval)) * fullinterval; + + for (i = 0; i < (numframes - 1); i++) { + if (pintervals[i] > targettime) + break; + } + + pspriteframe = pspritegroup->frames[i]; + } + + return pspriteframe; +} + +void +R_DrawSprite (void) +{ + int i; + msprite_t *psprite; + vec3_t tvec; + float dot, angle, sr, cr; + + psprite = currententity->model->cache.data; + + r_spritedesc.pspriteframe = R_GetSpriteframe (psprite); + + sprite_width = r_spritedesc.pspriteframe->width; + sprite_height = r_spritedesc.pspriteframe->height; + + // TODO: make this caller-selectable + if (psprite->type == SPR_FACING_UPRIGHT) { + // generate the sprite's axes, with vup straight up in worldspace, and + // r_spritedesc.vright perpendicular to modelorg. + // This will not work if the view direction is very close to straight + // up or down, because the cross product will be between two nearly + // parallel vectors and starts to approach an undefined state, so we + // don't draw if the two vectors are less than 1 degree apart + tvec[0] = -modelorg[0]; + tvec[1] = -modelorg[1]; + tvec[2] = -modelorg[2]; + VectorNormalize (tvec); + dot = tvec[2]; // same as DotProduct (tvec, + // r_spritedesc.vup) because + // r_spritedesc.vup is 0, 0, 1 + if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) = + // 0.999848 + return; + r_spritedesc.vup[0] = 0; + r_spritedesc.vup[1] = 0; + r_spritedesc.vup[2] = 1; + r_spritedesc.vright[0] = tvec[1]; +// CrossProduct(r_spritedesc.vup, -modelorg, r_spritedesc.vright) + r_spritedesc.vright[1] = -tvec[0]; + r_spritedesc.vright[2] = 0; + VectorNormalize (r_spritedesc.vright); + r_spritedesc.vpn[0] = -r_spritedesc.vright[1]; + r_spritedesc.vpn[1] = r_spritedesc.vright[0]; + r_spritedesc.vpn[2] = 0; +// CrossProduct (r_spritedesc.vright, r_spritedesc.vup, +// r_spritedesc.vpn) + } else if (psprite->type == SPR_VP_PARALLEL) { + // generate the sprite's axes, completely parallel to the viewplane. + // There are no problem situations, because the sprite is always in the + // same position relative to the viewer + for (i = 0; i < 3; i++) { + r_spritedesc.vup[i] = vup[i]; + r_spritedesc.vright[i] = vright[i]; + r_spritedesc.vpn[i] = vpn[i]; + } + } else if (psprite->type == SPR_VP_PARALLEL_UPRIGHT) { + // generate the sprite's axes, with vup straight up in worldspace, and + // r_spritedesc.vright parallel to the viewplane. + // This will not work if the view direction is very close to straight + // up or down, because the cross product will be between two nearly + // parallel vectors and starts to approach an undefined state, so we + // don't draw if the two vectors are less than 1 degree apart + dot = vpn[2]; // same as DotProduct (vpn, + // r_spritedesc.vup) because + // r_spritedesc.vup is 0, 0, 1 + if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) = + // 0.999848 + return; + r_spritedesc.vup[0] = 0; + r_spritedesc.vup[1] = 0; + r_spritedesc.vup[2] = 1; + r_spritedesc.vright[0] = vpn[1]; +// CrossProduct (r_spritedesc.vup, vpn, + r_spritedesc.vright[1] = -vpn[0]; // r_spritedesc.vright) + r_spritedesc.vright[2] = 0; + VectorNormalize (r_spritedesc.vright); + r_spritedesc.vpn[0] = -r_spritedesc.vright[1]; + r_spritedesc.vpn[1] = r_spritedesc.vright[0]; + r_spritedesc.vpn[2] = 0; + // CrossProduct (r_spritedesc.vright, r_spritedesc.vup, + // r_spritedesc.vpn) + } else if (psprite->type == SPR_ORIENTED) { + // generate the sprite's axes, according to the sprite's world + // orientation + AngleVectors (currententity->angles, r_spritedesc.vpn, + r_spritedesc.vright, r_spritedesc.vup); + } else if (psprite->type == SPR_VP_PARALLEL_ORIENTED) { + // generate the sprite's axes, parallel to the viewplane, but rotated + // in that plane around the center according to the sprite entity's + // roll angle. So vpn stays the same, but vright and vup rotate + angle = currententity->angles[ROLL] * (M_PI * 2 / 360); + sr = sin (angle); + cr = cos (angle); + + for (i = 0; i < 3; i++) { + r_spritedesc.vpn[i] = vpn[i]; + r_spritedesc.vright[i] = vright[i] * cr + vup[i] * sr; + r_spritedesc.vup[i] = vright[i] * -sr + vup[i] * cr; + } + } else { + Sys_Error ("R_DrawSprite: Bad sprite type %d", psprite->type); + } + + R_RotateSprite (psprite->beamlength); + + R_SetupAndDrawSprite (); +} diff --git a/libs/video/renderer/sw32/sw32_rsurf.c b/libs/video/renderer/sw32/sw32_rsurf.c new file mode 100644 index 000000000..52ee0781c --- /dev/null +++ b/libs/video/renderer/sw32/sw32_rsurf.c @@ -0,0 +1,916 @@ +/* + sw32_rsurf.c + + surface-related refresh code + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/render.h" +#include "QF/sys.h" + +#include "compat.h" +#include "r_local.h" + +drawsurf_t r_drawsurf; + +int lightleft, sourcesstep, blocksize, sourcetstep; +int lightdelta, lightdeltastep; +int lightright, lightleftstep, lightrightstep, blockdivshift; +unsigned int blockdivmask; +byte *prowdestbase; +byte *psource; +int surfrowbytes; // used by ASM files +int *r_lightptr; +int r_stepback; +int r_lightwidth; +int r_numhblocks, r_numvblocks; +byte *r_source, *r_sourcemax; + +void R_DrawSurfaceBlock8_mip0 (void); +void R_DrawSurfaceBlock8_mip1 (void); +void R_DrawSurfaceBlock8_mip2 (void); +void R_DrawSurfaceBlock8_mip3 (void); +void R_DrawSurfaceBlock16_mip0 (void); +void R_DrawSurfaceBlock16_mip1 (void); +void R_DrawSurfaceBlock16_mip2 (void); +void R_DrawSurfaceBlock16_mip3 (void); +void R_DrawSurfaceBlock32_mip0 (void); +void R_DrawSurfaceBlock32_mip1 (void); +void R_DrawSurfaceBlock32_mip2 (void); +void R_DrawSurfaceBlock32_mip3 (void); + +static void (*surfmiptable8[4]) (void) = { + R_DrawSurfaceBlock8_mip0, + R_DrawSurfaceBlock8_mip1, + R_DrawSurfaceBlock8_mip2, + R_DrawSurfaceBlock8_mip3 +}; + +static void (*surfmiptable16[4]) (void) = { + R_DrawSurfaceBlock16_mip0, + R_DrawSurfaceBlock16_mip1, + R_DrawSurfaceBlock16_mip2, + R_DrawSurfaceBlock16_mip3 +}; + +static void (*surfmiptable32[4]) (void) = { + R_DrawSurfaceBlock32_mip0, + R_DrawSurfaceBlock32_mip1, + R_DrawSurfaceBlock32_mip2, + R_DrawSurfaceBlock32_mip3 +}; + +int blocklights[18 * 18]; + + +void +R_AddDynamicLights (void) +{ + msurface_t *surf; + int lnum; + int sd, td; + float dist, rad, minlight; + vec3_t impact, local, lightorigin; + int s, t; + int i; + int smax, tmax; + mtexinfo_t *tex; + + surf = r_drawsurf.surf; + smax = (surf->extents[0] >> 4) + 1; + tmax = (surf->extents[1] >> 4) + 1; + tex = surf->texinfo; + + for (lnum = 0; lnum < MAX_DLIGHTS; lnum++) { + if (!(surf->dlightbits & (1 << lnum))) + continue; // not lit by this light + + VectorSubtract (r_dlights[lnum].origin, currententity->origin, + lightorigin); + rad = r_dlights[lnum].radius; + dist = DotProduct (lightorigin, surf->plane->normal) - + surf->plane->dist; + rad -= fabs (dist); + minlight = r_dlights[lnum].minlight; + if (rad < minlight) + continue; + minlight = rad - minlight; + + for (i = 0; i < 3; i++) + impact[i] = lightorigin[i] - surf->plane->normal[i] * dist; + + local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3]; + local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3]; + + local[0] -= surf->texturemins[0]; + local[1] -= surf->texturemins[1]; + + for (t = 0; t < tmax; t++) { + td = local[1] - t * 16; + if (td < 0) + td = -td; + for (s = 0; s < smax; s++) { + sd = local[0] - s * 16; + if (sd < 0) + sd = -sd; + if (sd > td) + dist = sd + (td >> 1); + else + dist = td + (sd >> 1); + if (dist < minlight) + blocklights[t * smax + s] += (rad - dist) * 256; + } + } + } +} + +/* + R_BuildLightMap + + Combine and scale multiple lightmaps into the 8.8 format in blocklights +*/ +void +R_BuildLightMap (void) +{ + int smax, tmax; + int t; + int i, size; + byte *lightmap; + unsigned int scale; + int maps; + msurface_t *surf; + + surf = r_drawsurf.surf; + + smax = (surf->extents[0] >> 4) + 1; + tmax = (surf->extents[1] >> 4) + 1; + size = smax * tmax; + lightmap = surf->samples; + + if (!r_worldentity.model->lightdata) { + for (i = 0; i < size; i++) + blocklights[i] = 0; + return; + } + // clear to ambient + for (i = 0; i < size; i++) + blocklights[i] = r_refdef.ambientlight << 8; + + // add all the lightmaps + if (lightmap) + for (maps = 0; maps < MAXLIGHTMAPS && surf->styles[maps] != 255; + maps++) { + scale = r_drawsurf.lightadj[maps]; // 8.8 fraction + for (i = 0; i < size; i++) + blocklights[i] += lightmap[i] * scale; + lightmap += size; // skip to next lightmap + } + // add all the dynamic lights + if (surf->dlightframe == r_framecount) + R_AddDynamicLights (); + + // LordHavoc: changed to positive (not inverse) lighting + for (i = 0; i < size; i++) { + t = bound(256, blocklights[i] >> (8 - VID_CBITS), + 256 * (VID_GRADES - 1)); + blocklights[i] = t; + } +/* + // bound, invert, and shift + for (i = 0; i < size; i++) { + t = (255 * 256 - blocklights[i]) >> (8 - VID_CBITS); + + if (t < (1 << 6)) + t = (1 << 6); + + blocklights[i] = t; + } +*/ +} + +/* + R_TextureAnimation + + Returns the proper texture for a given time and base texture +*/ +texture_t * +R_TextureAnimation (texture_t *base) +{ + int relative; + int count; + + if (currententity->frame) { + if (base->alternate_anims) + base = base->alternate_anims; + } + + if (!base->anim_total) + return base; + + relative = (int) (r_realtime * 10) % base->anim_total; + + count = 0; + while (base->anim_min > relative || base->anim_max <= relative) { + base = base->anim_next; + if (!base) + Sys_Error ("R_TextureAnimation: broken cycle"); + if (++count > 100) + Sys_Error ("R_TextureAnimation: infinite cycle"); + } + + return base; +} + +void +R_DrawSurface (void) +{ + unsigned char *basetptr; + int smax, tmax, twidth; + int u; + int soffset, basetoffset, texwidth; + int horzblockstep; + byte *pcolumndest; + void (*pblockdrawer) (void); + texture_t *mt; + + // calculate the lightings + R_BuildLightMap (); + + surfrowbytes = r_drawsurf.rowbytes; + + mt = r_drawsurf.texture; + + r_source = (byte *) mt + mt->offsets[r_drawsurf.surfmip]; + +// the fractional light values should range from 0 to (VID_GRADES - 1) << 16 +// from a source range of 0 - 255 + + texwidth = mt->width >> r_drawsurf.surfmip; + + blocksize = 16 >> r_drawsurf.surfmip; + blockdivshift = 4 - r_drawsurf.surfmip; + blockdivmask = (1 << blockdivshift) - 1; + + r_lightwidth = (r_drawsurf.surf->extents[0] >> 4) + 1; + + r_numhblocks = r_drawsurf.surfwidth >> blockdivshift; + r_numvblocks = r_drawsurf.surfheight >> blockdivshift; + +//============================== + + smax = mt->width >> r_drawsurf.surfmip; + twidth = texwidth; + tmax = mt->height >> r_drawsurf.surfmip; + sourcetstep = texwidth; + r_stepback = tmax * twidth; + + soffset = r_drawsurf.surf->texturemins[0]; + basetoffset = r_drawsurf.surf->texturemins[1]; + + switch (r_pixbytes) { + case 1: + pblockdrawer = surfmiptable8[r_drawsurf.surfmip]; + break; + case 2: + pblockdrawer = surfmiptable16[r_drawsurf.surfmip]; + break; + case 4: + pblockdrawer = surfmiptable32[r_drawsurf.surfmip]; + break; + default: + Sys_Error("R_DrawSurface: unsupported r_pixbytes %i\n", r_pixbytes); + pblockdrawer = NULL; + } + + horzblockstep = blocksize * r_pixbytes; + + r_sourcemax = r_source + (tmax * smax); + + // << 16 components are to guarantee positive values for % + basetptr = r_source + (((basetoffset >> r_drawsurf.surfmip) + + (tmax << 16)) % tmax) * twidth; + soffset = (((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax); + + pcolumndest = (byte *) r_drawsurf.surfdat; + + for (u = 0; u < r_numhblocks; u++) { + r_lightptr = blocklights + u; + + prowdestbase = pcolumndest; + + psource = basetptr + soffset; + + (*pblockdrawer) (); + + soffset = soffset + blocksize; + if (soffset >= smax) + soffset = 0; + + pcolumndest += horzblockstep; + } +} + +//============================================================================= + +void +R_DrawSurfaceBlock8_mip0 (void) +{ + int v, i, b, lightstep, light; + unsigned char pix, *prowdest; + + prowdest = prowdestbase; + + for (v = 0; v < r_numvblocks; v++) { + // FIXME: make these locals? + // FIXME: use delta rather than both right and left, like ASM? + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> 4; + lightrightstep = (r_lightptr[1] - lightright) >> 4; + + for (i = 0; i < 16; i++) { + lightstep = (lightleft - lightright) >> 4; + + light = lightright; + + for (b = 15; b >= 0; b--) { + pix = psource[b]; + prowdest[b] = vid.colormap8[(light & 0xFF00) + pix]; + light += lightstep; + } + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += surfrowbytes; + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + +void +R_DrawSurfaceBlock8_mip1 (void) +{ + int v, i, b, lightstep, light; + unsigned char pix, *prowdest; + + prowdest = prowdestbase; + + for (v = 0; v < r_numvblocks; v++) { + // FIXME: make these locals? + // FIXME: use delta rather than both right and left, like ASM? + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> 3; + lightrightstep = (r_lightptr[1] - lightright) >> 3; + + for (i = 0; i < 8; i++) { + lightstep = (lightleft - lightright) >> 3; + + light = lightright; + + for (b = 7; b >= 0; b--) { + pix = psource[b]; + prowdest[b] = vid.colormap8[(light & 0xFF00) + pix]; + light += lightstep; + } + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += surfrowbytes; + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + +void +R_DrawSurfaceBlock8_mip2 (void) +{ + int v, i, b, lightstep, light; + unsigned char pix, *prowdest; + + prowdest = prowdestbase; + + for (v = 0; v < r_numvblocks; v++) { + // FIXME: make these locals? + // FIXME: use delta rather than both right and left, like ASM? + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> 2; + lightrightstep = (r_lightptr[1] - lightright) >> 2; + + for (i = 0; i < 4; i++) { + lightstep = (lightleft - lightright) >> 2; + + light = lightright; + + for (b = 3; b >= 0; b--) { + pix = psource[b]; + prowdest[b] = vid.colormap8[(light & 0xFF00) + pix]; + light += lightstep; + } + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += surfrowbytes; + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + +void +R_DrawSurfaceBlock8_mip3 (void) +{ + int v, i, b, lightstep, light; + unsigned char pix, *prowdest; + + prowdest = prowdestbase; + + for (v = 0; v < r_numvblocks; v++) { + // FIXME: make these locals? + // FIXME: use delta rather than both right and left, like ASM? + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> 1; + lightrightstep = (r_lightptr[1] - lightright) >> 1; + + for (i = 0; i < 2; i++) { + lightstep = (lightleft - lightright) >> 1; + + light = lightright; + + for (b = 1; b >= 0; b--) { + pix = psource[b]; + prowdest[b] = vid.colormap8[(light & 0xFF00) + pix]; + light += lightstep; + } + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += surfrowbytes; + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + +void +R_DrawSurfaceBlock16_mip0 (void) +{ + int k, v; + int lightstep, light; + unsigned short *prowdest; + + prowdest = (unsigned short *) prowdestbase; + + for (v = 0; v < r_numvblocks; v++) + { + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> 4; + lightrightstep = (r_lightptr[1] - lightright) >> 4; + + for (k = 0; k < 16; k++) + { + light = lightleft; + lightstep = (lightright - lightleft) >> 4; + + prowdest[0] = vid.colormap16[(light & 0xFF00) + psource[0]]; + light += lightstep; + prowdest[1] = vid.colormap16[(light & 0xFF00) + psource[1]]; + light += lightstep; + prowdest[2] = vid.colormap16[(light & 0xFF00) + psource[2]]; + light += lightstep; + prowdest[3] = vid.colormap16[(light & 0xFF00) + psource[3]]; + light += lightstep; + prowdest[4] = vid.colormap16[(light & 0xFF00) + psource[4]]; + light += lightstep; + prowdest[5] = vid.colormap16[(light & 0xFF00) + psource[5]]; + light += lightstep; + prowdest[6] = vid.colormap16[(light & 0xFF00) + psource[6]]; + light += lightstep; + prowdest[7] = vid.colormap16[(light & 0xFF00) + psource[7]]; + light += lightstep; + prowdest[8] = vid.colormap16[(light & 0xFF00) + psource[8]]; + light += lightstep; + prowdest[9] = vid.colormap16[(light & 0xFF00) + psource[9]]; + light += lightstep; + prowdest[10] = vid.colormap16[(light & 0xFF00) + psource[10]]; + light += lightstep; + prowdest[11] = vid.colormap16[(light & 0xFF00) + psource[11]]; + light += lightstep; + prowdest[12] = vid.colormap16[(light & 0xFF00) + psource[12]]; + light += lightstep; + prowdest[13] = vid.colormap16[(light & 0xFF00) + psource[13]]; + light += lightstep; + prowdest[14] = vid.colormap16[(light & 0xFF00) + psource[14]]; + light += lightstep; + prowdest[15] = vid.colormap16[(light & 0xFF00) + psource[15]]; + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += (surfrowbytes >> 1); + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + +void +R_DrawSurfaceBlock16_mip1 (void) +{ + int k, v; + int lightstep, light; + unsigned short *prowdest; + + prowdest = (unsigned short *) prowdestbase; + + for (v = 0; v < r_numvblocks; v++) + { + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> 3; + lightrightstep = (r_lightptr[1] - lightright) >> 3; + + for (k = 0; k < 8; k++) + { + light = lightleft; + lightstep = (lightright - lightleft) >> 3; + + prowdest[0] = vid.colormap16[(light & 0xFF00) + psource[0]]; + light += lightstep; + prowdest[1] = vid.colormap16[(light & 0xFF00) + psource[1]]; + light += lightstep; + prowdest[2] = vid.colormap16[(light & 0xFF00) + psource[2]]; + light += lightstep; + prowdest[3] = vid.colormap16[(light & 0xFF00) + psource[3]]; + light += lightstep; + prowdest[4] = vid.colormap16[(light & 0xFF00) + psource[4]]; + light += lightstep; + prowdest[5] = vid.colormap16[(light & 0xFF00) + psource[5]]; + light += lightstep; + prowdest[6] = vid.colormap16[(light & 0xFF00) + psource[6]]; + light += lightstep; + prowdest[7] = vid.colormap16[(light & 0xFF00) + psource[7]]; + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += (surfrowbytes >> 1); + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + +void +R_DrawSurfaceBlock16_mip2 (void) +{ + int k, v; + int lightstep, light; + unsigned short *prowdest; + + prowdest = (unsigned short *) prowdestbase; + + for (v = 0; v < r_numvblocks; v++) + { + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> 2; + lightrightstep = (r_lightptr[1] - lightright) >> 2; + + for (k = 0; k < 4; k++) + { + light = lightleft; + lightstep = (lightright - lightleft) >> 2; + + prowdest[0] = vid.colormap16[(light & 0xFF00) + psource[0]]; + light += lightstep; + prowdest[1] = vid.colormap16[(light & 0xFF00) + psource[1]]; + light += lightstep; + prowdest[2] = vid.colormap16[(light & 0xFF00) + psource[2]]; + light += lightstep; + prowdest[3] = vid.colormap16[(light & 0xFF00) + psource[3]]; + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += (surfrowbytes >> 1); + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + +void +R_DrawSurfaceBlock16_mip3 (void) +{ + int v; + unsigned short *prowdest; + + prowdest = (unsigned short *) prowdestbase; + + for (v = 0; v < r_numvblocks; v++) + { + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> 1; + lightrightstep = (r_lightptr[1] - lightright) >> 1; + + prowdest[0] = vid.colormap16[(lightleft & 0xFF00) + psource[0]]; + prowdest[1] = vid.colormap16[(((lightleft + lightright) >> 1) & + 0xFF00) + psource[1]]; + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += (surfrowbytes >> 1); + + prowdest[0] = vid.colormap16[(lightleft & 0xFF00) + psource[0]]; + prowdest[1] = vid.colormap16[(((lightleft + lightright) >> 1) & + 0xFF00) + psource[1]]; + psource += sourcetstep; + prowdest += (surfrowbytes >> 1); + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + +void +R_DrawSurfaceBlock32_mip0 (void) +{ + int k, v; + int lightstep, light; + unsigned int *prowdest; + + prowdest = (unsigned int *) prowdestbase; + + for (v = 0; v < r_numvblocks; v++) + { + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> 4; + lightrightstep = (r_lightptr[1] - lightright) >> 4; + + for (k = 0; k < 16; k++) + { + light = lightleft; + lightstep = (lightright - lightleft) >> 4; + + prowdest[0] = vid.colormap32[(light & 0xFF00) + psource[0]]; + light += lightstep; + prowdest[1] = vid.colormap32[(light & 0xFF00) + psource[1]]; + light += lightstep; + prowdest[2] = vid.colormap32[(light & 0xFF00) + psource[2]]; + light += lightstep; + prowdest[3] = vid.colormap32[(light & 0xFF00) + psource[3]]; + light += lightstep; + prowdest[4] = vid.colormap32[(light & 0xFF00) + psource[4]]; + light += lightstep; + prowdest[5] = vid.colormap32[(light & 0xFF00) + psource[5]]; + light += lightstep; + prowdest[6] = vid.colormap32[(light & 0xFF00) + psource[6]]; + light += lightstep; + prowdest[7] = vid.colormap32[(light & 0xFF00) + psource[7]]; + light += lightstep; + prowdest[8] = vid.colormap32[(light & 0xFF00) + psource[8]]; + light += lightstep; + prowdest[9] = vid.colormap32[(light & 0xFF00) + psource[9]]; + light += lightstep; + prowdest[10] = vid.colormap32[(light & 0xFF00) + psource[10]]; + light += lightstep; + prowdest[11] = vid.colormap32[(light & 0xFF00) + psource[11]]; + light += lightstep; + prowdest[12] = vid.colormap32[(light & 0xFF00) + psource[12]]; + light += lightstep; + prowdest[13] = vid.colormap32[(light & 0xFF00) + psource[13]]; + light += lightstep; + prowdest[14] = vid.colormap32[(light & 0xFF00) + psource[14]]; + light += lightstep; + prowdest[15] = vid.colormap32[(light & 0xFF00) + psource[15]]; + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += (surfrowbytes >> 2); + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + +void +R_DrawSurfaceBlock32_mip1 (void) +{ + int k, v; + int lightstep, light; + unsigned int *prowdest; + + prowdest = (unsigned int *) prowdestbase; + + for (v = 0; v < r_numvblocks; v++) + { + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> 3; + lightrightstep = (r_lightptr[1] - lightright) >> 3; + + for (k = 0; k < 8; k++) + { + light = lightleft; + lightstep = (lightright - lightleft) >> 3; + + prowdest[0] = vid.colormap32[(light & 0xFF00) + psource[0]]; + light += lightstep; + prowdest[1] = vid.colormap32[(light & 0xFF00) + psource[1]]; + light += lightstep; + prowdest[2] = vid.colormap32[(light & 0xFF00) + psource[2]]; + light += lightstep; + prowdest[3] = vid.colormap32[(light & 0xFF00) + psource[3]]; + light += lightstep; + prowdest[4] = vid.colormap32[(light & 0xFF00) + psource[4]]; + light += lightstep; + prowdest[5] = vid.colormap32[(light & 0xFF00) + psource[5]]; + light += lightstep; + prowdest[6] = vid.colormap32[(light & 0xFF00) + psource[6]]; + light += lightstep; + prowdest[7] = vid.colormap32[(light & 0xFF00) + psource[7]]; + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += (surfrowbytes >> 2); + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + +void +R_DrawSurfaceBlock32_mip2 (void) +{ + int k, v; + int lightstep, light; + unsigned int *prowdest; + + prowdest = (unsigned int *) prowdestbase; + + for (v = 0; v < r_numvblocks; v++) + { + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> 2; + lightrightstep = (r_lightptr[1] - lightright) >> 2; + + for (k = 0; k < 4; k++) + { + light = lightleft; + lightstep = (lightright - lightleft) >> 2; + + prowdest[0] = vid.colormap32[(light & 0xFF00) + psource[0]]; + light += lightstep; + prowdest[1] = vid.colormap32[(light & 0xFF00) + psource[1]]; + light += lightstep; + prowdest[2] = vid.colormap32[(light & 0xFF00) + psource[2]]; + light += lightstep; + prowdest[3] = vid.colormap32[(light & 0xFF00) + psource[3]]; + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += (surfrowbytes >> 2); + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + +void +R_DrawSurfaceBlock32_mip3 (void) +{ + int v; + unsigned int *prowdest; + + prowdest = (unsigned int *) prowdestbase; + + for (v = 0; v < r_numvblocks; v++) + { + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> 1; + lightrightstep = (r_lightptr[1] - lightright) >> 1; + + prowdest[0] = vid.colormap32[(lightleft & 0xFF00) + psource[0]]; + prowdest[1] = vid.colormap32[(((lightleft + lightright) >> 1) & + 0xFF00) + psource[1]]; + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += (surfrowbytes >> 2); + + prowdest[0] = vid.colormap32[(lightleft & 0xFF00) + psource[0]]; + prowdest[1] = vid.colormap32[(((lightleft + lightright) >> 1) & + 0xFF00) + psource[1]]; + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += (surfrowbytes >> 2); + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + +/* +void +R_DrawSurfaceBlock32 (void) +{ + int k, v; + int lightstep, light; + unsigned int *prowdest; + + prowdest = prowdestbase; + + for (v = 0; v < r_numvblocks; v++) { + + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> blockdivshift; + lightrightstep = (r_lightptr[1] - lightright) >> blockdivshift; + + for (k = 0; k < blocksize; k++) { + int b; + + lightstep = (lightright - lightleft) >> blockdivshift; + + light = lightleft; + + for (b = 0;b < blocksize;b++, light += lightstep) + prowdest[b] = vid.colormap32[(light & 0xFF00) + psource[b]]; + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += (surfrowbytes >> 2); + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} +*/ diff --git a/libs/video/renderer/sw32/sw32_skin.c b/libs/video/renderer/sw32/sw32_skin.c new file mode 100644 index 000000000..a3c3382d5 --- /dev/null +++ b/libs/video/renderer/sw32/sw32_skin.c @@ -0,0 +1,187 @@ +/* + sw32_skin.c + + (description) + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_STRINGS_H +#include +#endif + +#include "QF/model.h" +#include "QF/render.h" +#include "QF/skin.h" +#include "QF/sys.h" + +#include "compat.h" +#include "d_iface.h" + +void +Skin_Set_Translate (int top, int bottom, void *_dest) +{ + int i, j; + + top = bound (0, top, 13) * 16; + bottom = bound (0, bottom, 13) * 16; + + switch(r_pixbytes) { + case 1: + { + byte *source; + byte *dest = (byte *) _dest; + + source = vid.colormap8; + memcpy (dest, vid.colormap8, VID_GRADES * 256); + + for (i = 0; i < VID_GRADES; i++, dest += 256, source += 256) { + if (top < 128) // the artists made some backwards + // ranges. sigh. + memcpy (dest + TOP_RANGE, source + top, 16); + else + for (j = 0; j < 16; j++) + dest[TOP_RANGE + j] = source[top + 15 - j]; + + if (bottom < 128) + memcpy (dest + BOTTOM_RANGE, source + bottom, 16); + else + for (j = 0; j < 16; j++) + dest[BOTTOM_RANGE + j] = source[bottom + 15 - j]; + } + } + break; + case 2: + { + unsigned short *source; + unsigned short *dest = (unsigned short *) _dest; + + source = vid.colormap16; + memcpy (dest, vid.colormap16, 2 * VID_GRADES * 256); + + for (i = 0; i < VID_GRADES; i++, dest += 256, source += 256) { + if (top < 128) + { + for (j = 0; j < 16; j++) + dest[TOP_RANGE + j] = source[top + j]; + } + else + { + for (j = 0; j < 16; j++) + dest[TOP_RANGE + j] = source[top + 15 - j]; + } + + if (bottom < 128) + { + for (j = 0; j < 16; j++) + dest[BOTTOM_RANGE + j] = source[bottom + j]; + } + else + { + for (j = 0; j < 16; j++) + dest[BOTTOM_RANGE + j] = source[bottom + 15 - j]; + } + } + } + break; + case 4: + { + unsigned int *source; + unsigned int *dest = (unsigned int *) _dest; + + source = vid.colormap32; + memcpy (dest, vid.colormap32, 4 * VID_GRADES * 256); + + for (i = 0; i < VID_GRADES; i++, dest += 256, source += 256) { + if (top < 128) + { + for (j = 0; j < 16; j++) + dest[TOP_RANGE + j] = source[top + j]; + } + else + { + for (j = 0; j < 16; j++) + dest[TOP_RANGE + j] = source[top + 15 - j]; + } + + if (bottom < 128) + { + for (j = 0; j < 16; j++) + dest[BOTTOM_RANGE + j] = source[bottom + j]; + } + else + { + for (j = 0; j < 16; j++) + dest[BOTTOM_RANGE + j] = source[bottom + 15 - j]; + } + } + } + break; + default: + Sys_Error("Skin_Set_Translate: unsupported r_pixbytes %i\n", + r_pixbytes); + } + + byte *dest = (byte *) _dest; + + for (j = 0;j < 256;j++) + dest[j] = d_8to24table[j]; + + if (top < 128) { + for (j = 0;j < 16;j++) + dest[TOP_RANGE + j] = d_8to24table[top + j]; + } else { + for (j = 0; j < 16; j++) + dest[TOP_RANGE + j] = d_8to24table[top + 15 - j]; + } + + if (bottom < 128) { + for (j = 0;j < 16;j++) + dest[BOTTOM_RANGE + j] = d_8to24table[bottom + j]; + } else { + for (j = 0; j < 16; j++) + dest[BOTTOM_RANGE + j] = d_8to24table[bottom + 15 - j]; + } +} + +void +Skin_Do_Translation (skin_t *player_skin, int slot, skin_t *skin) +{ +} + +void +Skin_Init_Translation (void) +{ +} + +void +Skin_Process (skin_t *skin, struct tex_s *tex) +{ +} diff --git a/libs/video/targets/Makefile.am b/libs/video/targets/Makefile.am index 154c18104..8c7e60c12 100644 --- a/libs/video/targets/Makefile.am +++ b/libs/video/targets/Makefile.am @@ -2,7 +2,7 @@ INCLUDES= -I$(top_srcdir)/include $(GGI_CFLAGS) $(MGL_CFLAGS) $(SDL_CFLAGS) $(SV lib_LTLIBRARIES = @VID_TARGETS@ -EXTRA_LTLIBRARIES = libQFjs.la libQFfbdev.la libQFsvga.la libQFx11.la libQFglx.la libQFsdl.la libQFsgl.la libQFtdfx.la libQFwgl.la libQFmgl.la +EXTRA_LTLIBRARIES = libQFjs.la libQFfbdev.la libQFsvga.la libQFx11.la libQFglx.la libQFsdl.la libQFsdl32.la libQFsgl.la libQFtdfx.la libQFwgl.la libQFmgl.la if ASM_ARCH ASM = libasm.la @@ -32,6 +32,7 @@ EXTRA_DIST= joy.c joy_linux.c joy_null.c joy_win.c in_common_SOURCE= in_common.c in_event.c keys.c old_keys.c + # Linux FBdev YFLAGS = -d YACCLEX_CLEANFILES= fbset_modes_y.c fbset_modes_y.h \ @@ -48,59 +49,48 @@ fbset_modes_l.lo: $(srcdir)/fbset_modes_l.c $(LTCOMPILE) -Wno-error -c $< libQFglx_la_LDFLAGS= -version-info 1:0:0 $(X_PRE_LIBS) $(VIDMODE_LIBS) $(DGA_LIBS) $(X_LIBS) -lX11 $(X_EXTRA_LIBS) -libQFglx_la_SOURCES= $(in_common_SOURCE) in_x11.c vid.c context_x11.c dga_check.c \ - qfgl_ext.c vid_common_gl.c vid_glx.c +libQFglx_la_SOURCES= $(in_common_SOURCE) in_x11.c vid.c context_x11.c dga_check.c qfgl_ext.c vid_common_gl.c vid_glx.c libQFglx.la: $(libQFglx_la_OBJECTS) $(libQFglx_la_DEPENDENCIES) $(LINK) -rpath $(libdir) $(libQFglx_la_LDFLAGS) $(libQFglx_la_OBJECTS) $(libQFglx_la_LIBADD) $(LIBS) - libQFmgl_la_LDFLAGS= -version-info 1:0:0 libQFmgl_la_SOURCES= $(in_common_SOURCE) in_win.c vid.c vid_common_sw.c vid_mgl.c libQFmgl.la: $(libQFmgl_la_OBJECTS) $(libQFmgl_la_DEPENDENCIES) $(LINK) -rpath $(libdir) $(libQFmgl_la_LDFLAGS) $(libQFmgl_la_OBJECTS) $(libQFmgl_la_LIBADD) $(LIBS) - libQFsdl_la_LDFLAGS= -version-info 1:0:0 libQFsdl_la_SOURCES= $(in_common_SOURCE) in_sdl.c vid.c vid_common_sw.c vid_sdl.c libQFsdl.la: $(libQFsdl_la_OBJECTS) $(libQFsdl_la_DEPENDENCIES) $(LINK) -rpath $(libdir) $(libQFsdl_la_LDFLAGS) $(libQFsdl_la_OBJECTS) $(libQFsdl_la_LIBADD) $(LIBS) -# FIXME: waiting on *view.c merge --DESPAIR -#libQFsdl32_la_LDFLAGS= -version-info 1:0:0 -#libQFsdl32_la_SOURCES= in_common.c in_sdl.c vid.c vid_common_sw.c vid_sdl32.c -#libQFsdl32.la: $(libQFsdl32_la_OBJECTS) $(libQFsdl32_la_DEPENDENCIES) -# $(LINK) -rpath $(libdir) $(libQFsdl32_la_LDFLAGS) $(libQFsdl32_la_OBJECTS) $(libQFsdl32_la_LIBADD) $(LIBS) - +libQFsdl32_la_LDFLAGS= -version-info 1:0:0 +libQFsdl32_la_SOURCES= in_common.c in_sdl.c vid.c vid_common_sw.c vid_sdl32.c +libQFsdl32.la: $(libQFsdl32_la_OBJECTS) $(libQFsdl32_la_DEPENDENCIES) + $(LINK) -rpath $(libdir) $(libQFsdl32_la_LDFLAGS) $(libQFsdl32_la_OBJECTS) $(libQFsdl32_la_LIBADD) $(LIBS) libQFsgl_la_LDFLAGS= -version-info 1:0:0 libQFsgl_la_SOURCES= $(in_common_SOURCE) in_sdl.c qfgl_ext.c vid.c vid_common_gl.c vid_sgl.c libQFsgl.la: $(libQFsgl_la_OBJECTS) $(libQFsgl_la_DEPENDENCIES) $(LINK) -rpath $(libdir) $(libQFsgl_la_LDFLAGS) $(libQFsgl_la_OBJECTS) $(libQFsgl_la_LIBADD) $(LIBS) - libQFsvga_la_LDFLAGS= -version-info 1:0:0 libQFsvga_la_LIBADD=$(ASM) -libQFsvga_la_SOURCES= $(in_common_SOURCE) in_svgalib.c vid.c vid_common_sw.c \ - vid_svgalib.c +libQFsvga_la_SOURCES= $(in_common_SOURCE) in_svgalib.c vid.c vid_common_sw.c vid_svgalib.c libQFsvga.la: $(libQFsvga_la_OBJECTS) $(libQFsvga_la_DEPENDENCIES) $(LINK) -rpath $(libdir) $(libQFsvga_la_LDFLAGS) $(libQFsvga_la_OBJECTS) $(libQFsvga_la_LIBADD) $(LIBS) - libQFtdfx_la_LDFLAGS= -version-info 1:0:0 libQFtdfx_la_SOURCES= $(in_common_SOURCE) in_svgalib.c qfgl_ext.c vid.c vid_common_gl.c vid_3dfxsvga.c libQFtdfx.la: $(libQFtdfx_la_OBJECTS) $(libQFtdfx_la_DEPENDENCIES) $(LINK) -rpath $(libdir) $(libQFtdfx_la_LDFLAGS) $(libQFtdfx_la_OBJECTS) $(libQFtdfx_la_LIBADD) $(LIBS) - libQFwgl_la_LDFLAGS= -version-info 1:0:0 libQFwgl_la_SOURCES= $(in_common_SOURCE) in_win.c qfgl_ext.c vid.c vid_common_gl.c vid_wgl.c libQFwgl.la: $(libQFwgl_la_OBJECTS) $(libQFwgl_la_DEPENDENCIES) $(LINK) -rpath $(libdir) $(libQFwgl_la_LDFLAGS) $(libQFwgl_la_OBJECTS) $(libQFwgl_la_LIBADD) $(LIBS) - libQFx11_la_LDFLAGS= -version-info 1:0:0 $(X_PRE_LIBS) $(VIDMODE_LIBS) $(DGA_LIBS) $(X_LIBS) -lX11 $(X_EXTRA_LIBS) $(X_SHM_LIB) -libQFx11_la_SOURCES= $(in_common_SOURCE) in_x11.c vid.c context_x11.c dga_check.c \ - vid_common_sw.c vid_x11.c +libQFx11_la_SOURCES= $(in_common_SOURCE) in_x11.c vid.c context_x11.c dga_check.c vid_common_sw.c vid_x11.c libQFx11.la: $(libQFx11_la_OBJECTS) $(libQFx11_la_DEPENDENCIES) $(LINK) -rpath $(libdir) $(libQFx11_la_LDFLAGS) $(libQFx11_la_OBJECTS) $(libQFx11_la_LIBADD) $(LIBS) diff --git a/libs/video/targets/vid_3dfxsvga.c b/libs/video/targets/vid_3dfxsvga.c index eefdac018..82349bfeb 100644 --- a/libs/video/targets/vid_3dfxsvga.c +++ b/libs/video/targets/vid_3dfxsvga.c @@ -37,26 +37,26 @@ #ifdef HAVE_STRINGS_H # include #endif +#ifdef HAVE_DLOPEN +# include +#endif #include #include #include -#ifdef HAVE_DLOPEN -# include -#endif - -#include "compat.h" #include "QF/console.h" #include "QF/cvar.h" #include "QF/qargs.h" #include "QF/qendian.h" -#include "sbar.h" -#include "QF/GL/extensions.h" -#include "QF/GL/funcs.h" #include "QF/sys.h" #include "QF/va.h" #include "QF/vid.h" +#include "QF/GL/extensions.h" +#include "QF/GL/funcs.h" + +#include "compat.h" +#include "sbar.h" #include "r_cvar.h" #define WARP_WIDTH 320 @@ -94,7 +94,6 @@ int VID_options_items = 0; extern void GL_Init_Common (void); extern void VID_Init8bitPalette (void); -/*-----------------------------------------------------------------------*/ void VID_Shutdown (void) @@ -127,9 +126,6 @@ InitSig (void) signal (SIGTERM, signal_handler); } -/* - GL_Init -*/ void GL_Init (void) { @@ -220,7 +216,6 @@ static int resolutions[][3] = { #define NUM_RESOLUTIONS (sizeof (resolutions) / (sizeof (int) * 3)) - static int findres (int *width, int *height) { @@ -253,7 +248,8 @@ TDFX_BrightenPalette (unsigned char *palette) green = (float) pal[1]; blue = (float) pal[2]; maxnum = max (red, max (green, blue)); - somenum = (bound (0.0, (maxnum * tdfx_brighten->value), 255.0) / maxnum); + somenum = (bound (0.0, (maxnum * tdfx_brighten->value), 255.0) / + maxnum); pal[0] = (byte) ((somenum * red) + 0.5); pal[1] = (byte) ((somenum * green) + 0.5); pal[2] = (byte) ((somenum * blue) + 0.5); @@ -269,16 +265,21 @@ VID_Init (unsigned char *palette) #ifdef HAVE_DLOPEN if (!(libgl_handle = dlopen (gl_libgl->string, RTLD_NOW))) { - Sys_Error ("Can't open OpenGL library \"%s\": %s\n", gl_libgl->string, dlerror()); + Sys_Error ("Can't open OpenGL library \"%s\": %s\n", gl_libgl->string, + dlerror()); return; } #else # error "No dynamic library support. FIXME." #endif - fxMesaCreateContext = QFGL_ProcAddress (libgl_handle, "fxMesaCreateContext", true); - fxMesaDestroyContext = QFGL_ProcAddress (libgl_handle, "fxMesaDestroyContext", true); - fxMesaMakeCurrent = QFGL_ProcAddress (libgl_handle, "fxMesaMakeCurrent", true); - fxMesaSwapBuffers = QFGL_ProcAddress (libgl_handle, "fxMesaSwapBuffers", true); + fxMesaCreateContext = QFGL_ProcAddress (libgl_handle, + "fxMesaCreateContext", true); + fxMesaDestroyContext = QFGL_ProcAddress (libgl_handle, + "fxMesaDestroyContext", true); + fxMesaMakeCurrent = QFGL_ProcAddress (libgl_handle, + "fxMesaMakeCurrent", true); + fxMesaSwapBuffers = QFGL_ProcAddress (libgl_handle, + "fxMesaSwapBuffers", true); QFGL_ProcAddress (NULL, NULL, false); VID_GetWindowSize (640, 480); @@ -286,8 +287,8 @@ VID_Init (unsigned char *palette) vid.maxwarpwidth = WARP_WIDTH; vid.maxwarpheight = WARP_HEIGHT; - vid.colormap = vid_colormap; - vid.fullbright = 256 - LittleLong (*((int *) vid.colormap + 2048)); + vid.colormap8 = vid_colormap; + vid.fullbright = 256 - LittleLong (*((int *) vid.colormap8 + 2048)); // interpret command-line params @@ -354,8 +355,10 @@ VID_Init (unsigned char *palette) void VID_Init_Cvars (void) { - vid_system_gamma = Cvar_Get ("vid_system_gamma", "1", CVAR_ARCHIVE, NULL, "Use system gamma control if available"); - tdfx_brighten = Cvar_Get ("tdfx_brighten", "0", CVAR_ROM, NULL, "Brighten 3DFX palette"); + vid_system_gamma = Cvar_Get ("vid_system_gamma", "1", CVAR_ARCHIVE, NULL, + "Use system gamma control if available"); + tdfx_brighten = Cvar_Get ("tdfx_brighten", "0", CVAR_ROM, NULL, + "Brighten 3DFX palette"); } void @@ -387,4 +390,3 @@ VID_SetGamma (double gamma) grGammaCorrectionValue((float) gamma); return true; } - diff --git a/libs/video/targets/vid_common_sw32.c b/libs/video/targets/vid_common_sw32.c new file mode 100644 index 000000000..1683cf3e6 --- /dev/null +++ b/libs/video/targets/vid_common_sw32.c @@ -0,0 +1,201 @@ +/* + vid_common_sw32.c + + general video driver functions + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "QF/cvar.h" +#include "QF/qargs.h" +#include "QF/sys.h" +#include "QF/va.h" +#include "QF/vid.h" + +extern viddef_t vid; // global video state + +int scr_width, scr_height; +cvar_t *vid_width; +cvar_t *vid_height; + +unsigned short d_8to16table[256]; +unsigned int d_8to24table[256]; +unsigned char d_15to8table[65536]; + + +/* + lhfindcolor + + LordHavoc: finds nearest matching color in a palette +*/ +int +lhfindcolor (byte *pal, int colors, int r, int g, int b) +{ + int i, dist, best, bestdist, rd, gd, bd; + best = 0; + bestdist = 1000000000; + for (i = 0;i < colors;i++) + { + rd = pal[i*3+0] - r; + gd = pal[i*3+1] - g; + bd = pal[i*3+2] - b; + dist = rd*rd+gd*gd+bd*bd; + if (dist < bestdist) + { + if (!dist) // exact match + return i; + best = i; + bestdist = dist; + } + } + return best; +} + +/* + VID_MakeColormap32 + + LordHavoc: makes a 32bit color*light table, RGBA order, no endian, + may need to be re-ordered to hardware at display time +*/ +void +VID_MakeColormap32 (void *outcolormap, byte *pal) +{ + int c, l; + byte *out; + out = (byte *)&d_8to24table; + for (c = 0; c < 256; c++) { + *out++ = pal[c*3+0]; + *out++ = pal[c*3+1]; + *out++ = pal[c*3+2]; + *out++ = 255; + } + d_8to24table[255] = 0; // 255 is transparent + out = (byte *) outcolormap; + for (l = 0;l < VID_GRADES;l++) + { + for (c = 0;c < vid.fullbright;c++) + { + out[(l*256+c)*4+0] = bound(0, (pal[c*3+0] * l) >> (VID_CBITS - 1), + 255); + out[(l*256+c)*4+1] = bound(0, (pal[c*3+1] * l) >> (VID_CBITS - 1), + 255); + out[(l*256+c)*4+2] = bound(0, (pal[c*3+2] * l) >> (VID_CBITS - 1), + 255); + out[(l*256+c)*4+3] = 255; + } + for (;c < 255;c++) + { + out[(l*256+c)*4+0] = pal[c*3+0]; + out[(l*256+c)*4+1] = pal[c*3+1]; + out[(l*256+c)*4+2] = pal[c*3+2]; + out[(l*256+c)*4+3] = 255; + } + out[(l*256+255)*4+0] = 0; + out[(l*256+255)*4+1] = 0; + out[(l*256+255)*4+2] = 0; + out[(l*256+255)*4+3] = 0; + } +} + +unsigned short lh24to16bit (int red, int green, int blue) +{ + red = bound(0, red, 255); + green = bound(0, green, 255); + blue = bound(0, blue, 255); + red >>= 3; + green >>= 2; + blue >>= 3; + red <<= 11; + green <<= 5; + return (unsigned short) (red | green | blue); +} + +/* + VID_MakeColormap16 + + LordHavoc: makes a 16bit color*light table, RGB order, native endian, + may need to be translated to hardware order at display time +*/ +void +VID_MakeColormap16 (void *outcolormap, byte *pal) +{ + int c, l; + unsigned short *out; + out = (unsigned short *)&d_8to16table; + for (c = 0; c < 256; c++) + *out++ = lh24to16bit(pal[c*3+0], pal[c*3+1], pal[c*3+2]); + d_8to16table[255] = 0; // 255 is transparent + out = (unsigned short *) outcolormap; + for (l = 0;l < VID_GRADES;l++) + { + for (c = 0;c < vid.fullbright;c++) + out[l*256+c] = lh24to16bit( + (pal[c*3+0] * l) >> (VID_CBITS - 1), + (pal[c*3+1] * l) >> (VID_CBITS - 1), + (pal[c*3+2] * l) >> (VID_CBITS - 1)); + for (;c < 255;c++) + out[l*256+c] = lh24to16bit(pal[c*3+0], pal[c*3+1], pal[c*3+2]); + out[l*256+255] = 0; + } +} + +/* + VID_MakeColormap8 + + LordHavoc: makes a 8bit color*light table +*/ +void +VID_MakeColormap8 (void *outcolormap, byte *pal) +{ + int c, l; + byte *out; + out = (byte *) outcolormap; + for (l = 0;l < VID_GRADES;l++) + { + for (c = 0;c < vid.fullbright;c++) + out[l*256+c] = lhfindcolor(pal, 256, + (pal[c*3+0] * l) >> (VID_CBITS - 1), + (pal[c*3+1] * l) >> (VID_CBITS - 1), + (pal[c*3+2] * l) >> (VID_CBITS - 1)); + for (;c < 256;c++) + out[l*256+c] = c; + } +} + +/* + VID_MakeColormaps + + LordHavoc: makes 8bit, 16bit, and 32bit colormaps and palettes +*/ +void +VID_MakeColormaps (int fullbrights, byte *pal) +{ + vid.fullbright = fullbrights; + VID_MakeColormap8(vid.colormap8, pal); + VID_MakeColormap16(vid.colormap16, pal); + VID_MakeColormap32(vid.colormap32, pal); +} diff --git a/libs/video/targets/vid_fbdev.c b/libs/video/targets/vid_fbdev.c index 0e9e92a70..446c55c45 100644 --- a/libs/video/targets/vid_fbdev.c +++ b/libs/video/targets/vid_fbdev.c @@ -35,6 +35,12 @@ #ifdef HAVE_CONFIG_H # include "config.h" #endif +#ifdef HAVE_STRING_H +# include "string.h" +#endif +#ifdef HAVE_STRINGS_H +# include "strings.h" +#endif #ifdef HAVE_UNISTD_H # include #endif @@ -43,20 +49,19 @@ #elif defined(HAVE_ASM_IO_H) # include #endif -#include -#include -#include -#include -#include #include -#include -#include -#include +#include +#include +#include +#include +#include #include #include #include -#include +#include +#include +#include #include "QF/cmd.h" #include "QF/console.h" @@ -126,7 +131,6 @@ D_BeginDirectRect (int x, int y, byte * pbitmap, int width, int height) } } - void D_EndDirectRect (int x, int y, int width, int height) { @@ -153,7 +157,6 @@ D_EndDirectRect (int x, int y, int width, int height) } } - static void VID_DescribeMode_f (void) { @@ -170,7 +173,6 @@ VID_DescribeMode_f (void) vmode->xres, vmode->yres, vmode->depth, vmode->vrate); } - static void VID_DescribeModes_f (void) { @@ -182,10 +184,6 @@ VID_DescribeModes_f (void) } } - -/* - VID_NumModes -*/ static int VID_NumModes (void) { @@ -198,7 +196,6 @@ VID_NumModes (void) return i; } - static void VID_NumModes_f (void) { @@ -229,13 +226,13 @@ static void VID_Debug_f (void) { Con_Printf ("mode: %s\n", current_mode.name); - Con_Printf ("height x width: %d x %d\n", current_mode.xres, current_mode.yres); + Con_Printf ("height x width: %d x %d\n", current_mode.xres, + current_mode.yres); Con_Printf ("bpp: %d\n", current_mode.depth); Con_Printf ("vrate: %5.3f\n", current_mode.vrate); Con_Printf ("vid.aspect: %f\n", vid.aspect); } - static void VID_InitModes (void) { @@ -243,7 +240,6 @@ VID_InitModes (void) num_modes = VID_NumModes(); } - static char * get_mode (char *name, int width, int height, int depth) { @@ -267,7 +263,6 @@ get_mode (char *name, int width, int height, int depth) return "640x480-60"; } - static unsigned char *fb_map_addr = 0; static unsigned long fb_map_length = 0; @@ -363,9 +358,9 @@ VID_SetMode (const char *name, unsigned char *palette) vid.width = vmode->xres; vid.height = vmode->yres; vid.rowbytes = vmode->xres * (vmode->depth >> 3); - vid.aspect = ((float) vid.height / (float) vid.width) * (320.0 / 240.0); - vid.colormap = (pixel_t *) vid_colormap; - vid.fullbright = 256 - LittleLong (*((int *) vid.colormap + 2048)); + vid.aspect = ((float) vid.height / (float) vid.width) * (4.0 / 3.0); + vid.colormap8 = (byte *) vid_colormap; + vid.fullbright = 256 - LittleLong (*((int *) vid.colormap8 + 2048)); vid.conrowbytes = vid.rowbytes; vid.conwidth = vid.width; vid.conheight = vid.height; @@ -392,7 +387,8 @@ VID_SetMode (const char *name, unsigned char *palette) smem_start = (unsigned long)fix.smem_start & PAGE_MASK; smem_offset = (unsigned long)fix.smem_start & ~PAGE_MASK; fb_map_length = (smem_offset+fix.smem_len+~PAGE_MASK) & PAGE_MASK; - fb_map_addr = (char *)mmap(0, fb_map_length, PROT_WRITE, MAP_SHARED, fb_fd, 0); + fb_map_addr = (char *)mmap(0, fb_map_length, PROT_WRITE, MAP_SHARED, + fb_fd, 0); if (!fb_map_addr) Sys_Error ("This mode isn't hapnin'\n"); vid.direct = framebuffer_ptr = fb_map_addr; @@ -486,8 +482,10 @@ VID_Init (unsigned char *palette) VID_InitModes (); Cmd_AddCommand ("vid_nummodes", VID_NumModes_f, "No Description"); - Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f, "No Description"); - Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f, "No Description"); + Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f, + "No Description"); + Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f, + "No Description"); Cmd_AddCommand ("vid_debug", VID_Debug_f, "No Description"); Cmd_AddCommand ("vid_fbset", VID_fbset_f, "No Description"); @@ -496,7 +494,8 @@ VID_Init (unsigned char *palette) if (getenv ("GFBDEVMODE")) { modestr = get_mode (getenv ("GFBDEVMODE"), w, h, d); } else if (COM_CheckParm ("-mode")) { - modestr = get_mode (com_argv[COM_CheckParm ("-mode") + 1], w, h, d); + modestr = get_mode (com_argv[COM_CheckParm ("-mode") + 1], w, h, + d); } else if (COM_CheckParm ("-w") || COM_CheckParm ("-h") || COM_CheckParm ("-d")) { if (COM_CheckParm ("-w")) { @@ -540,7 +539,6 @@ VID_Init_Cvars () NULL, "Wait for vertical retrace before drawing next frame"); } - void VID_Update (vrect_t *rects) { diff --git a/libs/video/targets/vid_glx.c b/libs/video/targets/vid_glx.c index 6920ea78c..a7a78c0e0 100644 --- a/libs/video/targets/vid_glx.c +++ b/libs/video/targets/vid_glx.c @@ -36,6 +36,9 @@ #ifdef HAVE_STRINGS_H # include #endif +#ifdef HAVE_DLOPEN +# include +#endif #include #include @@ -45,32 +48,26 @@ # include #endif -#ifdef HAVE_DLOPEN -# include -#endif - #include "QF/cmd.h" -#include "compat.h" #include "QF/console.h" +#include "QF/cvar.h" #include "QF/input.h" #include "QF/qargs.h" #include "QF/qendian.h" +#include "QF/sys.h" #include "QF/va.h" #include "QF/vid.h" #include "QF/GL/funcs.h" -#include "QF/sys.h" +#include "compat.h" #include "context_x11.h" #include "sbar.h" -#include "QF/cvar.h" #include "r_cvar.h" #define WARP_WIDTH 320 #define WARP_HEIGHT 200 -/* -** GLXContext is a pointer to opaque data. -*/ +/* GLXContext is a pointer to opaque data. */ typedef struct __GLXcontextRec *GLXContext; #define GLX_RGBA 4 /* true if RGBA mode */ @@ -97,7 +94,8 @@ const char *gl_vendor; const char *gl_renderer; const char *gl_version; const char *gl_extensions; -void *libgl_handle; +void *libgl_handle; + void VID_Shutdown (void) @@ -111,9 +109,6 @@ VID_Shutdown (void) X11_CloseDisplay (); } -/* - GL_Init -*/ void GL_Init (void) { @@ -149,7 +144,8 @@ VID_Init (unsigned char *palette) #ifdef HAVE_DLOPEN if (!(libgl_handle = dlopen (gl_libgl->string, RTLD_NOW))) { - Sys_Error ("Can't open OpenGL library \"%s\": %s\n", gl_libgl->string, dlerror()); + Sys_Error ("Can't open OpenGL library \"%s\": %s\n", gl_libgl->string, + dlerror()); return; } #else @@ -158,19 +154,21 @@ VID_Init (unsigned char *palette) glXSwapBuffers = QFGL_ProcAddress (libgl_handle, "glXSwapBuffers", true); glXChooseVisual = QFGL_ProcAddress (libgl_handle, "glXChooseVisual", true); - glXCreateContext = QFGL_ProcAddress (libgl_handle, "glXCreateContext", true); + glXCreateContext = QFGL_ProcAddress (libgl_handle, "glXCreateContext", + true); glXMakeCurrent = QFGL_ProcAddress (libgl_handle, "glXMakeCurrent", true); QFGL_ProcAddress (NULL, NULL, false); // make ProcAddress clear its cache - Cmd_AddCommand ("vid_center", VID_Center_f, "Center the view port on the quake window in a virtual desktop.\n"); + Cmd_AddCommand ("vid_center", VID_Center_f, "Center the view port on the " + "quake window in a virtual desktop.\n"); VID_GetWindowSize (640, 480); Con_CheckResize (); // Now that we have a window size, fix console vid.maxwarpwidth = WARP_WIDTH; vid.maxwarpheight = WARP_HEIGHT; - vid.colormap = vid_colormap; - vid.fullbright = 256 - LittleLong (*((int *) vid.colormap + 2048)); + vid.colormap8 = vid_colormap; + vid.fullbright = 256 - LittleLong (*((int *) vid.colormap8 + 2048)); /* Interpret command-line params */ @@ -196,7 +194,8 @@ VID_Init (unsigned char *palette) x_visinfo = glXChooseVisual (x_disp, x_screen, attrib); if (!x_visinfo) { - Sys_Error ("Error couldn't get an RGB, Double-buffered, Depth visual\n"); + Sys_Error ("Error couldn't get an RGB, Double-buffered, Depth " + "visual\n"); } x_vis = x_visinfo->visual; diff --git a/libs/video/targets/vid_mgl.c b/libs/video/targets/vid_mgl.c index a7eac3a0e..5268c42b0 100644 --- a/libs/video/targets/vid_mgl.c +++ b/libs/video/targets/vid_mgl.c @@ -32,21 +32,22 @@ #include -#include "cdaudio.h" #include "QF/cmd.h" +#include "QF/cdaudio.h" #include "QF/console.h" -#include "d_local.h" -#include "draw.h" -#include "in_win.h" +#include "QF/draw.h" #include "QF/keys.h" #include "QF/qargs.h" #include "QF/qendian.h" -#include "resource.h" -#include "screen.h" -#include "sound.h" +#include "QF/screen.h" +#include "QF/sound.h" #include "QF/sys.h" #include "QF/va.h" -#include "wad.h" +#include "QF/wad.h" + +#include "d_local.h" +#include "in_win.h" +#include "resource.h" #include "winquake.h" #define MINIMUM_MEMORY 0x550000 @@ -58,7 +59,8 @@ extern void (*vid_menudrawfn) (void); extern void (*vid_menukeyfn) (int); /* Unused */ -int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar; +int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, + VGA_planar; byte *VGA_pagebase; qboolean dibonly; @@ -75,21 +77,19 @@ RECT WindowRect; DWORD WindowStyle, ExWindowStyle; int window_center_x, window_center_y, window_x, window_y, window_width, - - window_height; + window_height; RECT window_rect; -static DEVMODE gdevmode; +static DEVMODE gdevmode; static qboolean startwindowed = 0, windowed_mode_set = 0; -static int firstupdate = 1; +static int firstupdate = 1; static qboolean vid_palettized; -static int lockcount; -static int vid_fulldib_on_focus_mode; +static int lockcount; +static int vid_fulldib_on_focus_mode; static qboolean force_minimized, in_mode_set, is_mode0x13, force_mode_set; -static int vid_stretched, windowed_mouse; +static int vid_stretched, windowed_mouse; static qboolean palette_changed, syscolchg, vid_mode_set, hide_window, - - pal_is_nostatic; + pal_is_nostatic; static HICON hIcon; extern viddef_t vid; // global video state @@ -179,9 +179,7 @@ void VID_MenuKey (int key); LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); void AppActivate (BOOL fActive, BOOL minimize); -/* - VID_RememberWindowPos -*/ + void VID_RememberWindowPos (void) { @@ -197,10 +195,6 @@ VID_RememberWindowPos (void) } } - -/* - VID_CheckWindowXY -*/ void VID_CheckWindowXY (void) { @@ -213,10 +207,6 @@ VID_CheckWindowXY (void) } } - -/* - VID_UpdateWindowStatus -*/ void VID_UpdateWindowStatus (void) { @@ -231,32 +221,18 @@ VID_UpdateWindowStatus (void) IN_UpdateClipCursor (); } - -/* - ClearAllStates -*/ void ClearAllStates (void) { IN_ClearStates (); } - -/* - VID_CheckAdequateMem -*/ qboolean VID_CheckAdequateMem (int width, int height) { return true; } - -/* - - VID_AllocBuffers - -*/ qboolean VID_AllocBuffers (int width, int height) { @@ -299,7 +275,6 @@ VID_AllocBuffers (int width, int height) return true; } - void initFatalError (void) { @@ -324,14 +299,13 @@ VID_Suspend (MGLDC * dc, int flags) block_drawing = true; } else if (flags & MGL_REACTIVATE) { IN_SetQuakeMouseState (); - // fix the leftover Alt from any Alt-Tab or the like that switched us - // away + // fix leftover Alt from any Alt-Tab or the like that switched us away ClearAllStates (); CDAudio_Resume (); in_mode_set = false; block_drawing = false; -// vid.recalc_refdef = 1; +// vid.recalc_refdef = 1; force_mode_set = 1; i = msg_suppress_1; msg_suppress_1 = 1; @@ -368,8 +342,7 @@ VID_Suspend (MGLDC * dc, int flags) // switched away } else if (flags & MGL_REACTIVATE) { IN_SetQuakeMouseState (); - // fix the leftover Alt from any Alt-Tab or the like that switched us - // away + // fix leftover Alt from any Alt-Tab or the like that switched us away ClearAllStates (); CDAudio_Resume (); S_UnblockSound (); @@ -383,8 +356,8 @@ VID_Suspend (MGLDC * dc, int flags) return MGL_NO_SUSPEND_APP; } -#endif +#endif void registerAllDispDrivers (void) @@ -393,11 +366,13 @@ registerAllDispDrivers (void) that they will still be available even if DirectDraw * is present and the user has disable the high performance * WinDirect modes. */ MGL_registerDriver (MGL_VGA8NAME, VGA8_driver); -// MGL_registerDriver(MGL_VGAXNAME,VGAX_driver); +// MGL_registerDriver(MGL_VGAXNAME, VGAX_driver); /* Register display drivers */ if (useWinDirect) { -//we don't want VESA 1.X drivers MGL_registerDriver(MGL_SVGA8NAME,SVGA8_driver); +/* we don't want VESA 1.X drivers + MGL_registerDriver(MGL_SVGA8NAME, SVGA8_driver); +*/ MGL_registerDriver (MGL_LINEAR8NAME, LINEAR8_driver); if (!COM_CheckParm ("-novbeaf")) @@ -409,7 +384,6 @@ registerAllDispDrivers (void) } } - void registerAllMemDrivers (void) { @@ -417,7 +391,6 @@ registerAllMemDrivers (void) MGL_registerDriver (MGL_PACKED8NAME, PACKED8_driver); } - void VID_InitMGLFull (HINSTANCE hInstance) { @@ -481,10 +454,8 @@ VID_InitMGLFull (HINSTANCE hInstance) } // if there's a mode we can stretch by 2 up to, thereby effectively - // getting - // a lower-res mode than the lowest-res real but still at least - // 320x200, that - // will be our default mode + // getting a lower-res mode than the lowest-res real but still at least + // 320x200, that will be our default mode if (lowstretchedres < lowres) { mode = stretchedmode; lowres = lowstretchedres; @@ -555,21 +526,17 @@ VID_InitMGLFull (HINSTANCE hInstance) MGL_setSuspendAppCallback (VID_Suspend); } +/* + createDisplayDC + Returns pointer to the MGL device context to use for the application + Initialises the MGL and creates an appropriate display device context to be + used by the GUI. This creates and apropriate device context depending on the + system being compile for, and should be the only place where system specific + code is required. +*/ MGLDC * createDisplayDC (int forcemem) -/**************************************************************************** -* -* Function: createDisplayDC -* Returns: Pointer to the MGL device context to use for the application -* -* Description: Initialises the MGL and creates an appropriate display -* device context to be used by the GUI. This creates and -* apropriate device context depending on the system being -* compile for, and should be the only place where system -* specific code is required. -* -****************************************************************************/ { MGLDC *dc; pixel_format_t pf; @@ -599,8 +566,8 @@ createDisplayDC (int forcemem) memdc = NULL; } else { // Set up for blitting from a memory buffer - memdc = - MGL_createMemoryDC (MGL_sizex (dc) + 1, MGL_sizey (dc) + 1, 8, &pf); + memdc = MGL_createMemoryDC (MGL_sizex (dc) + 1, MGL_sizey (dc) + 1, 8, + &pf); MGL_makeCurrentDC (memdc); } @@ -628,7 +595,6 @@ createDisplayDC (int forcemem) return dc; } - void VID_InitMGLDIB (HINSTANCE hInstance) { @@ -694,7 +660,7 @@ VID_InitMGLDIB (HINSTANCE hInstance) modelist[2].halfscreen = 0; modelist[2].bpp = 8; -// automatically stretch the default mode up if > 640x480 desktop resolution + // automatically stretch default mode up if > 640x480 desktop resolution hdc = GetDC (NULL); if ((GetDeviceCaps (hdc, HORZRES) > 640) @@ -713,10 +679,6 @@ VID_InitMGLDIB (HINSTANCE hInstance) DDActive = 0; } - -/* - VID_InitFullDIB -*/ void VID_InitFullDIB (HINSTANCE hInstance) { @@ -726,7 +688,7 @@ VID_InitFullDIB (HINSTANCE hInstance) int cstretch, istretch, mstretch = 0; BOOL stat; -// enumerate 8 bpp modes + // enumerate 8 bpp modes originalnummodes = nummodes; modenum = 0; lowestres = 99999; @@ -734,9 +696,9 @@ VID_InitFullDIB (HINSTANCE hInstance) do { stat = EnumDisplaySettings (NULL, modenum, &devmode); - if ((devmode.dmBitsPerPel == 8) && - (devmode.dmPelsWidth <= MAXWIDTH) && - (devmode.dmPelsHeight <= MAXHEIGHT) && (nummodes < MAX_MODE_LIST)) { + if ((devmode.dmBitsPerPel == 8) && (devmode.dmPelsWidth <= MAXWIDTH) && + (devmode.dmPelsHeight <= MAXHEIGHT) && + (nummodes < MAX_MODE_LIST)) { devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == @@ -764,13 +726,14 @@ VID_InitFullDIB (HINSTANCE hInstance) modelist[nummodes].width >>= 1; modelist[nummodes].halfscreen = 1; snprintf (modelist[nummodes].modedesc, - sizeof (modelist[nummodes].modedesc), "%dx%d", - modelist[nummodes].width, + sizeof (modelist[nummodes].modedesc), + "%dx%d", modelist[nummodes].width, modelist[nummodes].height); } } - for (i = originalnummodes, existingmode = 0; i < nummodes; i++) { + for (i = originalnummodes, existingmode = 0; i < nummodes; + i++) { if ((modelist[nummodes].width == modelist[i].width) && (modelist[nummodes].height == modelist[i].height)) { existingmode = 1; @@ -808,7 +771,8 @@ VID_InitFullDIB (HINSTANCE hInstance) (devmode.dmPelsWidth <= (MAXWIDTH * 2)) && (devmode.dmPelsWidth > (devmode.dmPelsHeight * 2)))) && (nummodes < MAX_MODE_LIST) && (devmode.dmBitsPerPel > 8)) { - devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; + devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | + DM_PELSHEIGHT; if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL) { @@ -827,8 +791,7 @@ VID_InitFullDIB (HINSTANCE hInstance) devmode.dmPelsWidth, devmode.dmPelsHeight); // if the width is more than twice the height, reduce it - // by half because this - // is probably a dual-screen monitor + // by half because this is probably a dual-screen monitor if (!COM_CheckParm ("-noadjustaspect")) { if (modelist[nummodes].width > (modelist[nummodes].height * 2)) { @@ -867,12 +830,12 @@ VID_InitFullDIB (HINSTANCE hInstance) modenum++; } while (stat); } -// see if there are any low-res modes that aren't being reported + // see if there are any low-res modes that aren't being reported numlowresmodes = sizeof (lowresmodes) / sizeof (lowresmodes[0]); bpp = 8; done = 0; -// first make sure the driver doesn't just answer yes to all tests + // first make sure the driver doesn't just answer yes to all tests devmode.dmBitsPerPel = 8; devmode.dmPelsWidth = 42; devmode.dmPelsHeight = 37; @@ -907,7 +870,8 @@ VID_InitFullDIB (HINSTANCE hInstance) devmode.dmPelsWidth, devmode.dmPelsHeight); // we only want the lowest-bpp version of each mode - for (i = originalnummodes, existingmode = 0; i < nummodes; i++) { + for (i = originalnummodes, existingmode = 0; i < nummodes; + i++) { if ((modelist[nummodes].width == modelist[i].width) && (modelist[nummodes].height == modelist[i].height) && (modelist[nummodes].bpp >= modelist[i].bpp)) { @@ -940,9 +904,9 @@ VID_InitFullDIB (HINSTANCE hInstance) } } -// now add the lowest stretch-by-2 pseudo-modes between 320-wide -// (inclusive) and lowest real res (not inclusive) -// don't bother if we have a real VGA mode 0x13 mode + // now add the lowest stretch-by-2 pseudo-modes between 320-wide + // (inclusive) and lowest real res (not inclusive) don't bother if we have + // a real VGA mode 0x13 mode if (!is_mode0x13) { for (i = originalnummodes, cstretch = 0; i < nummodes; i++) { if (((modelist[i].width >> 1) < lowestres) && @@ -979,20 +943,12 @@ VID_InitFullDIB (HINSTANCE hInstance) Con_Printf ("No fullscreen DIB modes found\n"); } - -/* - VID_NumModes -*/ int VID_NumModes (void) { return nummodes; } - -/* - VID_GetModePtr -*/ vmode_t * VID_GetModePtr (int modenum) { @@ -1003,10 +959,6 @@ VID_GetModePtr (int modenum) return &badmode; } - -/* - VID_CheckModedescFixup -*/ void VID_CheckModedescFixup (int mode) { @@ -1030,10 +982,6 @@ VID_CheckModedescFixup (int mode) } } - -/* - VID_GetModeDescriptionMemCheck -*/ char * VID_GetModeDescriptionMemCheck (int mode) { @@ -1055,10 +1003,6 @@ VID_GetModeDescriptionMemCheck (int mode) } } - -/* - VID_GetModeDescription -*/ char * VID_GetModeDescription (int mode) { @@ -1075,7 +1019,6 @@ VID_GetModeDescription (int mode) return pinfo; } - /* VID_GetModeDescription2 @@ -1105,9 +1048,7 @@ VID_GetModeDescription2 (int mode) return pinfo; } - // KJB: Added this to return the mode driver name in description for console - char * VID_GetExtModeDescription (int mode) { @@ -1132,7 +1073,6 @@ VID_GetExtModeDescription (int mode) return pinfo; } - void DestroyDIBWindow (void) { @@ -1147,11 +1087,9 @@ DestroyDIBWindow (void) } } - void DestroyFullscreenWindow (void) { - if (modestate == MS_FULLSCREEN) { // destroy the existing fullscreen mode and DC's if (mgldc) @@ -1162,8 +1100,6 @@ DestroyFullscreenWindow (void) } } - - void DestroyFullDIBWindow (void) { @@ -1179,7 +1115,6 @@ DestroyFullDIBWindow (void) } } - qboolean VID_SetWindowedMode (int modenum) { @@ -1211,7 +1146,7 @@ VID_SetWindowedMode (int modenum) MGL_destroyDC (dibdc); windc = dibdc = NULL; -// KJB: Signal to the MGL that we are going back to windowed mode + // KJB: Signal to the MGL that we are going back to windowed mode if (!MGL_changeDisplayMode (grWINDOWED)) initFatalError (); @@ -1234,18 +1169,14 @@ VID_SetWindowedMode (int modenum) ExWindowStyle = 0; AdjustWindowRectEx (&WindowRect, WindowStyle, FALSE, 0); -// the first time we're called to set the mode, create the window we'll use -// for the rest of the session + // the first time we're called to set the mode, create the window we'll use + // for the rest of the session if (!vid_mode_set) { - mainwindow = CreateWindowEx (ExWindowStyle, - "WinQuake", - PROGRAM, - WindowStyle, - 0, 0, + mainwindow = CreateWindowEx (ExWindowStyle, "WinQuake", PROGRAM, + WindowStyle, 0, 0, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top, NULL, NULL, global_hInstance, NULL); - if (!mainwindow) Sys_Error ("Couldn't create DIB window"); @@ -1258,9 +1189,7 @@ VID_SetWindowedMode (int modenum) SetWindowLong (mainwindow, GWL_EXSTYLE, ExWindowStyle); } - if (!SetWindowPos (mainwindow, - NULL, - 0, 0, + if (!SetWindowPos (mainwindow, NULL, 0, 0, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top, SWP_NOCOPYBITS | SWP_NOZORDER | SWP_HIDEWINDOW)) { @@ -1270,7 +1199,7 @@ VID_SetWindowedMode (int modenum) if (hide_window) return true; -// position and show the DIB window + // position and show the DIB window VID_CheckWindowXY (); SetWindowPos (mainwindow, NULL, vid_window_x->int_val, vid_window_y->int_val, 0, 0, @@ -1320,7 +1249,6 @@ VID_SetWindowedMode (int modenum) return true; } - qboolean VID_SetFullscreenMode (int modenum) { @@ -1356,22 +1284,21 @@ VID_SetFullscreenMode (int modenum) vid_stretched = modelist[modenum].stretched; -// needed because we're not getting WM_MOVE messages fullscreen on NT + // needed because we're not getting WM_MOVE messages fullscreen on NT window_x = 0; window_y = 0; -// set the large icon, so the Quake icon will show up in the taskbar + // set the large icon, so the Quake icon will show up in the taskbar SendMessage (mainwindow, WM_SETICON, (WPARAM) 1, (LPARAM) hIcon); SendMessage (mainwindow, WM_SETICON, (WPARAM) 0, (LPARAM) hIcon); -// shouldn't be needed, but Kendall needs to let us get the activation -// message for this not to be needed on NT + // shouldn't be needed, but Kendall needs to let us get the activation + // message for this not to be needed on NT AppActivate (true, false); return true; } - qboolean VID_SetFullDIBMode (int modenum) { @@ -1415,7 +1342,8 @@ VID_SetFullDIBMode (int modenum) hdc = GetDC (NULL); WindowRect.right = modelist[modenum].width << modelist[modenum].stretched; - WindowRect.bottom = modelist[modenum].height << modelist[modenum].stretched; + WindowRect.bottom = modelist[modenum].height << + modelist[modenum].stretched; ReleaseDC (NULL, hdc); @@ -1429,15 +1357,13 @@ VID_SetFullDIBMode (int modenum) SetWindowLong (mainwindow, GWL_STYLE, WindowStyle | WS_VISIBLE); SetWindowLong (mainwindow, GWL_EXSTYLE, ExWindowStyle); - if (!SetWindowPos (mainwindow, - NULL, - 0, 0, + if (!SetWindowPos (mainwindow, NULL, 0, 0, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top, SWP_NOCOPYBITS | SWP_NOZORDER)) { Sys_Error ("Couldn't resize DIB window"); } -// position and show the DIB window + // position and show the DIB window SetWindowPos (mainwindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_SHOWWINDOW | SWP_DRAWFRAME); ShowWindow (mainwindow, SW_SHOWDEFAULT); @@ -1471,14 +1397,13 @@ VID_SetFullDIBMode (int modenum) vid_stretched = modelist[modenum].stretched; -// needed because we're not getting WM_MOVE messages fullscreen on NT + // needed because we're not getting WM_MOVE messages fullscreen on NT window_x = 0; window_y = 0; return true; } - void VID_RestoreOldMode (int original_mode) { @@ -1490,7 +1415,7 @@ VID_RestoreOldMode (int original_mode) in_mode_set = false; inerror = true; -// make sure mode set happens (video mode changes) + // make sure mode set happens (video mode changes) vid_modenum = original_mode - 1; if (!VID_SetMode (original_mode, vid_curpal)) { @@ -1503,7 +1428,6 @@ VID_RestoreOldMode (int original_mode) inerror = false; } - void VID_SetDefaultMode (void) { @@ -1514,7 +1438,6 @@ VID_SetDefaultMode (void) IN_DeactivateMouse (); } - int VID_SetMode (int modenum, unsigned char *palette) { @@ -1541,7 +1464,7 @@ VID_SetMode (int modenum, unsigned char *palette) if (!force_mode_set && (modenum == vid_modenum)) return true; -// so Con_Printfs don't mess us up by forcing vid and snd updates + // so Con_Printfs don't mess us up by forcing vid and snd updates temp = scr_disabled_for_loading; scr_disabled_for_loading = true; in_mode_set = true; @@ -1630,13 +1553,14 @@ VID_SetMode (int modenum, unsigned char *palette) Sleep (100); if (!force_minimized) { - SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0, - SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | + SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0, SWP_DRAWFRAME | + SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOCOPYBITS); SetForegroundWindow (mainwindow); } -// fix the leftover Alt from any Alt-Tab or the like that switched us away + + // fix the leftover Alt from any Alt-Tab or the like that switched us away ClearAllStates (); Con_Printf ("Video mode %s initialized\n", @@ -1653,7 +1577,6 @@ VID_SetMode (int modenum, unsigned char *palette) void VID_LockBuffer (void) { - if (dibdc) return; @@ -1685,7 +1608,6 @@ VID_LockBuffer (void) screenwidth = vid.rowbytes; } - void VID_UnlockBuffer (void) { @@ -1704,10 +1626,8 @@ VID_UnlockBuffer (void) // to turn up any unlocked accesses vid.buffer = vid.conbuffer = vid.direct = d_viewbuffer = NULL; - } - int VID_ForceUnlockedAndReturnState (void) { @@ -1728,11 +1648,9 @@ VID_ForceUnlockedAndReturnState (void) return lk; } - void VID_ForceLockState (int lk) { - if (!dibdc && lk) { lockcount = 0; VID_LockBuffer (); @@ -1741,7 +1659,6 @@ VID_ForceLockState (int lk) lockcount = lk; } - void VID_SetPalette (unsigned char *palette) { @@ -1798,25 +1715,18 @@ VID_SetPalette (unsigned char *palette) memcpy (vid_curpal, palette, sizeof (vid_curpal)); if (syscolchg) { - PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM) 0, (LPARAM) 0); + PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM) 0, + (LPARAM) 0); syscolchg = false; } } - -/* - VID_DescribeCurrentMode_f -*/ void VID_DescribeCurrentMode_f (void) { Con_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum)); } - -/* - VID_NumModes_f -*/ void VID_NumModes_f (void) { @@ -1827,10 +1737,6 @@ VID_NumModes_f (void) Con_Printf ("%d video modes are available\n", nummodes); } - -/* - VID_DescribeMode_f -*/ void VID_DescribeMode_f (void) { @@ -1841,10 +1747,6 @@ VID_DescribeMode_f (void) Con_Printf ("%s\n", VID_GetExtModeDescription (modenum)); } - -/* - VID_DescribeModes_f -*/ void VID_DescribeModes_f (void) { @@ -1874,10 +1776,6 @@ VID_DescribeModes_f (void) } } - -/* - VID_TestMode_f -*/ void VID_TestMode_f (void) { @@ -1897,9 +1795,6 @@ VID_TestMode_f (void) } } -/* - VID_Windowed_f -*/ void VID_Windowed_f (void) { @@ -1907,10 +1802,6 @@ VID_Windowed_f (void) VID_SetMode (vid_windowed_mode->int_val, vid_curpal); } - -/* - VID_Fullscreen_f -*/ void VID_Fullscreen_f (void) { @@ -1918,24 +1809,15 @@ VID_Fullscreen_f (void) VID_SetMode (vid_fullscreen_mode->int_val, vid_curpal); } -/* - VID_Minimize_f -*/ void VID_Minimize_f (void) { - -// we only support minimizing windows; if you're fullscreen, -// switch to windowed first + // we only support minimizing windows; if you're fullscreen, + // switch to windowed first if (modestate == MS_WINDOWED) ShowWindow (mainwindow, SW_MINIMIZE); } - - -/* - VID_ForceMode_f -*/ void VID_ForceMode_f (void) { @@ -1950,7 +1832,6 @@ VID_ForceMode_f (void) } } - void VID_Init (unsigned char *palette) { @@ -1958,16 +1839,23 @@ VID_Init (unsigned char *palette) int basenummodes; byte *ptmp; - Cmd_AddCommand ("vid_testmode", VID_TestMode_f, "Switch to another video mode temporarily for 5-seconds to test it.\n" - "(vid_testmode (mode))"); - Cmd_AddCommand ("vid_nummodes", VID_NumModes_f, "Reports the total number of video modes available"); - Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f, "Report current video mode."); - Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f, "Report information on specified video mode, default is current.\n" - "(vid_describemode (mode))"); - Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f, "Report information on all video modes."); - Cmd_AddCommand ("vid_forcemode", VID_ForceMode_f, "Force QuakeWorld to use a certain video mode. (vid_forcemode (mode))"); + Cmd_AddCommand ("vid_testmode", VID_TestMode_f, "Switch to another video " + "mode temporarily for 5-seconds to test it.\n" + "(vid_testmode (mode))"); + Cmd_AddCommand ("vid_nummodes", VID_NumModes_f, "Reports the total number " + "of video modes available"); + Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f, + "Report current video mode."); + Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f, "Report " + "information on specified video mode, default is " + "current.\n(vid_describemode (mode))"); + Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f, "Report " + "information on all video modes."); + Cmd_AddCommand ("vid_forcemode", VID_ForceMode_f, "Force QuakeWorld to " + "use a certain video mode. (vid_forcemode (mode))"); Cmd_AddCommand ("vid_windowed", VID_Windowed_f, "Switch to windowed mode"); - Cmd_AddCommand ("vid_fullscreen", VID_Fullscreen_f, "Switch to full screen mode"); + Cmd_AddCommand ("vid_fullscreen", VID_Fullscreen_f, "Switch to full " + "screen mode"); Cmd_AddCommand ("vid_minimize", VID_Minimize_f, "Minimize windowed Quake"); if (COM_CheckParm ("-dibonly")) @@ -1980,23 +1868,23 @@ VID_Init (unsigned char *palette) if (!dibonly) VID_InitMGLFull (global_hInstance); -// if there are no non-windowed modes, or only windowed and mode 0x13, then use -// fullscreen DIBs as well - if (((nummodes == basenummodes) || - ((nummodes == (basenummodes + 1)) && is_mode0x13)) && + // if there are no non-windowed modes, or only windowed and mode 0x13, + // then use fullscreen DIBs as well + if (((nummodes == basenummodes) || ((nummodes == (basenummodes + 1)) && + is_mode0x13)) && !COM_CheckParm ("-nofulldib")) - { + { VID_InitFullDIB (global_hInstance); } vid.maxwarpwidth = WARP_WIDTH; vid.maxwarpheight = WARP_HEIGHT; - vid.colormap = vid_colormap; - vid.fullbright = 256 - LittleLong (*((int *) vid.colormap + 2048)); + vid.colormap8 = vid_colormap; + vid.fullbright = 256 - LittleLong (*((int *) vid.colormap8 + 2048)); vid_testingmode = 0; -// GDI doesn't let us remap palette index 0, so we'll remap color -// mappings from that black to another one + // GDI doesn't let us remap palette index 0, so we'll remap color + // mappings from that black to another one bestmatchmetric = 256 * 256 * 3; for (i = 1; i < 256; i++) { @@ -2015,7 +1903,8 @@ VID_Init (unsigned char *palette) } } - for (i = 0, ptmp = vid.colormap; i < (1 << (VID_CBITS + 8)); i++, ptmp++) { + for (i = 0, ptmp = vid.colormap8; i < (1 << (VID_CBITS + 8)); + i++, ptmp++) { if (*ptmp == 0) *ptmp = bestmatch; } @@ -2034,11 +1923,11 @@ VID_Init (unsigned char *palette) // fullscreen so the "hardware already in use" dialog is visible if it // gets displayed -// keep the window minimized until we're ready for the first real mode set + // keep the window minimized until we're ready for the first real mode set hide_window = true; VID_SetMode (MODE_WINDOWED, palette); hide_window = false; -// S_Init (); +// S_Init (); vid.initialized = true; @@ -2059,28 +1948,39 @@ VID_Init (unsigned char *palette) void VID_Init_Cvars () { - vid_mode = Cvar_Get ("vid_mode", "0", CVAR_NONE, NULL, "Set the video mode"); - vid_nopageflip = Cvar_Get ("vid_nopageflip", "0", CVAR_ARCHIVE, NULL, "Toggles the use of page flipping"); - _vid_default_mode_win = - Cvar_Get ("_vid_default_mode_win", "3", CVAR_ARCHIVE, NULL, "Default windowed video mode"); - vid_config_x = Cvar_Get ("vid_config_x", "800", CVAR_ARCHIVE, NULL, "Maximum x-axis screen size"); - vid_config_y = Cvar_Get ("vid_config_y", "600", CVAR_ARCHIVE, NULL, "Maximum y-axis screen size"); - vid_stretch_by_2 = Cvar_Get ("vid_stretch_by_2", "1", CVAR_ARCHIVE, NULL, "Stretch the pixles by a two fold to acheive proper view"); - _windowed_mouse = Cvar_Get ("_windowed_mouse", "0", CVAR_ARCHIVE, NULL, "Have quake grab the mouse from X when you play"); - vid_fullscreen_mode = - Cvar_Get ("vid_fullscreen_mode", "3", CVAR_ARCHIVE, NULL, "Set the full screen video mode."); - vid_windowed_mode = - Cvar_Get ("vid_windowed_mode", "0", CVAR_ARCHIVE, NULL, "Set the windowed video mode"); - block_switch = Cvar_Get ("block_switch", "0", CVAR_ARCHIVE, NULL, "If set, won't allow you to task switch while playing"); - vid_window_x = Cvar_Get ("vid_window_x", "0", CVAR_ARCHIVE, NULL, "The x-axis location of the window, if windowed"); - vid_window_y = Cvar_Get ("vid_window_y", "0", CVAR_ARCHIVE, NULL, "The y-axis location of the window, if windowed"); + vid_mode = Cvar_Get ("vid_mode", "0", CVAR_NONE, NULL, "Set the video " + "mode"); + vid_nopageflip = Cvar_Get ("vid_nopageflip", "0", CVAR_ARCHIVE, NULL, + "Toggles the use of page flipping"); + _vid_default_mode_win = Cvar_Get ("_vid_default_mode_win", "3", + CVAR_ARCHIVE, NULL, "Default windowed " + "video mode"); + vid_config_x = Cvar_Get ("vid_config_x", "800", CVAR_ARCHIVE, NULL, + "Maximum x-axis screen size"); + vid_config_y = Cvar_Get ("vid_config_y", "600", CVAR_ARCHIVE, NULL, + "Maximum y-axis screen size"); + vid_stretch_by_2 = Cvar_Get ("vid_stretch_by_2", "1", CVAR_ARCHIVE, NULL, + "Stretch the pixles by a two fold to acheive " + "proper view"); + _windowed_mouse = Cvar_Get ("_windowed_mouse", "0", CVAR_ARCHIVE, NULL, + "Have quake grab the mouse from X when you " + "play"); + vid_fullscreen_mode = Cvar_Get ("vid_fullscreen_mode", "3", CVAR_ARCHIVE, + NULL, "Set the full screen video mode."); + vid_windowed_mode = Cvar_Get ("vid_windowed_mode", "0", CVAR_ARCHIVE, NULL, + "Set the windowed video mode"); + block_switch = Cvar_Get ("block_switch", "0", CVAR_ARCHIVE, NULL, "If " + "set, won't allow you to task switch while " + "playing"); + vid_window_x = Cvar_Get ("vid_window_x", "0", CVAR_ARCHIVE, NULL, "The " + "x-axis location of the window, if windowed"); + vid_window_y = Cvar_Get ("vid_window_y", "0", CVAR_ARCHIVE, NULL, "The " + "y-axis location of the window, if windowed"); } - void VID_Shutdown (void) { - #ifdef SPLASH_SCREEN if (hwnd_dialog) DestroyWindow (hwnd_dialog); @@ -2092,7 +1992,8 @@ VID_Shutdown (void) PostMessage (HWND_BROADCAST, WM_PALETTECHANGED, (WPARAM) mainwindow, (LPARAM) 0); - PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM) 0, (LPARAM) 0); + PostMessage (HWND_BROADCAST, WM_SYSCOLORCHANGE, (WPARAM) 0, + (LPARAM) 0); AppActivate (false, false); DestroyDIBWindow (); @@ -2109,10 +2010,6 @@ VID_Shutdown (void) } } - -/* - FlipScreen -*/ void FlipScreen (vrect_t *rects) { @@ -2122,18 +2019,14 @@ FlipScreen (vrect_t *rects) if (memdc) { while (rects) { if (vid_stretched) { - MGL_stretchBltCoord (mgldc, memdc, - rects->x, - rects->y, - rects->x + rects->width, + MGL_stretchBltCoord (mgldc, memdc, rects->x, + rects->y, rects->x + rects->width, rects->y + rects->height, - rects->x << 1, - rects->y << 1, + rects->x << 1, rects->y << 1, (rects->x + rects->width) << 1, (rects->y + rects->height) << 1); } else { - MGL_bitBltCoord (mgldc, memdc, - rects->x, rects->y, + MGL_bitBltCoord (mgldc, memdc, rects->x, rects->y, (rects->x + rects->width), (rects->y + rects->height), rects->x, rects->y, MGL_REPLACE_MODE); @@ -2161,16 +2054,14 @@ FlipScreen (vrect_t *rects) while (rects) { if (vid_stretched) { - MGL_stretchBltCoord (windc, dibdc, - rects->x, rects->y, + MGL_stretchBltCoord (windc, dibdc, rects->x, rects->y, rects->x + rects->width, rects->y + rects->height, rects->x << 1, rects->y << 1, (rects->x + rects->width) << 1, (rects->y + rects->height) << 1); } else { - MGL_bitBltCoord (windc, dibdc, - rects->x, rects->y, + MGL_bitBltCoord (windc, dibdc, rects->x, rects->y, rects->x + rects->width, rects->y + rects->height, rects->x, rects->y, MGL_REPLACE_MODE); @@ -2184,7 +2075,6 @@ FlipScreen (vrect_t *rects) } } - void VID_Update (vrect_t *rects) { @@ -2214,15 +2104,14 @@ VID_Update (vrect_t *rects) VID_CheckWindowXY (); SetWindowPos (mainwindow, NULL, vid_window_x->int_val, - vid_window_y->int_val, 0, 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | - SWP_DRAWFRAME); + vid_window_y->int_val, 0, 0, SWP_NOSIZE | + SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); } } if ((_vid_default_mode_win->int_val != vid_default) && - (!startwindowed - || (_vid_default_mode_win->int_val < MODE_FULLSCREEN_DEFAULT))) { + (!startwindowed || (_vid_default_mode_win->int_val < + MODE_FULLSCREEN_DEFAULT))) { firstupdate = 0; if (COM_CheckParm ("-resetwinpos")) { @@ -2256,7 +2145,7 @@ VID_Update (vrect_t *rects) } } -// handle the mouse state when windowed if that's changed + // handle the mouse state when windowed if that's changed if (modestate == MS_WINDOWED) { if (!_windowed_mouse->int_val) { if (windowed_mouse) { @@ -2277,10 +2166,6 @@ VID_Update (vrect_t *rects) } } - -/* - D_BeginDirectRect -*/ void D_BeginDirectRect (int x, int y, byte * pbitmap, int width, int height) { @@ -2360,10 +2245,6 @@ D_BeginDirectRect (int x, int y, byte * pbitmap, int width, int height) } } - -/* - D_EndDirectRect -*/ void D_EndDirectRect (int x, int y, int width, int height) { @@ -2436,7 +2317,6 @@ D_EndDirectRect (int x, int y, int width, int height) } } - //========================================================================== byte scantokey[128] = { @@ -2451,7 +2331,8 @@ byte scantokey[128] = { 'b', 'n', 'm', ',', '.', '/', K_SHIFT, KP_MULTIPLY, K_ALT, ' ', K_CAPSLOCK, K_F1, K_F2, K_F3, K_F4, K_F5, // 3 K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, K_SCRLCK, KP_HOME, - KP_UPARROW, KP_PGUP, KP_MINUS, KP_LEFTARROW, KP_5, KP_RIGHTARROW, KP_PLUS, KP_END, // 4 + KP_UPARROW, KP_PGUP, KP_MINUS, KP_LEFTARROW, KP_5, KP_RIGHTARROW, KP_PLUS, + KP_END, // 4 KP_DOWNARROW, KP_PGDN, KP_INS, KP_DEL, 0, 0, 0, K_F11, K_F12, 0, 0, 0, 0, 0, 0, 0, // 5 0, 0, 0, 0, 0, 0, 0, 0, @@ -2481,8 +2362,6 @@ byte extscantokey[128] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - - /* MapKey @@ -2505,19 +2384,15 @@ MapKey (int key) return scantokey[key]; } - +/* + AppActivate + + fActive - True if app is activating + If the application is activating, then swap the system into SYSPAL_NOSTATIC + mode so that our palettes will display correctly. +*/ void AppActivate (BOOL fActive, BOOL minimize) -/**************************************************************************** -* -* Function: AppActivate -* Parameters: fActive - True if app is activating -* -* Description: If the application is activating, then swap the system -* into SYSPAL_NOSTATIC mode so that our palettes will display -* correctly. -* -****************************************************************************/ { HDC hdc; int i, t; @@ -2525,7 +2400,7 @@ AppActivate (BOOL fActive, BOOL minimize) ActiveApp = fActive; -// messy, but it seems to work + // messy, but it seems to work if (vid_fulldib_on_focus_mode) { Minimized = minimize; @@ -2567,7 +2442,7 @@ AppActivate (BOOL fActive, BOOL minimize) ReleaseDC (NULL, hdc); } -// enable/disable sound on focus gain/loss + // enable/disable sound on focus gain/loss if (!ActiveApp && sound_active) { S_BlockSound (); S_ClearBuffer (); @@ -2577,7 +2452,7 @@ AppActivate (BOOL fActive, BOOL minimize) S_ClearBuffer (); sound_active = true; } -// minimize/restore fulldib windows/mouse-capture normal windows on demand + // minimize/restore fulldib windows/mouse-capture normal windows on demand if (!in_mode_set) { if (ActiveApp) { if (vid_fulldib_on_focus_mode) { @@ -2616,8 +2491,7 @@ AppActivate (BOOL fActive, BOOL minimize) force_minimized = false; // we never seem to get WM_ACTIVATE inactive from this - // mode set, so we'll - // do it manually + // mode set, so we'll do it manually t = in_mode_set; in_mode_set = true; AppActivate (false, true); @@ -2626,9 +2500,8 @@ AppActivate (BOOL fActive, BOOL minimize) IN_DeactivateMouse (); IN_ShowMouse (); - } else if ((modestate == MS_WINDOWED) && _windowed_mouse->int_val /* && - mouseactive - */ ) { + } else if ((modestate == MS_WINDOWED) && _windowed_mouse->int_val + /* && mouseactive */ ) { IN_DeactivateMouse (); IN_ShowMouse (); } @@ -2636,10 +2509,6 @@ AppActivate (BOOL fActive, BOOL minimize) } } - -/* - VID_HandlePause -*/ void VID_HandlePause (qboolean pause) { @@ -2656,13 +2525,11 @@ VID_HandlePause (qboolean pause) #endif } - /* - MAIN WINDOW + MAIN WINDOW */ LONG CDAudio_MessageHandler (HWND hWnd, UINT uMsg, WPARAM wParam, - LPARAM lParam); /* main window procedure */ @@ -2680,222 +2547,210 @@ MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) wParam <<= 16; } - switch (uMsg) { case WM_CREATE: break; case WM_SYSCOMMAND: - // Check for maximize being hit switch (wParam & ~0x0F) { - case SC_MAXIMIZE: - // if minimized, bring up as a window before going - // fullscreen, - // so MGL will have the right state to restore - if (Minimized) { - force_mode_set = true; - VID_SetMode (vid_modenum, vid_curpal); - force_mode_set = false; - } + case SC_MAXIMIZE: + // if minimized, bring up as a window before going + // fullscreen, + // so MGL will have the right state to restore + if (Minimized) { + force_mode_set = true; + VID_SetMode (vid_modenum, vid_curpal); + force_mode_set = false; + } - VID_SetMode (vid_fullscreen_mode->int_val, vid_curpal); - break; - - case SC_SCREENSAVE: - case SC_MONITORPOWER: - if (modestate != MS_WINDOWED) { - // don't call DefWindowProc() because we don't want - // to start - // the screen saver fullscreen - break; - } - // fall through windowed and allow the screen saver to - // start - - default: - if (!in_mode_set) { - S_BlockSound (); - S_ClearBuffer (); - } - - lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); - - if (!in_mode_set) { - S_UnblockSound (); - } - } - break; - - case WM_MOVE: - window_x = (int) LOWORD (lParam); - window_y = (int) HIWORD (lParam); - VID_UpdateWindowStatus (); - - if ((modestate == MS_WINDOWED) && !in_mode_set && !Minimized) - VID_RememberWindowPos (); - - break; - - case WM_SIZE: - Minimized = false; - - if (!(wParam & SIZE_RESTORED)) { - if (wParam & SIZE_MINIMIZED) - Minimized = true; - } - break; - - case WM_SYSCHAR: - // keep Alt-Space from happening - break; - - case WM_ACTIVATE: - fActive = LOWORD (wParam); - fMinimized = (BOOL) HIWORD (wParam); - AppActivate (!(fActive == WA_INACTIVE), fMinimized); - - // fix the leftover Alt from any Alt-Tab or the like that - // switched us away - ClearAllStates (); - - if (!in_mode_set) { - if (windc) - MGL_activatePalette (windc, true); - - VID_SetPalette (vid_curpal); - } - - break; - - case WM_PAINT: - hdc = BeginPaint (hWnd, &ps); - - if (!in_mode_set && host_initialized) - SCR_UpdateWholeScreen (); - - EndPaint (hWnd, &ps); - break; - - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - if (!in_mode_set) - Key_Event (MapKey (lParam), -1, true); - break; - - case WM_KEYUP: - case WM_SYSKEYUP: - if (!in_mode_set) - Key_Event (MapKey (lParam), -1, false); - break; - - // this is complicated because Win32 seems to pack multiple mouse - // events into - // one update sometimes, so we always check all states and look - // for events - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: - case WM_RBUTTONDOWN: - case WM_RBUTTONUP: - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - case WM_MOUSEMOVE: - if (!in_mode_set) { - temp = 0; - - if (wParam & MK_LBUTTON) - temp |= 1; - - if (wParam & MK_RBUTTON) - temp |= 2; - - if (wParam & MK_MBUTTON) - temp |= 4; - - IN_MouseEvent (temp); - } - break; - // JACK: This is the mouse wheel with the Intellimouse - // Its delta is either positive or neg, and we generate the - // proper - // Event. - case WM_MOUSEWHEEL: - if ((short) HIWORD (wParam) > 0) { - Key_Event (K_MWHEELUP, -1, true); - Key_Event (K_MWHEELUP, -1, false); - } else { - Key_Event (K_MWHEELDOWN, -1, true); - Key_Event (K_MWHEELDOWN, -1, false); - } - break; - // KJB: Added these new palette functions - case WM_PALETTECHANGED: - if ((HWND) wParam == hWnd) + VID_SetMode (vid_fullscreen_mode->int_val, vid_curpal); break; - /* Fall through to WM_QUERYNEWPALETTE */ - case WM_QUERYNEWPALETTE: - hdc = GetDC (NULL); - if (GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE) - vid_palettized = true; - else - vid_palettized = false; + case SC_SCREENSAVE: + case SC_MONITORPOWER: + if (modestate != MS_WINDOWED) { + // don't call DefWindowProc() because we don't want + // to start the screen saver fullscreen + break; + } - ReleaseDC (NULL, hdc); + // fall through windowed and allow the screen saver to start + default: + if (!in_mode_set) { + S_BlockSound (); + S_ClearBuffer (); + } - scr_fullupdate = 0; + lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); - if (vid.initialized && !in_mode_set && windc - && MGL_activatePalette (windc, false) && !Minimized) { - VID_SetPalette (vid_curpal); - InvalidateRect (mainwindow, NULL, false); - - // specifically required if WM_QUERYNEWPALETTE realizes a new - // palette - lRet = TRUE; - } - break; - - case WM_DISPLAYCHANGE: - if (!in_mode_set && (modestate == MS_WINDOWED) - && !vid_fulldib_on_focus_mode) { - force_mode_set = true; - VID_SetMode (vid_modenum, vid_curpal); - force_mode_set = false; - } - break; - - case WM_CLOSE: - // this causes Close in the right-click task bar menu not to - // work, but right - // now bad things happen if Close is handled in that case - // (garbage and a - // crash on Win95) - if (!in_mode_set) { - if (MessageBox - (mainwindow, "Are you sure you want to quit?", - "Confirm Exit", - MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES) { - Sys_Quit (); + if (!in_mode_set) { + S_UnblockSound (); } } break; - case MM_MCINOTIFY: - lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam); - break; + case WM_MOVE: + window_x = (int) LOWORD (lParam); + window_y = (int) HIWORD (lParam); + VID_UpdateWindowStatus (); - default: - /* pass all unhandled messages to DefWindowProc */ - lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); + if ((modestate == MS_WINDOWED) && !in_mode_set && !Minimized) + VID_RememberWindowPos (); + + break; + + case WM_SIZE: + Minimized = false; + + if (!(wParam & SIZE_RESTORED)) { + if (wParam & SIZE_MINIMIZED) + Minimized = true; + } + break; + + case WM_SYSCHAR: + // keep Alt-Space from happening + break; + + case WM_ACTIVATE: + fActive = LOWORD (wParam); + fMinimized = (BOOL) HIWORD (wParam); + AppActivate (!(fActive == WA_INACTIVE), fMinimized); + + // fix leftover Alt from any Alt-Tab or the like that switched us away + ClearAllStates (); + + if (!in_mode_set) { + if (windc) + MGL_activatePalette (windc, true); + + VID_SetPalette (vid_curpal); + } + break; + + case WM_PAINT: + hdc = BeginPaint (hWnd, &ps); + + if (!in_mode_set && host_initialized) + SCR_UpdateWholeScreen (); + + EndPaint (hWnd, &ps); + break; + + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + if (!in_mode_set) + Key_Event (MapKey (lParam), -1, true); + break; + + case WM_KEYUP: + case WM_SYSKEYUP: + if (!in_mode_set) + Key_Event (MapKey (lParam), -1, false); + break; + + // this is complicated because Win32 seems to pack multiple mouse events + // into one update sometimes, so always check all states and look for + // events + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_MOUSEMOVE: + if (!in_mode_set) { + temp = 0; + + if (wParam & MK_LBUTTON) + temp |= 1; + + if (wParam & MK_RBUTTON) + temp |= 2; + + if (wParam & MK_MBUTTON) + temp |= 4; + + IN_MouseEvent (temp); + } + break; + // JACK: This is the mouse wheel with the Intellimouse + // Its delta is either positive or neg, and we generate the proper Event. + case WM_MOUSEWHEEL: + if ((short) HIWORD (wParam) > 0) { + Key_Event (K_MWHEELUP, -1, true); + Key_Event (K_MWHEELUP, -1, false); + } else { + Key_Event (K_MWHEELDOWN, -1, true); + Key_Event (K_MWHEELDOWN, -1, false); + } + break; + // KJB: Added these new palette functions + case WM_PALETTECHANGED: + if ((HWND) wParam == hWnd) break; + /* Fall through to WM_QUERYNEWPALETTE */ + case WM_QUERYNEWPALETTE: + hdc = GetDC (NULL); + + if (GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE) + vid_palettized = true; + else + vid_palettized = false; + + ReleaseDC (NULL, hdc); + + scr_fullupdate = 0; + + if (vid.initialized && !in_mode_set && windc + && MGL_activatePalette (windc, false) && !Minimized) { + VID_SetPalette (vid_curpal); + InvalidateRect (mainwindow, NULL, false); + + // specifically required if WM_QUERYNEWPALETTE realizes a new + // palette + lRet = TRUE; + } + break; + + case WM_DISPLAYCHANGE: + if (!in_mode_set && (modestate == MS_WINDOWED) + && !vid_fulldib_on_focus_mode) { + force_mode_set = true; + VID_SetMode (vid_modenum, vid_curpal); + force_mode_set = false; + } + break; + + case WM_CLOSE: + // this causes Close in the right-click task bar menu not to work, but + // right now bad things happen if Close is handled in that case + // (garbage and a crash on Win95) + if (!in_mode_set) { + if (MessageBox + (mainwindow, "Are you sure you want to quit?", + "Confirm Exit", + MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES) { + Sys_Quit (); + } + } + break; + + case MM_MCINOTIFY: + lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam); + break; + + default: + /* pass all unhandled messages to DefWindowProc */ + lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); + break; } /* return 0 if handled message, 1 if not */ return lRet; } - extern void M_Menu_Options_f (void); extern void M_Print (int cx, int cy, char *str); extern void M_PrintWhite (int cx, int cy, char *str); @@ -2919,9 +2774,6 @@ typedef struct { static modedesc_t modedescs[MAX_MODEDESCS]; -/* - VID_MenuDraw -*/ void VID_MenuDraw (void) { @@ -2992,8 +2844,8 @@ VID_MenuDraw (void) } } -// sort the modes on width (to handle picking up oddball dibonly modes -// after all the others) + // sort the modes on width (to handle picking up oddball dibonly modes + // after all the others) for (i = 3; i < (vid_wmodes - 1); i++) { for (j = (i + 1); j < vid_wmodes; j++) { if (modedescs[i].width > modedescs[j].width) { @@ -3004,7 +2856,6 @@ VID_MenuDraw (void) } } - M_Print (13 * 8, 36, "Windowed Modes"); column = 16; @@ -3039,7 +2890,7 @@ VID_MenuDraw (void) } } } -// line cursor + // line cursor if (vid_testingmode) { snprintf (temp, sizeof (temp), "TESTING %s", modedescs[vid_line].desc); M_Print (13 * 8, 36 + MODE_AREA_HEIGHT * 8 + 8 * 4, temp); @@ -3076,10 +2927,6 @@ VID_MenuDraw (void) } } - -/* - VID_MenuKey -*/ void VID_MenuKey (int key) { @@ -3174,8 +3021,8 @@ VID_SetCaption (const char *text) if (text && *text) { char *temp = strdup (text); - SetWindowText (mainwindow, - (LPSTR) va ("%s %s: %s", PROGRAM, VERSION, text)); + SetWindowText (mainwindow, (LPSTR) va ("%s %s: %s", PROGRAM, VERSION, + text)); free (temp); } else { SetWindowText (mainwindow, (LPSTR) va ("%s %s", PROGRAM, VERSION)); diff --git a/libs/video/targets/vid_null.c b/libs/video/targets/vid_null.c index c9b7e96be..be7bdf070 100644 --- a/libs/video/targets/vid_null.c +++ b/libs/video/targets/vid_null.c @@ -55,8 +55,8 @@ VID_Init (unsigned char *palette) vid.maxwarpheight = vid.height = vid.conheight = BASEHEIGHT; vid.aspect = 1.0; vid.numpages = 1; - vid.colormap = vid_colormap; - vid.fullbright = 256 - LittleLong (*((int *) vid.colormap + 2048)); + vid.colormap8 = vid_colormap; + vid.fullbright = 256 - LittleLong (*((int *) vid.colormap8 + 2048)); vid.buffer = vid.conbuffer = vid_buffer; vid.rowbytes = vid.conrowbytes = BASEWIDTH; @@ -79,18 +79,11 @@ VID_Update (vrect_t *rects) { } -/* - D_BeginDirectRect -*/ void D_BeginDirectRect (int x, int y, byte * pbitmap, int width, int height) { } - -/* - D_EndDirectRect -*/ void D_EndDirectRect (int x, int y, int width, int height) { diff --git a/libs/video/targets/vid_sdl.c b/libs/video/targets/vid_sdl.c index 9c6526566..8bf59c46b 100644 --- a/libs/video/targets/vid_sdl.c +++ b/libs/video/targets/vid_sdl.c @@ -39,7 +39,6 @@ #include #include -#include "compat.h" #include "QF/console.h" #include "QF/cvar.h" #include "QF/qendian.h" @@ -47,6 +46,8 @@ #include "QF/va.h" #include "QF/vid.h" +#include "compat.h" + #ifdef WIN32 /* FIXME: this is evil hack to get full DirectSound support with SDL */ #include @@ -60,8 +61,8 @@ cvar_t *vid_fullscreen; cvar_t *vid_system_gamma; extern viddef_t vid; // global video state -int modestate; // FIXME: just to avoid cross-comp. - // errors - remove later +int modestate; // FIXME: just to avoid cross-compile + // errors - remove later // The original defaults #define BASEWIDTH 320 @@ -118,8 +119,8 @@ VID_Init (unsigned char *palette) VGA_height = vid.conheight = vid.height; vid.aspect = ((float) vid.height / (float) vid.width) * (320.0 / 240.0); vid.numpages = 1; - vid.colormap = vid_colormap; - vid.fullbright = 256 - LittleLong (*((int *) vid.colormap + 2048)); + vid.colormap8 = vid_colormap; + vid.fullbright = 256 - LittleLong (*((int *) vid.colormap8 + 2048)); VGA_pagebase = vid.buffer = screen->pixels; VGA_rowbytes = vid.rowbytes = screen->pitch; vid.conbuffer = vid.buffer; @@ -132,7 +133,6 @@ VID_Init (unsigned char *palette) // initialize the mouse SDL_ShowCursor (0); - #ifdef WIN32 // FIXME: EVIL thing - but needed for win32 until // SDL_sound works better - without this DirectSound fails. @@ -143,7 +143,6 @@ VID_Init (unsigned char *palette) #endif vid.initialized = true; - } void @@ -201,9 +200,6 @@ VID_Update (vrect_t *rects) SDL_UpdateRects (screen, n, sdlrects); } -/* - D_BeginDirectRect -*/ void D_BeginDirectRect (int x, int y, byte * pbitmap, int width, int height) { @@ -222,9 +218,6 @@ D_BeginDirectRect (int x, int y, byte * pbitmap, int width, int height) } } -/* - D_EndDirectRect -*/ void D_EndDirectRect (int x, int y, int width, int height) { diff --git a/libs/video/targets/vid_sdl32.c b/libs/video/targets/vid_sdl32.c new file mode 100644 index 000000000..5863c4ffe --- /dev/null +++ b/libs/video/targets/vid_sdl32.c @@ -0,0 +1,283 @@ +/* + vid_sdl32.c + + Video driver for Sam Lantinga's Simple DirectMedia Layer + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + +#include +#include + +#include "QF/console.h" +#include "QF/cvar.h" +#include "QF/qendian.h" +#include "QF/render.h" // FIXME: should this be touching render? +#include "QF/sys.h" +#include "QF/va.h" +#include "QF/vid.h" + +//#include "compat.h" +#include "d_iface.h" +#include "d_local.h" + +#ifdef WIN32 +/* fixme: this is evil hack to get full DirectSound support with SDL */ +#include +#include +HWND mainwindow; +#endif + +// static float oldin_grab = 0; + +cvar_t *vid_fullscreen; +cvar_t *vid_bitdepth; +extern viddef_t vid; // global video state + +int modestate; // fixme: just to avoid cross-comp errors - remove later + +// The original defaults +#define BASEWIDTH 320 +#define BASEHEIGHT 200 + +int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes = 0; +byte *VGA_pagebase; + +static SDL_Surface *screen = NULL; +static SDL_Surface *rendersurface = NULL; + +extern void VID_MakeColormaps (int fullbrights, byte *pal); + + +void +VID_SetPalette (unsigned char *palette) +{ + if (vid_bitdepth->int_val == 8) + { + int i; + SDL_Color colors[256]; + + for (i = 0; i < 256; ++i) { + colors[i].r = *palette++; + colors[i].g = *palette++; + colors[i].b = *palette++; + } + SDL_SetColors (screen, colors, 0, 256); + } +} + +void +VID_Init (unsigned char *palette) +{ + Uint32 flags; + + // Load the SDL library + if (SDL_Init (SDL_INIT_VIDEO) < 0) + Sys_Error ("VID: Couldn't load SDL: %s", SDL_GetError ()); + + // Set up display mode (width and height) + VID_GetWindowSize (BASEWIDTH, BASEHEIGHT); + Con_CheckResize (); // Now that we have a window size, fix console + + vid.maxwarpwidth = WARP_WIDTH; + vid.maxwarpheight = WARP_HEIGHT; + + if (vid_bitdepth->int_val != 8 && vid_bitdepth->int_val != 16 && + vid_bitdepth->int_val != 32) + Sys_Error("unsupported vid_bitdepth %i, must be 8, 16, or 32", + vid_bitdepth->int_val); + + // Set video width, height and flags + flags = SDL_SWSURFACE; + if (vid_bitdepth->int_val == 8) + flags |= SDL_HWPALETTE; + if (vid_fullscreen->int_val) + flags |= SDL_FULLSCREEN; + + // Initialize display + if (!(screen = SDL_SetVideoMode (vid.width, vid.height, + vid_bitdepth->int_val, flags))) + Sys_Error ("VID: Couldn't set video mode: %s\n", SDL_GetError ()); + VID_SetPalette (palette); + VID_SetCaption (""); + + switch (vid_bitdepth->int_val) { + case 8: + r_pixbytes = 1; + rendersurface = screen; + break; + case 16: + r_pixbytes = 2; + rendersurface = SDL_CreateRGBSurface (SDL_SWSURFACE, vid.width, + vid.height, 16, 0xF800, 0x07E0, + 0x001F, 0x0000); + break; + case 32: + r_pixbytes = 4; + if (bigendien) + rendersurface = SDL_CreateRGBSurface + (SDL_SWSURFACE, vid.width, vid.height, 32, 0xFF000000, + 0x00FF0000, 0x0000FF00, 0x00000000); + else + rendersurface = SDL_CreateRGBSurface + (SDL_SWSURFACE, vid.width, vid.height, 32, 0x000000FF, + 0x0000FF00, 0x00FF0000, 0x00000000); + break; + default: + Sys_Error ("VID_Init: unsupported bit depth\n"); + } + + // now we know everything we need to know about the buffer + VGA_width = vid.conwidth = vid.width; + VGA_height = vid.conheight = vid.height; + vid.aspect = ((float) vid.height / (float) vid.width) * (320.0 / 240.0); + vid.numpages = 1; + if (vid_colormap) + VID_MakeColormaps(256 - vid_colormap[16384], vid_basepal); + else + VID_MakeColormaps(224, vid_basepal); + VGA_pagebase = vid.buffer = rendersurface->pixels; + VGA_rowbytes = vid.rowbytes = rendersurface->pitch; + vid.conbuffer = vid.buffer; + vid.conrowbytes = vid.rowbytes; + vid.direct = rendersurface->pixels; + + // allocate z buffer and surface cache + VID_InitBuffers (); + + // initialize the mouse + SDL_ShowCursor (0); + +#ifdef WIN32 + // fixme: EVIL thing - but needed for win32 until + // SDL_sound works better - without this DirectSound fails. + +// SDL_GetWMInfo(&info); +// mainwindow=info.window; + mainwindow=GetActiveWindow(); +#endif +} + +void +VID_UpdateFullscreen (cvar_t *vid_fullscreen) +{ + if (!vid.initialized) + return; + if ((vid_fullscreen->int_val && !(screen->flags & SDL_FULLSCREEN)) || + (!vid_fullscreen->int_val && screen->flags & SDL_FULLSCREEN)) + if (!SDL_WM_ToggleFullScreen (screen)) + Con_Printf ("VID_UpdateFullscreen: error setting fullscreen\n"); +} + +void +VID_Init_Cvars () +{ + vid_fullscreen = Cvar_Get ("vid_fullscreen", "0", CVAR_NONE, + VID_UpdateFullscreen, + "Toggles fullscreen game mode"); + vid_bitdepth = Cvar_Get ("vid_bitdepth", "8", CVAR_ROM, NULL, "Sets " + "display bitdepth (supported modes: 8 16 32)"); +} + +void +VID_Shutdown (void) +{ + SDL_Quit (); +} + +void +VID_Update (vrect_t *rects) +{ +/* FIXME + if (vid_bitdepth->int_val != 8) + { + // blit internal framebuffer to display buffer + SDL_BlitSurface(rendersurface, &rects, screen, &rects); + } + // update display + SDL_UpdateRect (screen, rects); +*/ +} + +void +D_BeginDirectRect (int x, int y, byte * pbitmap, int width, int height) +{ + /* + Uint8 *offset; + + + if (!screen) + return; + if (x < 0) + x = screen->w + x - 1; + offset = (Uint8 *) screen->pixels + y * screen->pitch + x; + while (height--) { + memcpy (offset, pbitmap, width); + offset += screen->pitch; + pbitmap += width; + } + */ +} + +void +D_EndDirectRect (int x, int y, int width, int height) +{ + /* + if (!screen) + return; + if (x < 0) + x = screen->w + x - 1; + SDL_UpdateRect (screen, x, y, width, height); + */ +} + +void +VID_LockBuffer (void) +{ +} + +void +VID_UnlockBuffer (void) +{ +} + +void +VID_SetCaption (const char *text) +{ + if (text && *text) { + char *temp = strdup (text); + SDL_WM_SetCaption (va ("%s %s: %s", PROGRAM, VERSION, temp), NULL); + free (temp); + } else + SDL_WM_SetCaption (va ("%s %s", PROGRAM, VERSION), NULL); +} diff --git a/libs/video/targets/vid_sgl.c b/libs/video/targets/vid_sgl.c index 9d3f478c4..a40c9aa84 100644 --- a/libs/video/targets/vid_sgl.c +++ b/libs/video/targets/vid_sgl.c @@ -41,8 +41,6 @@ #include -#include "compat.h" -#include "QF/GL/funcs.h" #include "QF/console.h" #include "QF/cvar.h" #include "QF/qargs.h" @@ -50,7 +48,9 @@ #include "QF/sys.h" #include "QF/va.h" #include "QF/vid.h" +#include "QF/GL/funcs.h" +#include "compat.h" #include "sbar.h" #ifdef WIN32 @@ -72,7 +72,6 @@ int modestate; extern void GL_Init_Common (void); extern void VID_Init8bitPalette (void); -/*-----------------------------------------------------------------------*/ void VID_SDL_GammaCheck (void) @@ -135,14 +134,14 @@ VID_Init (unsigned char *palette) Uint32 flags = SDL_OPENGL; int i; -// SDL_SysWMinfo info; +// SDL_SysWMinfo info; VID_GetWindowSize (640, 480); vid.maxwarpwidth = WARP_WIDTH; vid.maxwarpheight = WARP_HEIGHT; - vid.colormap = vid_colormap; - vid.fullbright = 256 - LittleLong (*((int *) vid.colormap + 2048)); + vid.colormap8 = vid_colormap; + vid.fullbright = 256 - LittleLong (*((int *) vid.colormap8 + 2048)); // Interpret command-line params diff --git a/libs/video/targets/vid_svgalib.c b/libs/video/targets/vid_svgalib.c index 5b018afca..0dcd60068 100644 --- a/libs/video/targets/vid_svgalib.c +++ b/libs/video/targets/vid_svgalib.c @@ -52,7 +52,6 @@ #include #include "QF/cmd.h" -#include "compat.h" #include "QF/console.h" #include "QF/cvar.h" #include "QF/input.h" @@ -61,6 +60,8 @@ #include "QF/sys.h" #include "QF/vid.h" +#include "compat.h" + void VGA_UpdatePlanarScreen (void *srcbuffer); cvar_t *vid_system_gamma; @@ -80,7 +81,6 @@ static cvar_t *vid_waitforrefresh; static char *framebuffer_ptr; - static byte backingbuf[48 * 24]; int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar; @@ -146,7 +146,6 @@ D_BeginDirectRect (int x, int y, byte * pbitmap, int width, int height) } } - void D_EndDirectRect (int x, int y, int width, int height) { @@ -199,7 +198,6 @@ D_EndDirectRect (int x, int y, int width, int height) } } - static void VID_DescribeMode_f (void) { @@ -218,7 +216,6 @@ VID_DescribeMode_f (void) } } - static void VID_DescribeModes_f (void) { @@ -235,10 +232,6 @@ VID_DescribeModes_f (void) } } - -/* - VID_NumModes -*/ static int VID_NumModes (void) { @@ -250,14 +243,12 @@ VID_NumModes (void) return (i1); } - static void VID_NumModes_f (void) { Con_Printf ("%d modes\n", VID_NumModes ()); } - static void VID_Debug_f (void) { @@ -267,7 +258,6 @@ VID_Debug_f (void) Con_Printf ("vid.aspect: %f\n", vid.aspect); } - static void VID_InitModes (void) { @@ -292,7 +282,6 @@ VID_InitModes (void) } } - static int get_mode (char *name, int width, int height, int depth) { @@ -326,7 +315,6 @@ get_mode (char *name, int width, int height, int depth) return i; } - void VID_Shutdown (void) { @@ -341,7 +329,6 @@ VID_Shutdown (void) svgalib_inited = 0; } - void VID_SetPalette (byte * palette) { @@ -366,7 +353,6 @@ VID_SetPalette (byte * palette) } } - int VID_SetMode (int modenum, unsigned char *palette) { @@ -398,8 +384,8 @@ VID_SetMode (int modenum, unsigned char *palette) } vid.aspect = ((float) vid.height / (float) vid.width) * (320.0 / 240.0); - vid.colormap = (pixel_t *) vid_colormap; - vid.fullbright = 256 - LittleLong (*((int *) vid.colormap + 2048)); + vid.colormap8 = (byte *) vid_colormap; + vid.fullbright = 256 - LittleLong (*((int *) vid.colormap8 + 2048)); vid.conrowbytes = vid.rowbytes; vid.conwidth = vid.width; vid.conheight = vid.height; @@ -447,7 +433,6 @@ comefrom_background (void) svgalib_backgrounded = 0; } - void VID_Init (unsigned char *palette) { @@ -475,10 +460,13 @@ VID_Init (unsigned char *palette) VID_InitModes (); - Cmd_AddCommand ("vid_nummodes", VID_NumModes_f, "Reports the total number of video modes available."); - Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f, "Report information on specified video mode, default is current.\n" - "(vid_describemode (mode))"); - Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f, "Report information on all video modes."); + Cmd_AddCommand ("vid_nummodes", VID_NumModes_f, "Reports the total " + "number of video modes available."); + Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f, "Report " + "information on specified video mode, default is " + "current.\n(vid_describemode (mode))"); + Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f, "Report " + "information on all video modes."); Cmd_AddCommand ("vid_debug", VID_Debug_f, "FIXME: No Description"); /* Interpret command-line params */ @@ -528,7 +516,6 @@ VID_Init_Cvars () "Use system gamma control if available"); } - void VID_Update (vrect_t *rects) { @@ -594,7 +581,6 @@ VID_Update (vrect_t *rects) } } - static int dither = 0; void @@ -608,7 +594,6 @@ VID_DitherOn (void) } } - void VID_DitherOff (void) { @@ -620,10 +605,6 @@ VID_DitherOff (void) } } - -/* - VID_ModeInfo -*/ char * VID_ModeInfo (int modenum) { @@ -631,22 +612,20 @@ VID_ModeInfo (int modenum) static char modestr[40]; if (modenum == 0) { - snprintf (modestr, sizeof (modestr), "%d x %d, %d bpp", - vid.width, vid.height, modes[current_mode].bytesperpixel * 8); + snprintf (modestr, sizeof (modestr), "%d x %d, %d bpp", vid.width, + vid.height, modes[current_mode].bytesperpixel * 8); return (modestr); } else { return (badmodestr); } } - void VID_ExtraOptionDraw (unsigned int options_draw_cursor) { /* No extra option menu items yet */ } - void VID_ExtraOptionCmd (int option_cursor) { diff --git a/libs/video/targets/vid_vga.c b/libs/video/targets/vid_vga.c index 541546260..8c1cce2fe 100644 --- a/libs/video/targets/vid_vga.c +++ b/libs/video/targets/vid_vga.c @@ -329,15 +329,15 @@ VGA_InitMode (viddef_t *lvid, vmode_t * pcurrentmode) if (VGA_pcurmode) VGA_ClearVideoMem (VGA_pcurmode->planar); -// mode 0x13 is the base for all the Mode X-class mode sets + // mode 0x13 is the base for all the Mode X-class mode sets regs.h.ah = 0; regs.h.al = 0x13; dos_int86 (0x10); VGA_pagebase = (void *) real2ptr (0xa0000); - lvid->direct = (pixel_t *) VGA_pagebase; + lvid->direct = (byte *) VGA_pagebase; -// set additional registers as needed + // set additional registers as needed VideoRegisterSet (pextra->pregset); VGA_numpages = 1; diff --git a/libs/video/targets/vid_wgl.c b/libs/video/targets/vid_wgl.c index 4861fd360..c4f27f9de 100644 --- a/libs/video/targets/vid_wgl.c +++ b/libs/video/targets/vid_wgl.c @@ -32,7 +32,6 @@ #include "winquake.h" -#include "QF/GL/funcs.h" #include "QF/cdaudio.h" #include "QF/cmd.h" #include "QF/console.h" @@ -41,18 +40,19 @@ #include "QF/keys.h" #include "QF/qargs.h" #include "QF/qendian.h" -#include "QF/vfs.h" #include "QF/screen.h" #include "QF/sound.h" #include "QF/sys.h" #include "QF/va.h" +#include "QF/vfs.h" #include "QF/vid.h" +#include "QF/GL/funcs.h" #include "compat.h" -#include "sbar.h" #include "in_win.h" #include "r_cvar.h" #include "resource.h" +#include "sbar.h" extern void GL_Init_Common (void); extern void VID_Init8bitPalette (void); @@ -167,13 +167,10 @@ void GL_Init (void); cvar_t *_windowed_mouse; cvar_t *vid_use8bit; - int window_center_x, window_center_y, window_x, window_y, window_width, - - window_height; + window_height; RECT window_rect; -// direct draw software compatability stuff void VID_ForceLockState (int lk) @@ -229,13 +226,13 @@ VID_SetWindowedMode (int modenum) // Create the window mainwindow = CreateWindow ("QuakeForge", "GLQuakeWorld", - WindowStyle, rect.left, rect.top, width, height, NULL, NULL, - global_hInstance, NULL); + WindowStyle, rect.left, rect.top, width, height, + NULL, NULL, global_hInstance, NULL); if (!mainwindow) - Sys_Error ("Couldn't create DIB window (%lx)\r\n",GetLastError()); + Sys_Error ("Couldn't create DIB window (%lx)\r\n",GetLastError()); -// Center and show the window + // Center and show the window CenterWindow (mainwindow, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top, false); @@ -248,7 +245,7 @@ VID_SetWindowedMode (int modenum) // (to avoid flickering when re-sizing the window on the desktop), // we clear the window to black when created, otherwise it will be // empty while Quake starts up. - hdc = GetDC (mainwindow); + hdc = GetDC (mainwindow); PatBlt (hdc, 0, 0, WindowRect.right, WindowRect.bottom, BLACKNESS); ReleaseDC (mainwindow, hdc); @@ -269,7 +266,6 @@ VID_SetWindowedMode (int modenum) return true; } - qboolean VID_SetFullDIBMode (int modenum) { @@ -289,7 +285,8 @@ VID_SetFullDIBMode (int modenum) if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) - Sys_Error ("Couldn't set fullscreen DIB mode (%lx)\r\n",GetLastError()); + Sys_Error ("Couldn't set fullscreen DIB mode (%lx)\r\n", + GetLastError()); } lastmodestate = modestate; @@ -308,8 +305,8 @@ VID_SetFullDIBMode (int modenum) // until I find way around it, or find some other cause for it // this is way to avoid it - if (COM_CheckParm ("-brokenpopup")) WindowStyle = 0; - else WindowStyle = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; + if (COM_CheckParm ("-brokenpopup")) WindowStyle = 0; + else WindowStyle = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; rect = WindowRect; AdjustWindowRect (&rect, WindowStyle, FALSE); @@ -323,7 +320,7 @@ VID_SetFullDIBMode (int modenum) global_hInstance, NULL); if (!mainwindow) - Sys_Error ("Couldn't create DIB window (%lx)\r\n",GetLastError()); + Sys_Error ("Couldn't create DIB window (%lx)\r\n",GetLastError()); ShowWindow (mainwindow, SW_SHOWDEFAULT); UpdateWindow (mainwindow); @@ -345,7 +342,7 @@ VID_SetFullDIBMode (int modenum) vid.numpages = 2; -// needed because we're not getting WM_MOVE messages fullscreen on NT + // needed because we're not getting WM_MOVE messages fullscreen on NT window_x = 0; window_y = 0; @@ -357,7 +354,6 @@ VID_SetFullDIBMode (int modenum) return true; } - int VID_SetMode (int modenum, unsigned char *palette) { @@ -369,7 +365,8 @@ VID_SetMode (int modenum, unsigned char *palette) (!windowed && (modenum < 1)) || (!windowed && (modenum >= nummodes))) { Sys_Error ("Bad video mode\n"); } -// so Con_Printfs don't mess us up by forcing vid and snd updates + + // so Con_Printfs don't mess us up by forcing vid and snd updates temp = scr_disabled_for_loading; scr_disabled_for_loading = true; @@ -430,7 +427,7 @@ VID_SetMode (int modenum, unsigned char *palette) SetForegroundWindow (mainwindow); -// fix the leftover Alt from any Alt-Tab or the like that switched us away + // fix the leftover Alt from any Alt-Tab or the like that switched us away ClearAllStates (); Con_Printf ("Video mode %s initialized.\n", @@ -443,10 +440,6 @@ VID_SetMode (int modenum, unsigned char *palette) return true; } - -/* - VID_UpdateWindowStatus -*/ void VID_UpdateWindowStatus (void) { @@ -461,9 +454,6 @@ VID_UpdateWindowStatus (void) IN_UpdateClipCursor (); } -/* - GL_Init -*/ void GL_Init (void) { @@ -481,7 +471,7 @@ GL_EndRendering (void) if (!scr_skipupdate || block_drawing) SwapBuffers (maindc); -// handle the mouse state when windowed if that's changed + // handle the mouse state when windowed if that's changed if (modestate == MS_WINDOWED) { if (!_windowed_mouse->int_val) { if (windowed_mouse) { @@ -510,7 +500,6 @@ VID_SetDefaultMode (void) IN_DeactivateMouse (); } - void VID_Shutdown (void) { @@ -551,7 +540,6 @@ VID_Shutdown (void) } } - //========================================================================== BOOL @@ -563,7 +551,8 @@ bSetupPixelFormat (HDC hDC) memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); pfd.nVersion = 1; - pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW; + pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | + PFD_DRAW_TO_WINDOW; pfd.iPixelType = PFD_TYPE_RGBA; if (!modelist[vid_default].bpp) pfd.cColorBits = 16; @@ -584,7 +573,6 @@ bSetupPixelFormat (HDC hDC) return TRUE; } - //========================================================================== byte scantokey[128] = { @@ -629,8 +617,6 @@ byte extscantokey[128] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - - /* MapKey @@ -653,40 +639,32 @@ MapKey (int key) return scantokey[key]; } - /* MAIN WINDOW */ - -/* - ClearAllStates -*/ void ClearAllStates (void) { IN_ClearStates (); } +/* + AppActivate + + fActive - True if app is activating + If the application is activating, then swap the system into SYSPAL_NOSTATIC + mode so that our palettes will display correctly. +*/ void AppActivate (BOOL fActive, BOOL minimize) -/**************************************************************************** -* -* Function: AppActivate -* Parameters: fActive - True if app is activating -* -* Description: If the application is activating, then swap the system -* into SYSPAL_NOSTATIC mode so that our palettes will display -* correctly. -* -****************************************************************************/ { static BOOL sound_active; ActiveApp = fActive; Minimized = minimize; -// enable/disable sound on focus gain/loss + // enable/disable sound on focus gain/loss if (!ActiveApp && sound_active) { S_BlockSound (); sound_active = false; @@ -705,12 +683,15 @@ AppActivate (BOOL fActive, BOOL minimize) if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) { IN_ShowMouse (); - Sys_Error ("Couldn't set fullscreen DIB mode\n(try upgrading your video drivers)\r\n (%lx)",GetLastError()); + Sys_Error ("Couldn't set fullscreen DIB mode\n(try " + "upgrading your video drivers)\r\n (%lx)", + GetLastError()); } ShowWindow (mainwindow, SW_SHOWNORMAL); // Fix for alt-tab bug in NVidia drivers - MoveWindow(mainwindow,0,0,gdevmode.dmPelsWidth,gdevmode.dmPelsHeight,false); + MoveWindow(mainwindow, 0, 0, gdevmode.dmPelsWidth, + gdevmode.dmPelsHeight, false); } } else if ((modestate == MS_WINDOWED) && _windowed_mouse->int_val @@ -718,7 +699,6 @@ AppActivate (BOOL fActive, BOOL minimize) IN_ActivateMouse (); IN_HideMouse (); } - } else { if (modestate == MS_FULLDIB) { IN_DeactivateMouse (); @@ -734,7 +714,6 @@ AppActivate (BOOL fActive, BOOL minimize) } } - /* main window procedure */ LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) @@ -747,144 +726,121 @@ MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) uMsg = WM_MOUSEWHEEL; switch (uMsg) { - case WM_KILLFOCUS: - if (modestate == MS_FULLDIB) - ShowWindow (mainwindow, SW_SHOWMINNOACTIVE); - break; + case WM_KILLFOCUS: + if (modestate == MS_FULLDIB) + ShowWindow (mainwindow, SW_SHOWMINNOACTIVE); + break; + case WM_CREATE: + break; - case WM_CREATE: - break; + case WM_MOVE: + window_x = (int) LOWORD (lParam); + window_y = (int) HIWORD (lParam); + VID_UpdateWindowStatus (); + break; - case WM_MOVE: - window_x = (int) LOWORD (lParam); - window_y = (int) HIWORD (lParam); - VID_UpdateWindowStatus (); - break; + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + Key_Event (MapKey (lParam), -1, true); + break; - case WM_KEYDOWN: - case WM_SYSKEYDOWN: - Key_Event (MapKey (lParam), -1, true); - break; + case WM_KEYUP: + case WM_SYSKEYUP: + Key_Event (MapKey (lParam), -1, false); + break; - case WM_KEYUP: - case WM_SYSKEYUP: - Key_Event (MapKey (lParam), -1, false); - break; + case WM_SYSCHAR: + // keep Alt-Space from happening + break; - case WM_SYSCHAR: - // keep Alt-Space from happening - break; + // this is complicated because Win32 seems to pack multiple mouse events + // into one update sometimes, so we always check all states and look for + // events + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + case WM_MOUSEMOVE: + temp = 0; - // this is complicated because Win32 seems to pack multiple mouse - // events into - // one update sometimes, so we always check all states and look - // for events - case WM_LBUTTONDOWN: - case WM_LBUTTONUP: - case WM_RBUTTONDOWN: - case WM_RBUTTONUP: - case WM_MBUTTONDOWN: - case WM_MBUTTONUP: - case WM_MOUSEMOVE: - temp = 0; + if (wParam & MK_LBUTTON) + temp |= 1; + if (wParam & MK_RBUTTON) + temp |= 2; + if (wParam & MK_MBUTTON) + temp |= 4; + IN_MouseEvent (temp); - if (wParam & MK_LBUTTON) - temp |= 1; + break; - if (wParam & MK_RBUTTON) - temp |= 2; + // JACK: This is the mouse wheel with the Intellimouse + // It's delta is either positive or neg, and we generate the proper Event. + case WM_MOUSEWHEEL: + if ((short) HIWORD (wParam) > 0) { + Key_Event (M_WHEEL_UP, -1, true); + Key_Event (M_WHEEL_UP, -1, false); + } else { + Key_Event (M_WHEEL_DOWN, -1, true); + Key_Event (M_WHEEL_DOWN, -1, false); + } + break; - if (wParam & MK_MBUTTON) - temp |= 4; + case WM_SIZE: + break; - IN_MouseEvent (temp); + case WM_CLOSE: + if (MessageBox + (mainwindow, "Are you sure you want to quit?", "Confirm Exit", + MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES) { + Sys_Quit (); + } + break; - break; + case WM_ACTIVATE: + fActive = LOWORD (wParam); + fMinimized = (BOOL) HIWORD (wParam); + AppActivate (!(fActive == WA_INACTIVE), fMinimized); + // fix leftover Alt from any Alt-Tab or the like that switched us away + ClearAllStates (); + break; - // JACK: This is the mouse wheel with the Intellimouse - // Its delta is either positive or neg, and we generate the - // proper - // Event. - case WM_MOUSEWHEEL: - if ((short) HIWORD (wParam) > 0) { - Key_Event (M_WHEEL_UP, -1, true); - Key_Event (M_WHEEL_UP, -1, false); - } else { - Key_Event (M_WHEEL_DOWN, -1, true); - Key_Event (M_WHEEL_DOWN, -1, false); - } - break; + case WM_DESTROY: + if (mainwindow) + DestroyWindow (mainwindow); + PostQuitMessage (0); + break; - case WM_SIZE: - break; + case MM_MCINOTIFY: + //FIXME lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam); + break; - case WM_CLOSE: - if (MessageBox - (mainwindow, "Are you sure you want to quit?", "Confirm Exit", - MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES) { - Sys_Quit (); - } - - break; - - case WM_ACTIVATE: - fActive = LOWORD (wParam); - fMinimized = (BOOL) HIWORD (wParam); - AppActivate (!(fActive == WA_INACTIVE), fMinimized); - // fix the leftover Alt from any Alt-Tab or the like that - // switched us away - ClearAllStates (); - - break; - - case WM_DESTROY: - if (mainwindow) - DestroyWindow (mainwindow); - PostQuitMessage (0); - break; - - case MM_MCINOTIFY: - //FIXME lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam); - break; - - default: - /* pass all unhandled messages to DefWindowProc */ - lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); - break; + default: + /* pass all unhandled messages to DefWindowProc */ + lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); + break; } /* return 1 if handled message, 0 if not */ return lRet; } - -/* - VID_NumModes -*/ int VID_NumModes (void) { return nummodes; } - -/* - VID_GetModePtr -*/ vmode_t * VID_GetModePtr (int modenum) { - if ((modenum >= 0) && (modenum < nummodes)) return &modelist[modenum]; else return &badmode; } - -/* - VID_GetModeDescription -*/ char * VID_GetModeDescription (int mode) { @@ -910,7 +866,6 @@ VID_GetModeDescription (int mode) // KJB: Added this to return the mode driver name in description for console - char * VID_GetExtModeDescription (int mode) { @@ -939,34 +894,21 @@ VID_GetExtModeDescription (int mode) return pinfo; } - -/* - VID_DescribeCurrentMode_f -*/ void VID_DescribeCurrentMode_f (void) { Con_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum)); } - -/* - VID_NumModes_f -*/ void VID_NumModes_f (void) { - if (nummodes == 1) Con_Printf ("%d video mode is available\n", nummodes); else Con_Printf ("%d video modes are available\n", nummodes); } - -/* - VID_DescribeMode_f -*/ void VID_DescribeMode_f (void) { @@ -982,10 +924,6 @@ VID_DescribeMode_f (void) leavecurrentmode = t; } - -/* - VID_DescribeModes_f -*/ void VID_DescribeModes_f (void) { @@ -1007,7 +945,6 @@ VID_DescribeModes_f (void) leavecurrentmode = t; } - void VID_InitDIB (HINSTANCE hInstance) { @@ -1026,7 +963,7 @@ VID_InitDIB (HINSTANCE hInstance) wc.lpszClassName = "QuakeForge"; if (!RegisterClass (&wc)) - Sys_Error ("Couldn't register window class (%lx)\r\n",GetLastError()); + Sys_Error ("Couldn't register window class (%lx)\r\n", GetLastError()); modelist[0].type = MS_WINDOWED; @@ -1058,10 +995,6 @@ VID_InitDIB (HINSTANCE hInstance) nummodes = 1; } - -/* - VID_InitFullDIB -*/ void VID_InitFullDIB (HINSTANCE hInstance) { @@ -1070,7 +1003,7 @@ VID_InitFullDIB (HINSTANCE hInstance) int j, bpp, done; BOOL stat; -// enumerate >8 bpp modes + // enumerate >8 bpp modes originalnummodes = nummodes; modenum = 0; @@ -1079,7 +1012,8 @@ VID_InitFullDIB (HINSTANCE hInstance) if ((devmode.dmBitsPerPel >= 15) && (devmode.dmPelsWidth <= MAXWIDTH) && - (devmode.dmPelsHeight <= MAXHEIGHT) && (nummodes < MAX_MODE_LIST)) { + (devmode.dmPelsHeight <= MAXHEIGHT) && + (nummodes < MAX_MODE_LIST)) { devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == @@ -1098,8 +1032,7 @@ VID_InitFullDIB (HINSTANCE hInstance) devmode.dmBitsPerPel); // if the width is more than twice the height, reduce it by - // half because this - // is probably a dual-screen monitor + // half because this is probably a dual-screen monitor if (!COM_CheckParm ("-noadjustaspect")) { if (modelist[nummodes].width > (modelist[nummodes].height << 1)) { @@ -1113,7 +1046,8 @@ VID_InitFullDIB (HINSTANCE hInstance) } } - for (i = originalnummodes, existingmode = 0; i < nummodes; i++) { + for (i = originalnummodes, existingmode = 0; i < nummodes; + i++) { if ((modelist[nummodes].width == modelist[i].width) && (modelist[nummodes].height == modelist[i].height) && (modelist[nummodes].bpp == modelist[i].bpp)) { @@ -1131,7 +1065,7 @@ VID_InitFullDIB (HINSTANCE hInstance) modenum++; } while (stat); -// see if there are any low-res modes that aren't being reported + // see if there are any low-res modes that aren't being reported numlowresmodes = sizeof (lowresmodes) / sizeof (lowresmodes[0]); bpp = 16; done = 0; @@ -1158,7 +1092,8 @@ VID_InitFullDIB (HINSTANCE hInstance) devmode.dmPelsWidth, devmode.dmPelsHeight, devmode.dmBitsPerPel); - for (i = originalnummodes, existingmode = 0; i < nummodes; i++) { + for (i = originalnummodes, existingmode = 0; i < nummodes; + i++) { if ((modelist[nummodes].width == modelist[i].width) && (modelist[nummodes].height == modelist[i].height) && (modelist[nummodes].bpp == modelist[i].bpp)) { @@ -1191,9 +1126,6 @@ VID_InitFullDIB (HINSTANCE hInstance) Con_Printf ("No fullscreen DIB modes found\n"); } -/* - VID_Init -*/ void VID_Init (unsigned char *palette) { @@ -1210,24 +1142,33 @@ VID_Init (unsigned char *palette) return; } - qf_wglCreateContext = QFGL_ProcAddress (libgl_handle, "wglCreateContext", true); - qf_wglDeleteContext = QFGL_ProcAddress (libgl_handle, "wglDeleteContext", true); - qf_wglGetCurrentContext = QFGL_ProcAddress (libgl_handle, "wglGetCurrentContext", true); - qf_wglGetCurrentDC = QFGL_ProcAddress (libgl_handle, "wglGetCurrentDC", true); - qf_wglMakeCurrent = QFGL_ProcAddress (libgl_handle, "wglMakeCurrent", true); + qf_wglCreateContext = QFGL_ProcAddress (libgl_handle, "wglCreateContext", + true); + qf_wglDeleteContext = QFGL_ProcAddress (libgl_handle, "wglDeleteContext", + true); + qf_wglGetCurrentContext = QFGL_ProcAddress (libgl_handle, + "wglGetCurrentContext", true); + qf_wglGetCurrentDC = QFGL_ProcAddress (libgl_handle, "wglGetCurrentDC", + true); + qf_wglMakeCurrent = QFGL_ProcAddress (libgl_handle, "wglMakeCurrent", + true); memset (&devmode, 0, sizeof (devmode)); - Cmd_AddCommand ("vid_nummodes", VID_NumModes_f, "Reports the total number of video modes available"); - Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f, "Report current video mode."); - Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f, "Report information on specified video mode, default is current.\n" - "(vid_describemode (mode))"); - Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f, "Report information on all video modes."); + Cmd_AddCommand ("vid_nummodes", VID_NumModes_f, "Reports the total number " + "of video modes available"); + Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f, + "Report current video mode."); + Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f, "Report " + "information on specified video mode, default is " + "current.\n(vid_describemode (mode))"); + Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f, "Report " + "information on all video modes."); hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON1)); // FIXME: If you put these back, remember commctrl.h -// InitCommonControls (); +// InitCommonControls (); VID_InitDIB (global_hInstance); basenummodes = nummodes = 1; @@ -1280,8 +1221,7 @@ VID_Init (unsigned char *palette) if (COM_CheckParm ("-height")) height = atoi (com_argv[COM_CheckParm ("-height") + 1]); - // if they want to force it, add the specified mode to the - // list + // if they want to force it, add the specified mode to the list if (COM_CheckParm ("-force") && (nummodes < MAX_MODE_LIST)) { modelist[nummodes].type = MS_FULLDIB; modelist[nummodes].width = width; @@ -1298,8 +1238,8 @@ VID_Init (unsigned char *palette) for (i = nummodes, existingmode = 0; i < nummodes; i++) { if ((modelist[nummodes].width == modelist[i].width) && - (modelist[nummodes].height == modelist[i].height) && - (modelist[nummodes].bpp == modelist[i].bpp)) { + (modelist[nummodes].height == modelist[i].height) + && (modelist[nummodes].bpp == modelist[i].bpp)) { existingmode = 1; break; } @@ -1314,7 +1254,8 @@ VID_Init (unsigned char *palette) do { if (COM_CheckParm ("-height")) { - height = atoi (com_argv[COM_CheckParm ("-height") + 1]); + height = atoi (com_argv[COM_CheckParm ("-height") + + 1]); for (i = 1, vid_default = 0; i < nummodes; i++) { if ((modelist[i].width == width) && @@ -1387,8 +1328,8 @@ VID_Init (unsigned char *palette) vid.maxwarpwidth = WARP_WIDTH; vid.maxwarpheight = WARP_HEIGHT; - vid.colormap = vid_colormap; - vid.fullbright = 256 - LittleLong (*((int *) vid.colormap + 2048)); + vid.colormap8 = vid_colormap; + vid.fullbright = 256 - LittleLong (*((int *) vid.colormap8 + 2048)); #ifdef SPLASH_SCREEN if(hwnd_dialog) @@ -1408,7 +1349,9 @@ VID_Init (unsigned char *palette) lasterror=GetLastError(); if (maindc && mainwindow) ReleaseDC (mainwindow, maindc); - Sys_Error("Could not initialize GL (wglCreateContext failed).\n\nMake sure you in are 65535 color mode, and try running -window. \nError code: (%lx)\r\n",lasterror); + Sys_Error("Could not initialize GL (wglCreateContext failed).\n\nMake " + "sure you in are 65535 color mode, and try running -window. " + "\nError code: (%lx)\r\n", lasterror); } if (!qf_wglMakeCurrent (maindc, baseRC)) { @@ -1417,7 +1360,7 @@ VID_Init (unsigned char *palette) qf_wglDeleteContext (baseRC); if (maindc && mainwindow) ReleaseDC (mainwindow, maindc); - Sys_Error ("wglMakeCurrent failed (%lx)\r\n",lasterror); + Sys_Error ("wglMakeCurrent failed (%lx)\r\n", lasterror); } GL_Init (); @@ -1442,10 +1385,7 @@ VID_Init_Cvars () { } - -//======================================================== -// Video menu stuff -//======================================================== +// Video menu stuff ====================================== typedef struct { int modenum; @@ -1459,7 +1399,6 @@ typedef struct { //static modedesc_t modedescs[MAX_MODEDESCS]; - void VID_SetCaption (const char *text) { diff --git a/libs/video/targets/vid_x11.c b/libs/video/targets/vid_x11.c index e7e75da63..6507705f3 100644 --- a/libs/video/targets/vid_x11.c +++ b/libs/video/targets/vid_x11.c @@ -50,15 +50,14 @@ #include #include #include +#include +#include #include #include - #include #include #include #include -#include -#include #include #ifdef HAVE_VIDMODE @@ -66,7 +65,6 @@ #endif #include "QF/cmd.h" -#include "compat.h" #include "QF/console.h" #include "QF/cvar.h" #include "QF/qargs.h" @@ -76,6 +74,7 @@ #include "QF/va.h" #include "QF/vid.h" +#include "compat.h" #include "context_x11.h" #include "dga_check.h" @@ -111,6 +110,7 @@ static unsigned long r_mask, g_mask, b_mask; cvar_t *vid_width; cvar_t *vid_height; + static void shiftmask_init (void) { @@ -129,7 +129,7 @@ shiftmask_init (void) shiftmask_fl = 1; } -static PIXEL16 +static PIXEL16 xlib_rgb16 (int r, int g, int b) { PIXEL16 p = 0; @@ -170,7 +170,6 @@ xlib_rgb16 (int r, int g, int b) return p; } - static PIXEL24 xlib_rgb24 (int r, int g, int b) { @@ -231,7 +230,6 @@ st2_fixup (XImage *framebuf, int x, int y, int width, int height) } } - static void st3_fixup (XImage * framebuf, int x, int y, int width, int height) { @@ -279,26 +277,18 @@ st3_fixup (XImage * framebuf, int x, int y, int width, int height) } } -/* - D_BeginDirectRect -*/ void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) { // direct drawing of the "accessing disk" icon isn't supported } - -/* - D_EndDirectRect -*/ void D_EndDirectRect (int x, int y, int width, int height) { // direct drawing of the "accessing disk" icon isn't supported } - static void ResetFrameBuffer (void) { @@ -419,7 +409,8 @@ VID_Init (unsigned char *palette) int num_visuals; int template_mask; - Cmd_AddCommand ("vid_center", VID_Center_f, "Center the view port on the quake window in a virtual desktop.\n"); + Cmd_AddCommand ("vid_center", VID_Center_f, "Center the view port on the " + "quake window in a virtual desktop.\n"); VID_GetWindowSize (320, 200); @@ -428,8 +419,8 @@ VID_Init (unsigned char *palette) Con_CheckResize (); // Now that we have a window size, fix console vid.numpages = 2; - vid.colormap = vid_colormap; - vid.fullbright = 256 - LittleLong (*((int *) vid.colormap + 2048)); + vid.colormap8 = vid_colormap; + vid.fullbright = 256 - LittleLong (*((int *) vid.colormap8 + 2048)); srandom (getpid ()); @@ -454,11 +445,13 @@ VID_Init (unsigned char *palette) } // pick a visual -- warn if more than one was available - x_visinfo = XGetVisualInfo (x_disp, template_mask, &template, &num_visuals); + x_visinfo = XGetVisualInfo (x_disp, template_mask, &template, + &num_visuals); x_vis = x_visinfo->visual; if (num_visuals > 1) { - printf ("Found more than one visual id at depth %d:\n", template.depth); + printf ("Found more than one visual id at depth %d:\n", + template.depth); for (i = 0; i < num_visuals; i++) printf (" -visualid %d\n", (int) x_visinfo[i].visualid); } else { @@ -560,7 +553,6 @@ VID_Init_Cvars () X11_Init_Cvars (); } - void VID_SetPalette (unsigned char *palette) { @@ -589,7 +581,6 @@ VID_SetPalette (unsigned char *palette) } } - /* VID_Shutdown @@ -682,7 +673,6 @@ VID_DitherOn (void) } } - void VID_DitherOff (void) { diff --git a/nq/source/.indent.pro b/nq/source/.indent.pro index b638c4a2d..4e01e695a 100644 --- a/nq/source/.indent.pro +++ b/nq/source/.indent.pro @@ -147,7 +147,6 @@ -T particle_t -T pcx_t -T physent_t --T pixel_t -T plane_t -T player_info_s -T player_info_t diff --git a/nq/source/Makefile.am b/nq/source/Makefile.am index 4e91bb15e..0c49597bd 100644 --- a/nq/source/Makefile.am +++ b/nq/source/Makefile.am @@ -35,7 +35,7 @@ INCLUDES= -I$(top_srcdir)/include -I$(top_srcdir)/nq/include bin_PROGRAMS = @NQ_TARGETS@ -EXTRA_PROGRAMS= nq-3dfx nq-fbdev nq-glx nq-mgl nq-sdl \ +EXTRA_PROGRAMS= nq-3dfx nq-fbdev nq-glx nq-mgl nq-sdl nq-sdl32 \ nq-sgl nq-svga nq-wgl nq-x11 nq-server if ASM_ARCH @@ -93,12 +93,18 @@ nq_mgl_LDADD= ../../libs/video/renderer/.libs/libQFrenderer_sw.a ../../libs/mode nq_mgl_LDFLAGS= $(common_ldflags) nq_mgl_DEPENDENCIES=../../libs/video/renderer/.libs/libQFrenderer_sw.a ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFmgl.la $(client_LIB_DEPS) -# ... Sam Lantinga's Simple DirectMedia Layer, version 1.0 and higher +# ... Sam Lantinga's Simple DirectMedia Layer, version 1.2 and higher nq_sdl_SOURCES= $(combined_SOURCES) sys_sdl.c nq_sdl_LDADD= ../../libs/video/renderer/.libs/libQFrenderer_sw.a ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFsdl.la $(client_LIBS) $(SDL_LIBS) -nq_sgl_LDFLAGS= $(common_ldflags) +nq_sdl_LDFLAGS= $(common_ldflags) nq_sdl_DEPENDENCIES=../../libs/video/renderer/.libs/libQFrenderer_sw.a ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFsdl.la $(client_LIB_DEPS) +# ... Sam Lantinga's Simple DirectMedia Layer, version 1.2 and higher +nq_sdl32_SOURCES= $(combined_SOURCES) sys_sdl.c +nq_sdl32_LDADD= ../../libs/video/renderer/.libs/libQFrenderer_sw32.a ../../libs/models/libQFmodels_sw32.la ../../libs/video/targets/libQFsdl32.la $(client_LIBS) $(SDL_LIBS) +nq_sdl32_LDFLAGS= $(common_ldflags) +nq_sdl32_DEPENDENCIES=../../libs/video/renderer/.libs/libQFrenderer_sw32.a ../../libs/models/libQFmodels_sw32.la ../../libs/video/targets/libQFsdl32.la $(client_LIB_DEPS) + # ... Linux SVGAlib nq_svga_SOURCES= $(combined_SOURCES) sys_unix.c nq_svga_LDADD= ../../libs/video/renderer/.libs/libQFrenderer_sw.a ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFsvga.la $(client_LIBS) $(SVGA_LIBS) @@ -126,7 +132,7 @@ nq_glx_LDADD= ../../libs/video/renderer/libQFrenderer_gl.la ../../libs/models/li nq_glx_LDFLAGS= $(common_ldflags) nq_glx_DEPENDENCIES=../../libs/video/renderer/libQFrenderer_gl.la ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFglx.la $(client_LIB_DEPS) -# ... Simple Directmedia Layer, version 1.1 and higher, in GL mode +# ... Simple Directmedia Layer, version 1.2 and higher, in GL mode nq_sgl_SOURCES= $(combined_SOURCES) sys_sdl.c nq_sgl_LDADD= ../../libs/video/renderer/libQFrenderer_gl.la ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFsgl.la $(client_LIBS) $(X_LIBS) $(SDL_LIBS) $(DL_LIBS) nq_sgl_LDFLAGS= $(common_ldflags) diff --git a/nq/source/cl_parse.c b/nq/source/cl_parse.c index 535082ab8..60aeb69d5 100644 --- a/nq/source/cl_parse.c +++ b/nq/source/cl_parse.c @@ -111,7 +111,7 @@ CL_EntityNum (int num) if (num >= MAX_EDICTS) Host_Error ("CL_EntityNum: %i is an invalid number", num); while (cl.num_entities <= num) { - cl_entities[cl.num_entities].colormap = vid.colormap; + cl_entities[cl.num_entities].colormap = vid.colormap8; cl.num_entities++; } } @@ -415,7 +415,7 @@ CL_ParseUpdate (int bits) else i = ent->baseline->colormap; if (!i) - ent->colormap = vid.colormap; + ent->colormap = vid.colormap8; else { if (i > cl.maxclients) Sys_Error ("i >= cl.maxclients"); @@ -625,7 +625,7 @@ CL_ParseStatic (void) // copy it to the current state ent->model = cl.model_precache[ent->baseline->modelindex]; ent->frame = ent->baseline->frame; - ent->colormap = vid.colormap; + ent->colormap = vid.colormap8; ent->skinnum = ent->baseline->skin; ent->effects = ent->baseline->effects; diff --git a/nq/source/cl_tent.c b/nq/source/cl_tent.c index c81cda6d2..1e846ed0c 100644 --- a/nq/source/cl_tent.c +++ b/nq/source/cl_tent.c @@ -137,7 +137,7 @@ CL_Init_Entity (entity_t *ent) { memset (ent, 0, sizeof (*ent)); - ent->colormap = vid.colormap; + ent->colormap = vid.colormap8; ent->glow_size = 0; ent->glow_color = 254; ent->alpha = 1; diff --git a/nq/source/cl_view.c b/nq/source/cl_view.c index d98547f7b..cebe666eb 100644 --- a/nq/source/cl_view.c +++ b/nq/source/cl_view.c @@ -716,7 +716,7 @@ V_CalcRefdef (void) view->model = cl.model_precache[cl.stats[STAT_WEAPON]]; view->frame = cl.stats[STAT_WEAPONFRAME]; - view->colormap = vid.colormap; + view->colormap = vid.colormap8; // LordHavoc: make gun visible view->alpha = 1; view->colormod[0] = view->colormod[1] = view->colormod[2] = 1; diff --git a/nq/source/console.c b/nq/source/console.c index 225cd9999..e253dff6e 100644 --- a/nq/source/console.c +++ b/nq/source/console.c @@ -386,7 +386,7 @@ Con_DrawInput (void) y = con_vislines - 22; for (i = 0; i < con_linewidth; i++) - Draw_Character8 ((i + 1) << 3, con_vislines - 22, text[i]); + Draw_Character ((i + 1) << 3, con_vislines - 22, text[i]); } @@ -421,7 +421,7 @@ Con_DrawNotify (void) scr_copytop = 1; for (x = 0; x < con_linewidth; x++) - Draw_Character8 ((x + 1) << 3, v, text[x]); + Draw_Character ((x + 1) << 3, v, text[x]); v += 8; } @@ -431,10 +431,10 @@ Con_DrawNotify (void) scr_copytop = 1; if (chat_team) { - Draw_String8 (8, v, "say_team:"); + Draw_String (8, v, "say_team:"); skip = 11; } else { - Draw_String8 (8, v, "say:"); + Draw_String (8, v, "say:"); skip = 5; } @@ -443,11 +443,11 @@ Con_DrawNotify (void) s += chat_bufferlen - ((vid.width >> 3) - (skip + 1)); x = 0; while (s[x]) { - Draw_Character8 ((x + skip) << 3, v, s[x]); + Draw_Character ((x + skip) << 3, v, s[x]); x++; } - Draw_Character8 ((x + skip) << 3, v, - 10 + ((int) (realtime * con_cursorspeed) & 1)); + Draw_Character ((x + skip) << 3, v, + 10 + ((int) (realtime * con_cursorspeed) & 1)); v += 8; } @@ -487,7 +487,7 @@ Con_DrawConsole (int lines) if (con->display != con->current) { // draw arrows to show the buffer is backscrolled for (x = 0; x < con_linewidth; x += 4) - Draw_Character8 ((x + 1) << 3, y, '^'); + Draw_Character ((x + 1) << 3, y, '^'); y -= 8; rows--; @@ -503,7 +503,7 @@ Con_DrawConsole (int lines) text = con->text + (row % con_totallines) * con_linewidth; for (x = 0; x < con_linewidth; x++) - Draw_Character8 ((x + 1) << 3, y, text[x]); + Draw_Character ((x + 1) << 3, y, text[x]); } // draw the input prompt, user text, and cursor if desired @@ -554,7 +554,7 @@ Con_DrawDownload (int lines) // draw it y = lines - 22 + 8; for (i = 0; i < strlen (dlbar); i++) - Draw_Character8 ((i + 1) << 3, y, dlbar[i]); + Draw_Character ((i + 1) << 3, y, dlbar[i]); } /* diff --git a/nq/source/sbar.c b/nq/source/sbar.c index 7b326dfeb..c54c61154 100644 --- a/nq/source/sbar.c +++ b/nq/source/sbar.c @@ -216,10 +216,10 @@ void Sbar_DrawCharacter (int x, int y, int num) { if (sbar_centered) - Draw_Character8 (x + ((vid.width - 320) >> 1) + 4, - y + vid.height - SBAR_HEIGHT, num); + Draw_Character (x + ((vid.width - 320) >> 1) + 4, + y + vid.height - SBAR_HEIGHT, num); else - Draw_Character8 (x + 4, y + vid.height - SBAR_HEIGHT, num); + Draw_Character (x + 4, y + vid.height - SBAR_HEIGHT, num); } @@ -232,10 +232,10 @@ void Sbar_DrawString (int x, int y, char *str) { if (sbar_centered) - Draw_String8 (x + ((vid.width - 320) >> 1), - y + vid.height - SBAR_HEIGHT, str); + Draw_String (x + ((vid.width - 320) >> 1), + y + vid.height - SBAR_HEIGHT, str); else - Draw_String8 (x, y + vid.height - SBAR_HEIGHT, str); + Draw_String (x, y + vid.height - SBAR_HEIGHT, str); } @@ -952,15 +952,15 @@ Sbar_DeathmatchOverlay (void) f = s->frags; snprintf (num, sizeof (num), "%3i", f); - Draw_Character8 (x + 8, y, num[0]); - Draw_Character8 (x + 16, y, num[1]); - Draw_Character8 (x + 24, y, num[2]); + Draw_Character (x + 8, y, num[0]); + Draw_Character (x + 16, y, num[1]); + Draw_Character (x + 24, y, num[2]); if (k == cl.viewentity - 1) - Draw_Character8 (x - 8, y, 12); + Draw_Character (x - 8, y, 12); // draw name - Draw_String8 (x + 64, y, s->name); + Draw_String (x + 64, y, s->name); y += 10; } @@ -1027,16 +1027,16 @@ Sbar_MiniDeathmatchOverlay (void) f = s->frags; snprintf (num, sizeof (num), "%3i", f); - Draw_Character8 (x + 8, y, num[0]); - Draw_Character8 (x + 16, y, num[1]); - Draw_Character8 (x + 24, y, num[2]); + Draw_Character (x + 8, y, num[0]); + Draw_Character (x + 16, y, num[1]); + Draw_Character (x + 24, y, num[2]); if (k == cl.viewentity - 1) { - Draw_Character8 (x, y, 16); - Draw_Character8 (x + 32, y, 17); + Draw_Character (x, y, 16); + Draw_Character (x + 32, y, 17); } // draw name - Draw_String8 (x + 48, y, s->name); + Draw_String (x + 48, y, s->name); y += 8; } diff --git a/qw/source/.indent.pro b/qw/source/.indent.pro index b638c4a2d..4e01e695a 100644 --- a/qw/source/.indent.pro +++ b/qw/source/.indent.pro @@ -147,7 +147,6 @@ -T particle_t -T pcx_t -T physent_t --T pixel_t -T plane_t -T player_info_s -T player_info_t diff --git a/qw/source/Makefile.am b/qw/source/Makefile.am index 0f3ad47f7..5d760ed53 100644 --- a/qw/source/Makefile.am +++ b/qw/source/Makefile.am @@ -35,10 +35,9 @@ INCLUDES= -I$(top_srcdir)/include -I$(top_srcdir)/qw/include bin_PROGRAMS= @QW_TARGETS@ GLIDE_LIBS= @GLIDE_LIBS@ -EXTRA_PROGRAMS= qw-client-3dfx qw-client-fbdev \ - qw-client-glx qw-client-mgl qw-client-sdl \ - qw-client-sgl qw-client-svga qw-client-wgl \ - qw-client-x11 qw-server +EXTRA_PROGRAMS= qw-client-3dfx qw-client-fbdev qw-client-glx qw-client-mgl \ + qw-client-sdl qw-client-sdl32 qw-client-sgl qw-client-svga \ + qw-client-wgl qw-client-x11 qw-server if ASM_ARCH ASM = libasm.la @@ -50,9 +49,7 @@ noinst_LTLIBRARIES= libqfnet.la $(ASM) libasm_la_SOURCES = sys_x86.S worlda.S -common_SOURCES= buildnum.c com.c \ - game.c msg_ucmd.c \ - pmove.c pmovetst.c \ +common_SOURCES= buildnum.c com.c game.c msg_ucmd.c pmove.c pmovetst.c \ net_packetlog.c common_ldflags= -export-dynamic @@ -74,10 +71,10 @@ else syssv_SRC= sv_sys_unix.c endif -server_SOURCES= crudefile.c sv_ccmds.c sv_console.c sv_cvar.c \ - sv_ents.c sv_init.c sv_main.c sv_misc.c \ - sv_model.c sv_move.c sv_nchan.c sv_phys.c sv_pr_cmds.c \ - sv_progs.c sv_send.c sv_user.c world.c $(syssv_SRC) +server_SOURCES= crudefile.c sv_ccmds.c sv_console.c sv_cvar.c sv_ents.c \ + sv_init.c sv_main.c sv_misc.c sv_model.c sv_move.c \ + sv_nchan.c sv_phys.c sv_pr_cmds.c sv_progs.c sv_send.c \ + sv_user.c world.c $(syssv_SRC) qf_server_LIBS= $(top_builddir)/libs/models/libQFmodels.la \ $(top_builddir)/libs/gamecode/engine/libQFgamecode.la \ @@ -118,12 +115,18 @@ qw_client_mgl_LDADD= ../../libs/video/renderer/.libs/libQFrenderer_sw.a ../../li qw_client_mgl_LDFLAGS= $(common_ldflags) qw_client_mgl_DEPENDENCIES=../../libs/video/renderer/.libs/libQFrenderer_sw.a ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFmgl.la $(client_LIB_DEPS) -# ... Simple DirectMedia Layer, version 1.0 and higher +# ... Simple DirectMedia Layer, version 1.2 and higher qw_client_sdl_SOURCES= $(common_SOURCES) $(client_SOURCES) cl_sys_sdl.c qw_client_sdl_LDADD= ../../libs/video/renderer/.libs/libQFrenderer_sw.a ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFsdl.la $(client_LIBS) $(SDL_LIBS) qw_client_sdl_LDFLAGS= $(common_ldflags) qw_client_sdl_DEPENDENCIES=../../libs/video/renderer/.libs/libQFrenderer_sw.a ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFsdl.la $(client_LIB_DEPS) +# ... Simple DirectMedia Layer, version 1.2 and higher +qw_client_sdl32_SOURCES= $(common_SOURCES) $(client_SOURCES) cl_sys_sdl.c +qw_client_sdl32_LDADD= ../../libs/video/renderer/.libs/libQFrenderer_sw32.a ../../libs/models/libQFmodels_sw32.la ../../libs/video/targets/libQFsdl32.la $(client_LIBS) $(SDL_LIBS) +qw_client_sdl32_LDFLAGS= $(common_ldflags) +qw_client_sdl32_DEPENDENCIES=../../libs/video/renderer/.libs/libQFrenderer_sw32.a ../../libs/models/libQFmodels_sw32.la ../../libs/video/targets/libQFsdl32.la $(client_LIB_DEPS) + # ... Linux SVGAlib qw_client_svga_SOURCES= $(common_SOURCES) $(client_SOURCES) cl_sys_unix.c qw_client_svga_LDADD= ../../libs/video/renderer/.libs/libQFrenderer_sw.a ../../libs/models/libQFmodels_sw.la ../../libs/video/targets/libQFsvga.la $(client_LIBS) $(SVGA_LIBS) @@ -151,7 +154,7 @@ qw_client_glx_LDADD= ../../libs/video/renderer/libQFrenderer_gl.la ../../libs/mo qw_client_glx_LDFLAGS= $(common_ldflags) qw_client_glx_DEPENDENCIES=../../libs/video/renderer/libQFrenderer_gl.la ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFglx.la $(client_LIB_DEPS) -# ... Simple DirectMedia Layer, version 1.1 and higher, in GL mode +# ... Simple DirectMedia Layer, version 1.2 and higher, in GL mode qw_client_sgl_SOURCES= $(common_SOURCES) $(client_SOURCES) cl_sys_sdl.c qw_client_sgl_LDADD= ../../libs/video/renderer/libQFrenderer_gl.la ../../libs/models/libQFmodels_gl.la ../../libs/video/targets/libQFsgl.la $(client_LIBS) $(SDL_LIBS) $(X_LIBS) $(DL_LIBS) qw_client_sgl_LDFLAGS= $(common_ldflags) diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index eb74f14ce..99eab8dc8 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -36,7 +36,6 @@ # include #endif -#include "compat.h" #include "QF/console.h" #include "QF/cvar.h" #include "QF/msg.h" @@ -49,6 +48,7 @@ #include "cl_parse.h" #include "cl_pred.h" #include "cl_tent.h" +#include "compat.h" #include "d_iface.h" #include "host.h" #include "msg_ucmd.h" @@ -85,7 +85,6 @@ CL_ClearEnts () CL_Init_Entity (&cl_player_ents[i]); } - void CL_NewDlight (int key, vec3_t org, int effects) { @@ -125,12 +124,10 @@ CL_NewDlight (int key, vec3_t org, int effects) dl->radius = radius; } - /* - PACKET ENTITY PARSING / LINKING + PACKET ENTITY PARSING / LINKING */ - /* CL_ParseDelta @@ -153,9 +150,9 @@ CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits) bits |= i; } // count the bits for net profiling -// for (i=0 ; i<16 ; i++) -// if (bits&(1<angles[2] = MSG_ReadAngle (net_message); // LordHavoc: Endy neglected to mark this as being part of the QSG - // version 2 stuff... - // rearranged it and implemented missing effects + // version 2 stuff... rearranged it and implemented missing effects // Ender (QSG - Begin) if (bits & U_ALPHA) to->alpha = MSG_ReadByte (net_message); @@ -238,7 +234,6 @@ CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits) */ } - void FlushEntityPacket (void) { @@ -267,7 +262,6 @@ FlushEntityPacket (void) } } - /* CL_ParsePacketEntities @@ -329,7 +323,8 @@ CL_ParsePacketEntities (qboolean delta) while (oldindex < oldp->num_entities) { // Con_Printf ("copy %i\n", oldp->entities[oldindex].number); if (newindex >= MAX_PACKET_ENTITIES) - Host_EndGame ("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES"); + Host_EndGame ("CL_ParsePacketEntities: newindex == " + "MAX_PACKET_ENTITIES"); newp->entities[newindex] = oldp->entities[oldindex]; newindex++; oldindex++; @@ -337,7 +332,8 @@ CL_ParsePacketEntities (qboolean delta) break; } newnum = word & 511; - oldnum = oldindex >= oldp->num_entities ? 9999 : oldp->entities[oldindex].number; + oldnum = oldindex >= oldp->num_entities ? 9999 : + oldp->entities[oldindex].number; while (newnum > oldnum) { if (full) { @@ -348,11 +344,13 @@ CL_ParsePacketEntities (qboolean delta) // Con_Printf ("copy %i\n", oldnum); // copy one of the old entities over to the new packet unchanged if (newindex >= MAX_PACKET_ENTITIES) - Host_EndGame ("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES"); + Host_EndGame ("CL_ParsePacketEntities: newindex == " + "MAX_PACKET_ENTITIES"); newp->entities[newindex] = oldp->entities[oldindex]; newindex++; oldindex++; - oldnum = oldindex >= oldp->num_entities ? 9999 : oldp->entities[oldindex].number; + oldnum = oldindex >= oldp->num_entities ? 9999 : + oldp->entities[oldindex].number; } if (newnum < oldnum) { // new from baseline @@ -368,8 +366,10 @@ CL_ParsePacketEntities (qboolean delta) } if (newindex >= MAX_PACKET_ENTITIES) - Host_EndGame ("CL_ParsePacketEntities: newindex == MAX_PACKET_ENTITIES"); - CL_ParseDelta (&cl_baselines[newnum], &newp->entities[newindex], word); + Host_EndGame ("CL_ParsePacketEntities: newindex == " + "MAX_PACKET_ENTITIES"); + CL_ParseDelta (&cl_baselines[newnum], &newp->entities[newindex], + word); newindex++; continue; } @@ -386,7 +386,8 @@ CL_ParsePacketEntities (qboolean delta) continue; } // Con_Printf ("delta %i\n", newnum); - CL_ParseDelta (&oldp->entities[oldindex], &newp->entities[newindex], word); + CL_ParseDelta (&oldp->entities[oldindex], + &newp->entities[newindex], word); newindex++; oldindex++; } @@ -395,7 +396,6 @@ CL_ParsePacketEntities (qboolean delta) newp->num_entities = newindex; } - void CL_LinkPacketEntities (void) { @@ -409,7 +409,8 @@ CL_LinkPacketEntities (void) extern int cl_playerindex; extern int cl_h_playerindex, cl_gib1index, cl_gib2index, cl_gib3index; - pack = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK].packet_entities; + pack = &cl.frames[cls.netchan.incoming_sequence & + UPDATE_MASK].packet_entities; for (pnum = 0; pnum < pack->num_entities; pnum++) { s1 = &pack->entities[pnum]; @@ -422,15 +423,15 @@ CL_LinkPacketEntities (void) continue; // Hack hack hack - if (cl_deadbodyfilter->int_val && s1->modelindex == cl_playerindex - && ((i = s1->frame) == 49 || i == 60 || i == 69 || i == 84 - || i == 93 || i == 102)) + if (cl_deadbodyfilter->int_val && s1->modelindex == cl_playerindex && + ((i = s1->frame) == 49 || i == 60 || i == 69 || i == 84 || + i == 93 || i == 102)) continue; if (cl_gibfilter->int_val && - (s1->modelindex == cl_h_playerindex - || s1->modelindex == cl_gib1index || s1->modelindex == cl_gib2index - || s1->modelindex == cl_gib3index)) + (s1->modelindex == cl_h_playerindex || s1->modelindex == + cl_gib1index || s1->modelindex == cl_gib2index || + s1->modelindex == cl_gib3index)) continue; // create a new entity @@ -450,7 +451,7 @@ CL_LinkPacketEntities (void) (*ent)->colormap = cl.players[s1->colormap - 1].translations; (*ent)->scoreboard = &cl.players[s1->colormap - 1]; } else { - (*ent)->colormap = vid.colormap; + (*ent)->colormap = vid.colormap8; (*ent)->scoreboard = NULL; } @@ -470,16 +471,20 @@ CL_LinkPacketEntities (void) // Ender: Extend (Colormod) [QSG - Begin] // N.B: All messy code below is the sole fault of LordHavoc and // his futile attempts to save bandwidth. :) - (*ent)->glow_size = s1->glow_size < 128 ? s1->glow_size * 8.0 : (s1->glow_size - 256) * 8.0; + (*ent)->glow_size = s1->glow_size < 128 ? s1->glow_size * 8.0 : + (s1->glow_size - 256) * 8.0; (*ent)->glow_color = s1->glow_color; (*ent)->alpha = s1->alpha / 255.0; (*ent)->scale = s1->scale / 16.0; if (s1->colormod == 255) { - (*ent)->colormod[0] = (*ent)->colormod[1] = (*ent)->colormod[2] = 1; + (*ent)->colormod[0] = (*ent)->colormod[1] = + (*ent)->colormod[2] = 1; } else { - (*ent)->colormod[0] = (float) ((s1->colormod >> 5) & 7) * (1.0 / 7.0); - (*ent)->colormod[1] = (float) ((s1->colormod >> 2) & 7) * (1.0 / 7.0); + (*ent)->colormod[0] = (float) ((s1->colormod >> 5) & 7) * (1.0 / + 7.0); + (*ent)->colormod[1] = (float) ((s1->colormod >> 2) & 7) * (1.0 / + 7.0); (*ent)->colormod[2] = (float) (s1->colormod & 3) * (1.0 / 3.0); } // Ender: Extend (Colormod) [QSG - End] @@ -541,7 +546,6 @@ CL_LinkPacketEntities (void) } } - /* PROJECTILE PARSING / LINKING */ @@ -557,14 +561,12 @@ int cl_num_projectiles; extern int cl_spikeindex; - void CL_ClearProjectiles (void) { cl_num_projectiles = 0; } - /* CL_ParseProjectiles @@ -597,7 +599,6 @@ CL_ParseProjectiles (void) } } - void CL_LinkProjectiles (void) { @@ -617,7 +618,7 @@ CL_LinkProjectiles (void) (*ent)->model = cl.model_precache[pr->modelindex]; (*ent)->skinnum = 0; (*ent)->frame = 0; - (*ent)->colormap = vid.colormap; + (*ent)->colormap = vid.colormap8; (*ent)->scoreboard = NULL; (*ent)->skin = NULL; // LordHavoc: Endy had neglected to do this as part of the QSG @@ -630,7 +631,6 @@ CL_LinkProjectiles (void) } } - extern int cl_spikeindex, cl_playerindex, cl_flagindex; extern int parsecountmod; extern double parsecounttime; diff --git a/qw/source/cl_ngraph.c b/qw/source/cl_ngraph.c index 3106d5791..a3b1c06c4 100644 --- a/qw/source/cl_ngraph.c +++ b/qw/source/cl_ngraph.c @@ -85,8 +85,8 @@ CL_NetGraph (int swap) y = vid.height - sb_lines - 24 - r_graphheight->int_val + 7; snprintf (st, sizeof (st), "%3i%% packet loss", lost); if (swap) { - Draw_String8 (vid.width - ((strlen (st) * 8) + 8), y, st); + Draw_String (vid.width - ((strlen (st) * 8) + 8), y, st); } else { - Draw_String8 (8, y, st); + Draw_String (8, y, st); } } diff --git a/qw/source/cl_screen.c b/qw/source/cl_screen.c index d255126d1..82ce37dcf 100644 --- a/qw/source/cl_screen.c +++ b/qw/source/cl_screen.c @@ -83,19 +83,19 @@ CL_NetStats (int swap) if (show_ping->int_val) { int ping = cl.players[cl.playernum].ping; ping = bound (0, ping, 999); - Draw_String8 (x, y, va ("%3d ms", ping)); + Draw_String (x, y, va ("%3d ms", ping)); x+= 48; } else if (swap) { x += 56; } if (show_ping->int_val && show_pl->int_val) { - Draw_String8(x, y, "/"); + Draw_String(x, y, "/"); x += 8; } if (show_pl->int_val) { int lost = CL_CalcNet (); lost = bound (0, lost, 999); - Draw_String8 (x, y, va ("%3d pl", lost)); + Draw_String (x, y, va ("%3d pl", lost)); } } diff --git a/qw/source/cl_tent.c b/qw/source/cl_tent.c index cd0c648fa..4c2912404 100644 --- a/qw/source/cl_tent.c +++ b/qw/source/cl_tent.c @@ -141,7 +141,7 @@ CL_Init_Entity (entity_t *ent) { memset (ent, 0, sizeof (*ent)); - ent->colormap = vid.colormap; + ent->colormap = vid.colormap8; ent->glow_size = 0; ent->glow_color = 254; ent->alpha = 1; diff --git a/qw/source/cl_view.c b/qw/source/cl_view.c index a8b81c44d..981405165 100644 --- a/qw/source/cl_view.c +++ b/qw/source/cl_view.c @@ -118,7 +118,6 @@ V_CalcRoll (vec3_t angles, vec3_t velocity) side = value; return side * sign; - } @@ -141,32 +140,29 @@ V_CalcBob (void) if (cycle < cl_bobup->value) cycle = M_PI * cycle / cl_bobup->value; else - cycle = - M_PI + M_PI * (cycle - cl_bobup->value) / (1.0 - cl_bobup->value); + cycle = M_PI + M_PI * (cycle - cl_bobup->value) / + (1.0 - cl_bobup->value); -// bob is proportional to simulated velocity in the xy plane -// (don't count Z, or jumping messes it up) + // bob is proportional to simulated velocity in the xy plane + // (don't count Z, or jumping messes it up) - bob = - sqrt (cl.simvel[0] * cl.simvel[0] + - cl.simvel[1] * cl.simvel[1]) * cl_bob->value; + bob = sqrt (cl.simvel[0] * cl.simvel[0] + cl.simvel[1] * cl.simvel[1]) * + cl_bob->value; bob = bob * 0.3 + bob * 0.7 * sin (cycle); if (bob > 4) bob = 4; else if (bob < -7) bob = -7; return bob; - } - void V_StartPitchDrift (void) { if (cl.laststop == cl.time) { - return; // something else is keeping it from - // drifting + return; // something else is keeping it from drifting } + if (cl.nodrift || !cl.pitchvel) { cl.pitchvel = v_centerspeed->value; cl.nodrift = false; @@ -174,7 +170,6 @@ V_StartPitchDrift (void) } } - void V_StopPitchDrift (void) { @@ -183,7 +178,6 @@ V_StopPitchDrift (void) cl.pitchvel = 0; } - /* V_DriftPitch @@ -210,8 +204,8 @@ V_DriftPitch (void) // don't count small mouse motion if (cl.nodrift) { if (fabs - (cl.frames[(cls.netchan.outgoing_sequence - 1) & UPDATE_MASK].cmd. - forwardmove) < 200) + (cl.frames[(cls.netchan.outgoing_sequence - 1) & + UPDATE_MASK].cmd.forwardmove) < 200) cl.driftmove = 0; else cl.driftmove += host_frametime; @@ -249,12 +243,10 @@ V_DriftPitch (void) } } - /* PALETTE FLASHES */ - void V_ParseDamage (void) { @@ -277,10 +269,12 @@ V_ParseDamage (void) cl.faceanimtime = cl.time + 0.2; // but sbar face into pain frame if (cl_cshift_damage->int_val - || (atoi (Info_ValueForKey (cl.serverinfo, "cshifts")) & INFO_CSHIFT_DAMAGE)) { + || (atoi (Info_ValueForKey (cl.serverinfo, "cshifts")) & + INFO_CSHIFT_DAMAGE)) { cl.cshifts[CSHIFT_DAMAGE].percent += 3 * count; - cl.cshifts[CSHIFT_DAMAGE].percent = bound (0, cl.cshifts[CSHIFT_DAMAGE].percent, 150); + cl.cshifts[CSHIFT_DAMAGE].percent = + bound (0, cl.cshifts[CSHIFT_DAMAGE].percent, 150); if (armor > blood) { cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 200; @@ -298,7 +292,6 @@ V_ParseDamage (void) } // calculate view angle kicks - VectorSubtract (from, cl.simorg, from); VectorNormalize (from); @@ -313,7 +306,6 @@ V_ParseDamage (void) v_dmg_time = v_kicktime->value; } - void V_cshift_f (void) { @@ -323,7 +315,6 @@ V_cshift_f (void) cshift_empty.percent = atoi (Cmd_Argv (4)); } - /* V_BonusFlash_f @@ -333,7 +324,8 @@ void V_BonusFlash_f (void) { if (!cl_cshift_bonus->int_val - && !(atoi (Info_ValueForKey (cl.serverinfo, "cshifts")) & INFO_CSHIFT_BONUS)) + && !(atoi (Info_ValueForKey (cl.serverinfo, "cshifts")) & + INFO_CSHIFT_BONUS)) return; cl.cshifts[CSHIFT_BONUS].destcolor[0] = 215; @@ -342,7 +334,6 @@ V_BonusFlash_f (void) cl.cshifts[CSHIFT_BONUS].percent = 50; } - /* V_SetContentsColor @@ -374,7 +365,6 @@ V_SetContentsColor (int contents) } } - void V_CalcPowerupCshift (void) { @@ -416,7 +406,6 @@ V_CalcPowerupCshift (void) } } - /* V_CalcBlend @@ -459,7 +448,6 @@ V_CalcBlend (void) v_blend[3] = bound (0.0, a, 1.0); } - void V_PrepBlend (void) { @@ -501,12 +489,10 @@ V_PrepBlend (void) V_CalcBlend(); } - /* VIEW RENDERING */ - float angledelta (float a) { @@ -516,13 +502,12 @@ angledelta (float a) return a; } - void CalcGunAngle (void) { - float yaw, pitch, move; - static float oldyaw = 0; - static float oldpitch = 0; + float yaw, pitch, move; + static float oldyaw = 0; + static float oldpitch = 0; yaw = r_refdef.viewangles[YAW]; pitch = -r_refdef.viewangles[PITCH]; @@ -556,12 +541,11 @@ CalcGunAngle (void) cl.viewent.angles[PITCH] = -(r_refdef.viewangles[PITCH] + pitch); } - void V_BoundOffsets (void) { -// absolutely bound refresh reletive to entity clipping hull -// so the view can never be inside a solid wall + // absolutely bound refresh reletive to entity clipping hull + // so the view can never be inside a solid wall if (r_refdef.vieworg[0] < cl.simorg[0] - 14) r_refdef.vieworg[0] = cl.simorg[0] - 14; @@ -577,7 +561,6 @@ V_BoundOffsets (void) r_refdef.vieworg[2] = cl.simorg[2] + 30; } - /* V_AddIdle @@ -586,28 +569,21 @@ V_BoundOffsets (void) void V_AddIdle (void) { - r_refdef.viewangles[ROLL] += - v_idlescale->value * sin (cl.time * v_iroll_cycle->value) * - v_iroll_level->value; - r_refdef.viewangles[PITCH] += - v_idlescale->value * sin (cl.time * v_ipitch_cycle->value) * - v_ipitch_level->value; - r_refdef.viewangles[YAW] += - v_idlescale->value * sin (cl.time * v_iyaw_cycle->value) * - v_iyaw_level->value; + r_refdef.viewangles[ROLL] += v_idlescale->value * + sin (cl.time * v_iroll_cycle->value) * v_iroll_level->value; + r_refdef.viewangles[PITCH] += v_idlescale->value * + sin (cl.time * v_ipitch_cycle->value) * v_ipitch_level->value; + r_refdef.viewangles[YAW] += v_idlescale->value * + sin (cl.time * v_iyaw_cycle->value) * v_iyaw_level->value; - cl.viewent.angles[ROLL] -= - v_idlescale->value * sin (cl.time * v_iroll_cycle->value) * - v_iroll_level->value; - cl.viewent.angles[PITCH] -= - v_idlescale->value * sin (cl.time * v_ipitch_cycle->value) * - v_ipitch_level->value; - cl.viewent.angles[YAW] -= - v_idlescale->value * sin (cl.time * v_iyaw_cycle->value) * - v_iyaw_level->value; + cl.viewent.angles[ROLL] -= v_idlescale->value * + sin (cl.time * v_iroll_cycle->value) * v_iroll_level->value; + cl.viewent.angles[PITCH] -= v_idlescale->value * + sin (cl.time * v_ipitch_cycle->value) * v_ipitch_level->value; + cl.viewent.angles[YAW] -= v_idlescale->value * + sin (cl.time * v_iyaw_cycle->value) * v_iyaw_level->value; } - /* V_CalcViewRoll @@ -631,7 +607,6 @@ V_CalcViewRoll (void) } - void V_CalcIntermissionRefdef (void) { @@ -652,16 +627,15 @@ V_CalcIntermissionRefdef (void) Cvar_SetValue (v_idlescale, old); } - void V_CalcRefdef (void) { entity_t *view; - int i; - vec3_t forward, right, up; - float bob; + int i; + vec3_t forward, right, up; + float bob; static float oldz = 0; - int zofs = 22; + int zofs = 22; if (cl.stdver) zofs = cl.stats[STAT_VIEWHEIGHT]; @@ -678,9 +652,9 @@ V_CalcRefdef (void) r_refdef.vieworg[2] += bob; -// never let it sit exactly on a node line, because a water plane can -// dissapear when viewed with the eye exactly on it. -// the server protocol only specifies to 1/8 pixel, so add 1/16 in each axis + // never let it sit exactly on a node line, because a water plane can + // disappear when viewed with the eye exactly on it. + // server protocol only specifies to 1/8 pixel, so add 1/16 in each axis r_refdef.vieworg[0] += 1.0 / 16; r_refdef.vieworg[1] += 1.0 / 16; r_refdef.vieworg[2] += 1.0 / 16; @@ -712,13 +686,13 @@ V_CalcRefdef (void) for (i = 0; i < 3; i++) { view->origin[i] += forward[i] * bob * 0.4; -// view->origin[i] += right[i]*bob*0.4; -// view->origin[i] += up[i]*bob*0.8; +// view->origin[i] += right[i] * bob *0.4; +// view->origin[i] += up[i] * bob * 0.8; } view->origin[2] += bob; -// fudge position around to keep amount of weapon visible -// roughly equal with different FOV + // fudge position around to keep amount of weapon visible + // roughly equal with different FOV if (cl_sbar->int_val == 0 && scr_viewsize->int_val >= 100) ; else if (scr_viewsize->int_val == 110) @@ -735,7 +709,7 @@ V_CalcRefdef (void) else view->model = cl.model_precache[cl.stats[STAT_WEAPON]]; view->frame = view_message->weaponframe; - view->colormap = vid.colormap; + view->colormap = vid.colormap8; // LordHavoc: make gun visible view->alpha = 1; view->colormod[0] = view->colormod[1] = view->colormod[2] = 1; @@ -760,7 +734,6 @@ V_CalcRefdef (void) oldz = cl.simorg[2]; } - void DropPunchAngle (void) { @@ -769,7 +742,6 @@ DropPunchAngle (void) cl.punchangle = 0; } - /* V_RenderView @@ -803,54 +775,63 @@ V_RenderView (void) void V_Init (void) { - Cmd_AddCommand ("v_cshift", V_cshift_f, "This adjusts all of the colors currently being displayed.\n" - "Used when you are underwater, hit, have the Ring of Shadows, or Quad Damage. (v_cshift r g b intensity)"); - - Cmd_AddCommand ("bf", V_BonusFlash_f, "Background flash, used when you pick up an item"); - Cmd_AddCommand ("centerview", V_StartPitchDrift, "Centers the player's view ahead after +lookup or +lookdown \n" - "Will not work while mlook is active or freelook is 1."); + Cmd_AddCommand ("v_cshift", V_cshift_f, "This adjusts all of the colors " + "currently being displayed.\n" + "Used when you are underwater, hit, have the Ring of " + "Shadows, or Quad Damage. (v_cshift r g b intensity)"); + Cmd_AddCommand ("bf", V_BonusFlash_f, "Background flash, used when you " + "pick up an item"); + Cmd_AddCommand ("centerview", V_StartPitchDrift, "Centers the player's " + "view ahead after +lookup or +lookdown \n" + "Will not work while mlook is active or freelook is 1."); } void V_Init_Cvars (void) { v_centermove = Cvar_Get ("v_centermove", "0.15", CVAR_NONE, NULL, - "How far the player must move forward before the view re-centers"); + "How far the player must move forward before the " + "view re-centers"); v_centerspeed = Cvar_Get ("v_centerspeed", "500", CVAR_NONE, NULL, - "How quickly you return to a center view after a lookup or lookdown"); - + "How quickly you return to a center view after " + "a lookup or lookdown"); v_iyaw_cycle = Cvar_Get ("v_iyaw_cycle", "2", CVAR_NONE, NULL, - "How far you tilt right and left when v_idlescale is enabled"); + "How far you tilt right and left when " + "v_idlescale is enabled"); v_iroll_cycle = Cvar_Get ("v_iroll_cycle", "0.5", CVAR_NONE, NULL, - "How quickly you tilt right and left when v_idlescale is enabled"); + "How quickly you tilt right and left when " + "v_idlescale is enabled"); v_ipitch_cycle = Cvar_Get ("v_ipitch_cycle", "1", CVAR_NONE, NULL, - "How quickly you lean forwards and backwards when v_idlescale is enabled"); + "How quickly you lean forwards and backwards " + "when v_idlescale is enabled"); v_iyaw_level = Cvar_Get ("v_iyaw_level", "0.3", CVAR_NONE, NULL, - "How far you tilt right and left when v_idlescale is enabled"); + "How far you tilt right and left when " + "v_idlescale is enabled"); v_iroll_level = Cvar_Get ("v_iroll_level", "0.1", CVAR_NONE, NULL, - "How far you tilt right and left when v_idlescale is enabled"); + "How far you tilt right and left when " + "v_idlescale is enabled"); v_ipitch_level = Cvar_Get ("v_ipitch_level", "0.3", CVAR_NONE, NULL, - "How far you lean forwards and backwards when v_idlescale is enabled"); - + "How far you lean forwards and backwards when " + "v_idlescale is enabled"); v_idlescale = Cvar_Get ("v_idlescale", "0", CVAR_NONE, NULL, - "Toggles whether the view remains idle"); + "Toggles whether the view remains idle"); cl_rollspeed = Cvar_Get ("cl_rollspeed", "200", CVAR_NONE, NULL, - "How quickly you straighten out after strafing"); + "How quickly you straighten out after strafing"); cl_rollangle = Cvar_Get ("cl_rollangle", "2.0", CVAR_NONE, NULL, - "How much your screen tilts when strafing"); - + "How much your screen tilts when strafing"); cl_bob = Cvar_Get ("cl_bob", "0.02", CVAR_NONE, NULL, - "How much your weapon moves up and down when walking"); + "How much your weapon moves up and down when walking"); cl_bobcycle = Cvar_Get ("cl_bobcycle", "0.6", CVAR_NONE, NULL, - "How quickly your weapon moves up and down when walking"); + "How quickly your weapon moves up and down when " + "walking"); cl_bobup = Cvar_Get ("cl_bobup", "0.5", CVAR_NONE, NULL, - "How long your weapon stays up before cycling when walking"); - + "How long your weapon stays up before cycling when " + "walking"); v_kicktime = Cvar_Get ("v_kicktime", "0.5", CVAR_NONE, NULL, - "How long the kick from an attack lasts"); + "How long the kick from an attack lasts"); v_kickroll = Cvar_Get ("v_kickroll", "0.6", CVAR_NONE, NULL, - "How much you lean when hit"); + "How much you lean when hit"); v_kickpitch = Cvar_Get ("v_kickpitch", "0.6", CVAR_NONE, NULL, - "How much you look up when hit"); + "How much you look up when hit"); } diff --git a/qw/source/console.c b/qw/source/console.c index 3a2e24e5e..10b511b0e 100644 --- a/qw/source/console.c +++ b/qw/source/console.c @@ -390,7 +390,7 @@ Con_DrawInput (void) y = con_vislines - 22; for (i = 0; i < con_linewidth; i++) - Draw_Character8 ((i + 1) << 3, con_vislines - 22, text[i]); + Draw_Character ((i + 1) << 3, con_vislines - 22, text[i]); } @@ -425,7 +425,7 @@ Con_DrawNotify (void) scr_copytop = 1; for (x = 0; x < con_linewidth; x++) - Draw_Character8 ((x + 1) << 3, v, text[x]); + Draw_Character ((x + 1) << 3, v, text[x]); v += 8; } @@ -435,10 +435,10 @@ Con_DrawNotify (void) scr_copytop = 1; if (chat_team) { - Draw_String8 (8, v, "say_team:"); + Draw_String (8, v, "say_team:"); skip = 11; } else { - Draw_String8 (8, v, "say:"); + Draw_String (8, v, "say:"); skip = 5; } @@ -447,10 +447,10 @@ Con_DrawNotify (void) s += chat_bufferlen - ((vid.width >> 3) - (skip + 1)); x = 0; while (s[x]) { - Draw_Character8 ((x + skip) << 3, v, s[x]); + Draw_Character ((x + skip) << 3, v, s[x]); x++; } - Draw_Character8 ((x + skip) << 3, v, + Draw_Character ((x + skip) << 3, v, 10 + ((int) (realtime * con_cursorspeed) & 1)); v += 8; } @@ -491,7 +491,7 @@ Con_DrawConsole (int lines) if (con->display != con->current) { // draw arrows to show the buffer is backscrolled for (x = 0; x < con_linewidth; x += 4) - Draw_Character8 ((x + 1) << 3, y, '^'); + Draw_Character ((x + 1) << 3, y, '^'); y -= 8; rows--; @@ -507,7 +507,7 @@ Con_DrawConsole (int lines) text = con->text + (row % con_totallines) * con_linewidth; for (x = 0; x < con_linewidth; x++) - Draw_Character8 ((x + 1) << 3, y, text[x]); + Draw_Character ((x + 1) << 3, y, text[x]); } // draw the input prompt, user text, and cursor if desired @@ -558,7 +558,7 @@ Con_DrawDownload (int lines) // draw it y = lines - 22 + 8; for (i = 0; i < strlen (dlbar); i++) - Draw_Character8 ((i + 1) << 3, y, dlbar[i]); + Draw_Character ((i + 1) << 3, y, dlbar[i]); } /* diff --git a/qw/source/sbar.c b/qw/source/sbar.c index 08935100e..16f932304 100644 --- a/qw/source/sbar.c +++ b/qw/source/sbar.c @@ -288,14 +288,14 @@ Sbar_DrawTransPic (int x, int y, qpic_t *pic) void Sbar_DrawCharacter (int x, int y, int num) { - Draw_Character8 (x + 4, y + vid.height - SBAR_HEIGHT, num); + Draw_Character (x + 4, y + vid.height - SBAR_HEIGHT, num); } void Sbar_DrawString (int x, int y, char *str) { - Draw_String8 (x, y + vid.height - SBAR_HEIGHT, str); + Draw_String (x, y + vid.height - SBAR_HEIGHT, str); } @@ -853,12 +853,12 @@ Sbar_TeamOverlay (void) y = 24; x = 36; - Draw_String8 (x, y, "low/avg/high team total players"); + Draw_String (x, y, "low/avg/high team total players"); y += 8; -// Draw_String8 (x, y, "------------ ---- ----- -------"); - Draw_String8 (x, y, "\x1d\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1f " - "\x1d\x1e\x1e\x1f \x1d\x1e\x1e\x1e\x1f " - "\x1d\x1e\x1e\x1e\x1e\x1e\x1f"); +// Draw_String (x, y, "------------ ---- ----- -------"); + Draw_String (x, y, "\x1d\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1f " + "\x1d\x1e\x1e\x1f \x1d\x1e\x1e\x1e\x1f " + "\x1d\x1e\x1e\x1e\x1e\x1e\x1f"); y += 8; // sort the teams @@ -886,25 +886,25 @@ Sbar_TeamOverlay (void) pavg = 999; snprintf (num, sizeof (num), "%3i/%3i/%3i", plow, pavg, phigh); - Draw_String8 (x, y, num); + Draw_String (x, y, num); // draw team team[4] = 0; strncpy (team, tm->team, 4); - Draw_String8 (x + 104, y, team); + Draw_String (x + 104, y, team); // draw total snprintf (num, sizeof (num), "%5i", tm->frags); - Draw_String8 (x + 104 + 40, y, num); + Draw_String (x + 104 + 40, y, num); // draw players snprintf (num, sizeof (num), "%5i", tm->players); - Draw_String8 (x + 104 + 88, y, num); + Draw_String (x + 104 + 88, y, num); if (!strncmp (Info_ValueForKey (cl.players[cl.playernum].userinfo, "team"), tm->team, 16)) { - Draw_Character8 (x + 104 - 8, y, 16); - Draw_Character8 (x + 104 + 32, y, 17); + Draw_Character (x + 104 - 8, y, 16); + Draw_Character (x + 104 + 32, y, 17); } y += 8; @@ -968,27 +968,27 @@ Sbar_DeathmatchOverlay (int start) x = 4; // 0 40 64 104 152 192 if (cl_showscoresuid->int_val == 0) - Draw_String8 (x, y, "ping pl time frags team name"); + Draw_String (x, y, "ping pl time frags team name"); else - Draw_String8 (x, y, " uid pl time frags team name"); + Draw_String (x, y, " uid pl time frags team name"); y += 8; -// Draw_String8 ( x , y, "---- -- ---- ----- ---- ----------------"); - Draw_String8 (x, y, "\x1d\x1e\x1e\x1f \x1d\x1f \x1d\x1e\x1e\x1f " - "\x1d\x1e\x1e\x1e\x1f \x1d\x1e\x1e\x1f \x1d\x1e\x1e" - "\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1f"); +// Draw_String ( x , y, "---- -- ---- ----- ---- ----------------"); + Draw_String (x, y, "\x1d\x1e\x1e\x1f \x1d\x1f \x1d\x1e\x1e\x1f " + "\x1d\x1e\x1e\x1e\x1f \x1d\x1e\x1e\x1f \x1d\x1e\x1e" + "\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1f"); y += 8; } else { x = 16; // 0 40 64 104 152 if (cl_showscoresuid->int_val == 0) - Draw_String8 (x, y, "ping pl time frags name"); + Draw_String (x, y, "ping pl time frags name"); else - Draw_String8 (x, y, " uid pl time frags name"); + Draw_String (x, y, " uid pl time frags name"); y += 8; -// Draw_String8 ( x , y, "---- -- ---- ----- ----------------"); - Draw_String8 (x, y, "\x1d\x1e\x1e\x1f \x1d\x1f \x1d\x1e\x1e\x1f " - "\x1d\x1e\x1e\x1e\x1f \x1d\x1e\x1e\x1e\x1e\x1e\x1e" - "\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1f"); +// Draw_String ( x , y, "---- -- ---- ----- ----------------"); + Draw_String (x, y, "\x1d\x1e\x1e\x1f \x1d\x1f \x1d\x1e\x1e\x1f " + "\x1d\x1e\x1e\x1e\x1f \x1d\x1e\x1e\x1e\x1e\x1e\x1e" + "\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1f"); y += 8; } @@ -1007,23 +1007,23 @@ Sbar_DeathmatchOverlay (int start) p = s->userid; } snprintf (num, sizeof (num), "%4i", p); - Draw_String8 (x, y, num); + Draw_String (x, y, num); // draw pl p = s->pl; snprintf (num, sizeof (num), "%3i", p); if (p > 25) - Draw_AltString8 (x + 32, y, num); + Draw_AltString (x + 32, y, num); else - Draw_String8 (x + 32, y, num); + Draw_String (x + 32, y, num); if (s->spectator) { - Draw_String8 (x + 40, y, "(spectator)"); + Draw_String (x + 40, y, "(spectator)"); // draw name if (teamplay) - Draw_String8 (x + 152 + 40, y, s->name); + Draw_String (x + 152 + 40, y, s->name); else - Draw_String8 (x + 152, y, s->name); + Draw_String (x + 152, y, s->name); y += skip; continue; } @@ -1035,7 +1035,7 @@ Sbar_DeathmatchOverlay (int start) total = realtime - s->entertime; minutes = (int) total / 60; snprintf (num, sizeof (num), "%4i", minutes); - Draw_String8 (x + 64, y, num); + Draw_String (x + 64, y, num); // draw background top = s->topcolor; @@ -1053,25 +1053,25 @@ Sbar_DeathmatchOverlay (int start) f = s->frags; snprintf (num, sizeof (num), "%3i", f); - Draw_Character8 (x + 112, y, num[0]); - Draw_Character8 (x + 120, y, num[1]); - Draw_Character8 (x + 128, y, num[2]); + Draw_Character (x + 112, y, num[0]); + Draw_Character (x + 120, y, num[1]); + Draw_Character (x + 128, y, num[2]); if (k == cl.playernum) { - Draw_Character8 (x + 104, y, 16); - Draw_Character8 (x + 136, y, 17); + Draw_Character (x + 104, y, 16); + Draw_Character (x + 136, y, 17); } // team if (teamplay) { team[4] = 0; strncpy (team, Info_ValueForKey (s->userinfo, "team"), 4); - Draw_String8 (x + 152, y, team); + Draw_String (x + 152, y, team); } // draw name if (teamplay) - Draw_String8 (x + 152 + 40, y, s->name); + Draw_String (x + 152 + 40, y, s->name); else - Draw_String8 (x + 152, y, s->name); + Draw_String (x + 152, y, s->name); y += skip; } @@ -1161,27 +1161,27 @@ Sbar_MiniDeathmatchOverlay (void) f = s->frags; snprintf (num, sizeof (num), "%3i", f); - Draw_Character8 (x + 8, y, num[0]); - Draw_Character8 (x + 16, y, num[1]); - Draw_Character8 (x + 24, y, num[2]); + Draw_Character (x + 8, y, num[0]); + Draw_Character (x + 16, y, num[1]); + Draw_Character (x + 24, y, num[2]); if (k == cl.playernum) { - Draw_Character8 (x, y, 16); - Draw_Character8 (x + 32, y, 17); + Draw_Character (x, y, 16); + Draw_Character (x + 32, y, 17); } // team if (teamplay) { team[4] = 0; strncpy (team, Info_ValueForKey (s->userinfo, "team"), 4); - Draw_String8 (x + 48, y, team); + Draw_String (x + 48, y, team); } // draw name name[16] = 0; strncpy (name, s->name, 16); if (teamplay) - Draw_String8 (x + 48 + 40, y, name); + Draw_String (x + 48 + 40, y, name); else - Draw_String8 (x + 48, y, name); + Draw_String (x + 48, y, name); y += 8; } @@ -1193,7 +1193,7 @@ Sbar_MiniDeathmatchOverlay (void) x += 208; if (cl_sbar_separator->int_val) for (y = vid.height - sb_lines; y < vid.height - 6; y += 2) - Draw_Character8 (x, y, 14); + Draw_Character (x, y, 14); x += 16; @@ -1205,16 +1205,16 @@ Sbar_MiniDeathmatchOverlay (void) // draw pings team[4] = 0; strncpy (team, tm->team, 4); - Draw_String8 (x, y, team); + Draw_String (x, y, team); // draw total snprintf (num, sizeof (num), "%5i", tm->frags); - Draw_String8 (x + 40, y, num); + Draw_String (x + 40, y, num); if (!strncmp (Info_ValueForKey (cl.players[cl.playernum].userinfo, "team"), tm->team, 16)) { - Draw_Character8 (x - 8, y, 16); - Draw_Character8 (x + 32, y, 17); + Draw_Character (x - 8, y, 16); + Draw_Character (x + 32, y, 17); } y += 8;