diff --git a/src/d_main.c b/src/d_main.c index 4cb0dfe..21ecef9 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -115,9 +115,6 @@ boolean storedemo; // If true, the main game loop has started. boolean main_loop_started = false; -// Josef: CPU traces walls while IPU does automap -boolean livewallupdates = false; - char wadfile[1024]; // primary wad file char mapdir[1024]; // directory of development maps @@ -209,10 +206,10 @@ void D_Display(void) { if (!gametic) break; - /* JOSEF: IPU draws automap now - if (automapactive) - AM_Drawer(); - */ + // if (automapactive) + // AM_Drawer(); + IPU_AM_Drawer(); // JOSEF + if (wipe || (viewheight != SCREENHEIGHT && fullscreen)) redrawsbar = true; @@ -235,11 +232,9 @@ void D_Display(void) { I_UpdateNoBlit(); // draw the view directly - int busy_with_automap = automapactive && !livewallupdates; // JOSEF - if (gamestate == GS_LEVEL && !busy_with_automap && gametic) + if (gamestate == GS_LEVEL && !automapactive && gametic) R_RenderPlayerView(&players[displayplayer]); - IPU_AM_Drawer(); // JOSEF: After RenderplayerView for wall updates if (gamestate == GS_LEVEL && gametic) HU_Drawer(); @@ -831,10 +826,6 @@ void D_DoomMain(void) { printf("Z_Init: Init zone memory allocation daemon. \n"); Z_Init(); - // JOSEF: flag to enable CPU wall mapping while in automap - if (M_CheckParm("-livewallupdates")) - livewallupdates = true; - //! // @category net // diff --git a/src/ipu/ipu_malloc.c b/src/ipu/ipu_malloc.c index 5d1ed48..ca10853 100644 --- a/src/ipu/ipu_malloc.c +++ b/src/ipu/ipu_malloc.c @@ -1,10 +1,9 @@ #include -// #include "ipu_malloc.h" -#include "ipu_print.h" +#include "ipu_malloc.h" +#include "print.h" - -#define IPUMALLOC_MAXMAPSIZE 150000 +#define IPUMALLOC_MAXMAPSIZE 250000 #define ALIGN32(x) (((x) + 3) & (~3)) @@ -12,16 +11,18 @@ static unsigned char PU_LEVEL_pool[IPUMALLOC_MAXMAPSIZE]; static int PU_LEVEL_size = 0; -void* IPU_level_malloc(int size) { +void* IPU_level_malloc(int size, const char* name) { void* ret = (void*)(&PU_LEVEL_pool[PU_LEVEL_size]); PU_LEVEL_size = ALIGN32(PU_LEVEL_size + size); + if (0) { // Enable for debug + printf("LEVEL_ALLOC: %s = %dK, total = %dK\n", + name, size / 1000, PU_LEVEL_size / 1000); + } + if (PU_LEVEL_size > IPUMALLOC_MAXMAPSIZE) { - ipuprint("ERROR: IPUMALLOC_MAXMAPSIZE is "); - ipuprintnum(IPUMALLOC_MAXMAPSIZE); - ipuprint(", but IPU_level_malloc wants "); - ipuprintnum(PU_LEVEL_size); - ipuprint("\n"); + printf("ERROR: IPUMALLOC_MAXMAPSIZE is %d, but IPU_level_malloc wants %d\n", + IPUMALLOC_MAXMAPSIZE, PU_LEVEL_size); // exit(1701); } return ret; diff --git a/src/ipu/ipu_malloc.h b/src/ipu/ipu_malloc.h index 211ce8a..df7c809 100644 --- a/src/ipu/ipu_malloc.h +++ b/src/ipu/ipu_malloc.h @@ -4,7 +4,7 @@ extern "C" { #endif -void* IPU_level_malloc(int size); +void* IPU_level_malloc(int size, const char* name); void IPU_level_free(void); diff --git a/src/ipu/p_mobj.c b/src/ipu/p_mobj.c index f3a8e07..dd92fc8 100644 --- a/src/ipu/p_mobj.c +++ b/src/ipu/p_mobj.c @@ -453,7 +453,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) { state_t *st; mobjinfo_t *info; - mobj = IPU_level_malloc(sizeof(*mobj)); + mobj = IPU_level_malloc(sizeof(*mobj), "SpawnMobj"); memset(mobj, 0, sizeof(*mobj)); // JOSEF: Just allocate the mem for now diff --git a/src/ipu/p_setup.c b/src/ipu/p_setup.c index 4e7724c..645adb8 100644 --- a/src/ipu/p_setup.c +++ b/src/ipu/p_setup.c @@ -1,5 +1,6 @@ #include "d_mode.h" +#include "doomdata.h" #include "doomstat.h" #include "i_swap.h" #include "m_bbox.h" @@ -92,7 +93,7 @@ void P_LoadVertexes(const unsigned char *buf) { numvertexes = lumplen / sizeof(mapvertex_t); // Allocate zone memory for buffer. - vertexes = IPU_level_malloc(numvertexes * sizeof(vertex_t)); + vertexes = IPU_level_malloc(numvertexes * sizeof(vertex_t), "P_LoadVertexes"); // Load data into cache. // JOSEF: data = W_CacheLumpNum(lump, PU_STATIC); @@ -108,6 +109,90 @@ void P_LoadVertexes(const unsigned char *buf) { } } +/* JOSEF: Don't think we need this? +// +// GetSectorAtNullAddress +// +sector_t *GetSectorAtNullAddress(void) { + static boolean null_sector_is_initialized = false; + static sector_t null_sector; + + if (!null_sector_is_initialized) { + memset(&null_sector, 0, sizeof(null_sector)); + I_GetMemoryValue(0, &null_sector.floorheight, 4); + I_GetMemoryValue(4, &null_sector.ceilingheight, 4); + null_sector_is_initialized = true; + } + + return &null_sector; +} +*/ + +// +// P_LoadSegs +// +void P_LoadSegs(const unsigned char *buf) { + byte *data; + int i; + mapseg_t *ml; + seg_t *li; + line_t *ldef; + int linedef; + int side; + int sidenum; + + int lumplen = ((int*)buf)[0]; + numsegs = lumplen / sizeof(mapseg_t); + segs = IPU_level_malloc(numsegs * sizeof(seg_t), "P_LoadSegs"); + memset(segs, 0, numsegs * sizeof(seg_t)); + + ml = (mapseg_t *)(&buf[sizeof(int)]); + li = segs; + for (i = 0; i < numsegs; i++, li++, ml++) { + li->v1 = &vertexes[SHORT(ml->v1)]; + li->v2 = &vertexes[SHORT(ml->v2)]; + + li->angle = (SHORT(ml->angle)) << FRACBITS; + li->offset = (SHORT(ml->offset)) << FRACBITS; + linedef = SHORT(ml->linedef); + ldef = &lines[linedef]; + li->linedef = ldef; + side = SHORT(ml->side); + + // e6y: check for wrong indexes + if ((unsigned)ldef->sidenum[side] >= (unsigned)numsides) { + // I_Error("P_LoadSegs: linedef %d for seg %d references a non-existent " + // "sidedef %d", + // linedef, i, (unsigned)ldef->sidenum[side]); + printf("ERROR: P_LoadSegs: linedef %d for seg %d references a non-existent " + "sidedef %d\n", + linedef, i, (unsigned)ldef->sidenum[side]); + } + + li->sidedef = &sides[ldef->sidenum[side]]; + li->frontsector = sides[ldef->sidenum[side]].sector; + + if (ldef->flags & ML_TWOSIDED) { + sidenum = ldef->sidenum[side ^ 1]; + + // If the sidenum is out of range, this may be a "glass hack" + // impassible window. Point at side #0 (this may not be + // the correct Vanilla behavior; however, it seems to work for + // OTTAWAU.WAD, which is the one place I've seen this trick + // used). + + if (sidenum < 0 || sidenum >= numsides) { + // li->backsector = GetSectorAtNullAddress(); // JOSEF: Don't support this? + printf("ERROR: GLASS HACK UNSUPPORTED\n"); // JOSEF + } else { + li->backsector = sides[sidenum].sector; + } + } else { + li->backsector = 0; + } + } +} + // // P_LoadSectors // @@ -119,7 +204,7 @@ void P_LoadSectors(const unsigned char *buf) { int lumplen = ((int*)buf)[0]; numsectors = lumplen / sizeof(mapsector_t); - sectors = IPU_level_malloc(numsectors * sizeof(sector_t)); + sectors = IPU_level_malloc(numsectors * sizeof(sector_t), "P_LoadSectors"); memset(sectors, 0, numsectors * sizeof(sector_t)); ms = (mapsector_t *)(&buf[sizeof(int)]); @@ -150,7 +235,7 @@ void P_LoadNodes(const unsigned char *buf) { int lumplen = ((int*)buf)[0]; numnodes = lumplen / sizeof(mapnode_t); - nodes = IPU_level_malloc(numnodes * sizeof(node_t)); + nodes = IPU_level_malloc(numnodes * sizeof(node_t), "P_LoadNodes"); memset(nodes, 0, numnodes * sizeof(node_t)); mn = (mapnode_t *)(&buf[sizeof(int)]); @@ -232,7 +317,7 @@ void P_LoadSideDefs(const unsigned char *buf) { int lumplen = ((int*)buf)[0]; numsides = lumplen / sizeof(mapsidedef_t); - sides = IPU_level_malloc(numsides * sizeof(side_t)); + sides = IPU_level_malloc(numsides * sizeof(side_t), "P_LoadSideDefs"); memset(sides, 0, numsides * sizeof(side_t)); msd = (mapsidedef_t *)(&buf[sizeof(int)]); @@ -263,7 +348,7 @@ void P_LoadLineDefs(const unsigned char *buf) { int lumplen = ((int*)buf)[0]; numlines = lumplen / sizeof(maplinedef_t); - lines = IPU_level_malloc(numlines * sizeof(line_t)); + lines = IPU_level_malloc(numlines * sizeof(line_t), "P_LoadLineDefs"); memset(lines, 0, numlines * sizeof(line_t)); mld = (maplinedef_t *)(&buf[sizeof(int)]); @@ -330,7 +415,7 @@ void P_LoadSubsectors(const unsigned char *buf) { int lumplen = ((int*)buf)[0]; numsubsectors = lumplen / sizeof(mapsubsector_t); - subsectors = IPU_level_malloc(numsubsectors * sizeof(subsector_t)); + subsectors = IPU_level_malloc(numsubsectors * sizeof(subsector_t), "P_LoadSubsectors"); ms = (mapsubsector_t *)(&buf[sizeof(int)]); memset(subsectors, 0, numsubsectors * sizeof(subsector_t)); @@ -448,7 +533,7 @@ void P_LoadBlockMap(const unsigned char *buf) { int lumplen; lumplen = ((int*)buf)[0]; - blockmaplump = IPU_level_malloc(lumplen); + blockmaplump = IPU_level_malloc(lumplen, "P_LoadBlockMap"); memcpy(blockmaplump, &buf[4], lumplen); blockmap = blockmaplump + 4; @@ -465,6 +550,6 @@ void P_LoadBlockMap(const unsigned char *buf) { // Clear out mobj chains count = sizeof(*blocklinks) * bmapwidth * bmapheight; - blocklinks = IPU_level_malloc(count); + blocklinks = IPU_level_malloc(count, "P_LoadBlockMap"); memset(blocklinks, 0, count); } \ No newline at end of file diff --git a/src/ipu/p_setup_codelets.cpp b/src/ipu/p_setup_codelets.cpp index a68daf3..2b1d7cb 100644 --- a/src/ipu/p_setup_codelets.cpp +++ b/src/ipu/p_setup_codelets.cpp @@ -1,4 +1,5 @@ -#include +#include +#include "poplar/StackSizeDefs.hpp" #include @@ -16,45 +17,63 @@ extern "C" { void P_LoadLineDefs(const unsigned char *buf); void P_LoadSubsectors(const unsigned char *buf); void P_LoadNodes(const unsigned char *buf); + void P_LoadSegs(const unsigned char *buf); void P_LoadThings(const unsigned char *buf); void IPU_Setup_UnpackMarkNums(const unsigned char* buf); }; +// DEF_STACK_USAGE(400, "__runCodelet_P_SetupLevel_Vertex"); + // --------------- P_Setup ----------------- // -struct P_SetupLevel_SubFunc { - void (*func)(const unsigned char*); - int lump_num; -}; -static P_SetupLevel_SubFunc setupLevelSubfuncs[14] = { - {P_SetupLevel_pt0, 0}, - {P_LoadBlockMap, ML_BLOCKMAP}, - {P_LoadVertexes, ML_VERTEXES}, - {P_LoadSectors, ML_SECTORS}, - {P_LoadSideDefs, ML_SIDEDEFS}, - {P_LoadLineDefs, ML_LINEDEFS}, - {P_LoadSubsectors, ML_SSECTORS}, - {P_LoadNodes, ML_NODES}, - // {P_LoadSegs, ML_SEGS}, - // {P_GroupLines, ML_SEGS}, - // {P_LoadReject, ML_REJECT}, - {P_LoadThings, ML_THINGS}, - // {P_SpawnSpecials, 0} - {NULL, 0}, /* SENTINEL */ -}; +// struct P_SetupLevel_SubFunc { +// void (*func)(const unsigned char*); +// int lump_num; +// }; +// static P_SetupLevel_SubFunc setupLevelSubfuncs[14] = { +// {P_SetupLevel_pt0, 0}, +// {P_LoadBlockMap, ML_BLOCKMAP}, +// {P_LoadVertexes, ML_VERTEXES}, +// {P_LoadSectors, ML_SECTORS}, +// {P_LoadSideDefs, ML_SIDEDEFS}, +// {P_LoadLineDefs, ML_LINEDEFS}, +// {P_LoadSubsectors, ML_SSECTORS}, +// {P_LoadNodes, ML_NODES}, +// {P_LoadSegs, ML_SEGS}, +// // {P_GroupLines, ML_SEGS}, +// // {P_LoadReject, ML_REJECT}, +// {P_LoadThings, ML_THINGS}, +// // {P_SpawnSpecials, 0} +// {NULL, 0}, /* SENTINEL */ +// }; + +// DEF_FUNC_CALL_PTRS("__runCodelet_P_SetupLevel_Vertex", +// "P_LoadBlockMap,P_LoadVertexes,P_LoadSectors,P_LoadSideDefs,P_LoadLineDefs,P_LoadSubsectors"); -// THIS IS CALLING VIA A POINTER. THAT'S PROBABLY BAD... class P_SetupLevel_Vertex : public poplar::Vertex { poplar::Input> lumpBuf; poplar::Output lumpNum; public: bool compute() { static int step = 0; - setupLevelSubfuncs[step].func(&lumpBuf[0]); - step += 1; - *lumpNum = gamelumpnum + setupLevelSubfuncs[step].lump_num; - if (setupLevelSubfuncs[step].func == NULL) { + int next; + // Switch statements are bonkers + switch (step++) { + next = 0; case 0: P_SetupLevel_pt0(&lumpBuf[0]); + next = ML_BLOCKMAP; break; case 1: P_LoadBlockMap(&lumpBuf[0]); + next = ML_VERTEXES; break; case 2: P_LoadVertexes(&lumpBuf[0]); + next = ML_SECTORS; break; case 3: P_LoadSectors(&lumpBuf[0]); + next = ML_SIDEDEFS; break; case 4: P_LoadSideDefs(&lumpBuf[0]); + next = ML_LINEDEFS; break; case 5: P_LoadLineDefs(&lumpBuf[0]); + next = ML_SSECTORS; break; case 6: P_LoadSubsectors(&lumpBuf[0]); + next = ML_NODES; break; case 7: P_LoadNodes(&lumpBuf[0]); + next = ML_SEGS; break; case 8: P_LoadSegs(&lumpBuf[0]); + next = ML_THINGS; break; case 9: P_LoadThings(&lumpBuf[0]); + next = -1; break; + } + *lumpNum = gamelumpnum + next; + if (next == -1) { step = 0; } return true; diff --git a/src/ipu/r_bsp.c b/src/ipu/r_bsp.c index 0c22c1d..44a6482 100644 --- a/src/ipu/r_bsp.c +++ b/src/ipu/r_bsp.c @@ -469,6 +469,7 @@ void R_Subsector(int num) { I_Error("R_Subsector: solidsegs overflow (vanilla may crash here)\n"); } +*/ // // RenderBSPNode // Renders all subsectors below a given node, @@ -477,7 +478,7 @@ void R_Subsector(int num) { void R_RenderBSPNode(int bspnum) { node_t *bsp; int side; - +/* // Found a subsector? if (bspnum & NF_SUBSECTOR) { if (bspnum == -1) @@ -498,5 +499,5 @@ void R_RenderBSPNode(int bspnum) { // Possibly divide back space. if (R_CheckBBox(bsp->bbox[side ^ 1])) R_RenderBSPNode(bsp->children[side ^ 1]); + */ } -*/ diff --git a/src/ipu/r_codelets.cpp b/src/ipu/r_codelets.cpp index 469a1cf..eaeefbe 100644 --- a/src/ipu/r_codelets.cpp +++ b/src/ipu/r_codelets.cpp @@ -19,10 +19,10 @@ struct R_RenderPlayerView_Vertex : public poplar::Vertex { poplar::InOut> frame; void compute() { - // for (int i = 0; i < 100; ++i){ - // frame[i + 320 * i ] = 1; - // frame[i + 320 * i + 1] = 1; - // } + for (int i = 0; i < 100; ++i){ + frame[i + 320 * i ] = 1; + frame[i + 320 * i + 1] = 1; + } IPU_R_RenderPlayerView_UnpackMiscValues( (R_RenderPlayerView_MiscValues_t*) &miscValues[0] ); diff --git a/src/ipu/r_draw.c b/src/ipu/r_draw.c new file mode 100644 index 0000000..482ab3d --- /dev/null +++ b/src/ipu/r_draw.c @@ -0,0 +1,857 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// DESCRIPTION: +// The actual span/column drawing functions. +// Here find the main potential for optimization, +// e.g. inline assembly, different algorithms. +// + +// #include // JOSEF + +#include "d_mode.h" +// State. +#include "doomstat.h" +#include "doomtype.h" +/* +#include "i_system.h" +#include "i_video.h" +#include "m_fixed.h" +#include "r_defs.h" +#include "r_main.h" +#include "r_state.h" +#include "v_patch.h" +// Needs access to LFB (guess what). +#include "v_video.h" +#include "w_wad.h" +#include "z_zone.h" +*/ + +// ? +#define MAXWIDTH 1120 +#define MAXHEIGHT 832 + +// status bar height at bottom of screen +#define SBARHEIGHT 32 + +// +// All drawing to the view buffer is accomplished in this file. +// The other refresh files only know about ccordinates, +// not the architecture of the frame buffer. +// Conveniently, the frame buffer is a linear one, +// and we need only the base address, +// and the total size == width*height*depth/8., +// + +byte *viewimage; +int viewwidth; +int scaledviewwidth; +int viewheight; +int viewwindowx; +int viewwindowy; +pixel_t *ylookup[MAXHEIGHT]; +int columnofs[MAXWIDTH]; + +// Color tables for different players, +// translate a limited part to another +// (color ramps used for suit colors). +// +byte translations[3][256]; + +// Backing buffer containing the bezel drawn around the screen and +// surrounding background. + +static pixel_t *background_buffer = NULL; + +// +// R_DrawColumn +// Source is the top of the column to scale. +// +lighttable_t *dc_colormap; +int dc_x; +int dc_yl; +int dc_yh; +fixed_t dc_iscale; +fixed_t dc_texturemid; + +// first pixel in a column (possibly virtual) +byte *dc_source; + +// just for profiling +int dccount; + +/* +// +// A column is a vertical slice/span from a wall texture that, +// given the DOOM style restrictions on the view orientation, +// will always have constant z depth. +// Thus a special case loop for very fast rendering can +// be used. It has also been used with Wolfenstein 3D. +// +void R_DrawColumn(void) { + int count; + pixel_t *dest; + fixed_t frac; + fixed_t fracstep; + + count = dc_yh - dc_yl; + + // Zero length, column does not exceed a pixel. + if (count < 0) + return; + + if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) + I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); + + // Framebuffer destination address. + // Use ylookup LUT to avoid multiply with ScreenWidth. + // Use columnofs LUT for subwindows? + dest = ylookup[dc_yl] + columnofs[dc_x]; + + // Determine scaling, + // which is the only mapping to be done. + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl - centery) * fracstep; + + // Inner loop that does the actual texture mapping, + // e.g. a DDA-lile scaling. + // This is as fast as it gets. + do { + // Re-map color indices from wall texture column + // using a lighting/special effects LUT. + *dest = dc_colormap[dc_source[(frac >> FRACBITS) & 127]]; + + dest += SCREENWIDTH; + frac += fracstep; + + } while (count--); +} + +// UNUSED. +// Loop unrolled. +#if 0 +void R_DrawColumn (void) +{ + int count; + byte* source; + byte* dest; + byte* colormap; + + unsigned frac; + unsigned fracstep; + unsigned fracstep2; + unsigned fracstep3; + unsigned fracstep4; + + count = dc_yh - dc_yl + 1; + + source = dc_source; + colormap = dc_colormap; + dest = ylookup[dc_yl] + columnofs[dc_x]; + + fracstep = dc_iscale<<9; + frac = (dc_texturemid + (dc_yl-centery)*dc_iscale)<<9; + + fracstep2 = fracstep+fracstep; + fracstep3 = fracstep2+fracstep; + fracstep4 = fracstep3+fracstep; + + while (count >= 8) + { + dest[0] = colormap[source[frac>>25]]; + dest[SCREENWIDTH] = colormap[source[(frac+fracstep)>>25]]; + dest[SCREENWIDTH*2] = colormap[source[(frac+fracstep2)>>25]]; + dest[SCREENWIDTH*3] = colormap[source[(frac+fracstep3)>>25]]; + + frac += fracstep4; + + dest[SCREENWIDTH*4] = colormap[source[frac>>25]]; + dest[SCREENWIDTH*5] = colormap[source[(frac+fracstep)>>25]]; + dest[SCREENWIDTH*6] = colormap[source[(frac+fracstep2)>>25]]; + dest[SCREENWIDTH*7] = colormap[source[(frac+fracstep3)>>25]]; + + frac += fracstep4; + dest += SCREENWIDTH*8; + count -= 8; + } + + while (count > 0) + { + *dest = colormap[source[frac>>25]]; + dest += SCREENWIDTH; + frac += fracstep; + count--; + } +} +#endif + +void R_DrawColumnLow(void) { + int count; + pixel_t *dest; + pixel_t *dest2; + fixed_t frac; + fixed_t fracstep; + int x; + + count = dc_yh - dc_yl; + + // Zero length. + if (count < 0) + return; + + if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) { + + I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); + } + // dccount++; + // Blocky mode, need to multiply by 2. + x = dc_x << 1; + + dest = ylookup[dc_yl] + columnofs[x]; + dest2 = ylookup[dc_yl] + columnofs[x + 1]; + + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl - centery) * fracstep; + + do { + // Hack. Does not work corretly. + *dest2 = *dest = dc_colormap[dc_source[(frac >> FRACBITS) & 127]]; + dest += SCREENWIDTH; + dest2 += SCREENWIDTH; + frac += fracstep; + + } while (count--); +} + +// +// Spectre/Invisibility. +// +#define FUZZTABLE 50 +#define FUZZOFF (SCREENWIDTH) + +int fuzzoffset[FUZZTABLE] = { + FUZZOFF, -FUZZOFF, FUZZOFF, -FUZZOFF, FUZZOFF, FUZZOFF, -FUZZOFF, + FUZZOFF, FUZZOFF, -FUZZOFF, FUZZOFF, FUZZOFF, FUZZOFF, -FUZZOFF, + FUZZOFF, FUZZOFF, FUZZOFF, -FUZZOFF, -FUZZOFF, -FUZZOFF, -FUZZOFF, + FUZZOFF, -FUZZOFF, -FUZZOFF, FUZZOFF, FUZZOFF, FUZZOFF, FUZZOFF, + -FUZZOFF, FUZZOFF, -FUZZOFF, FUZZOFF, FUZZOFF, -FUZZOFF, -FUZZOFF, + FUZZOFF, FUZZOFF, -FUZZOFF, -FUZZOFF, -FUZZOFF, -FUZZOFF, FUZZOFF, + FUZZOFF, FUZZOFF, FUZZOFF, -FUZZOFF, FUZZOFF, FUZZOFF, -FUZZOFF, + FUZZOFF}; + +int fuzzpos = 0; + +// +// Framebuffer postprocessing. +// Creates a fuzzy image by copying pixels +// from adjacent ones to left and right. +// Used with an all black colormap, this +// could create the SHADOW effect, +// i.e. spectres and invisible players. +// +void R_DrawFuzzColumn(void) { + int count; + pixel_t *dest; + fixed_t frac; + fixed_t fracstep; + + // Adjust borders. Low... + if (!dc_yl) + dc_yl = 1; + + // .. and high. + if (dc_yh == viewheight - 1) + dc_yh = viewheight - 2; + + count = dc_yh - dc_yl; + + // Zero length. + if (count < 0) + return; + + if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) { + I_Error("R_DrawFuzzColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); + } + + dest = ylookup[dc_yl] + columnofs[dc_x]; + + // Looks familiar. + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl - centery) * fracstep; + + // Looks like an attempt at dithering, + // using the colormap #6 (of 0-31, a bit + // brighter than average). + do { + // Lookup framebuffer, and retrieve + // a pixel that is either one column + // left or right of the current one. + // Add index from colormap to index. + *dest = colormaps[6 * 256 + dest[fuzzoffset[fuzzpos]]]; + + // Clamp table lookup index. + if (++fuzzpos == FUZZTABLE) + fuzzpos = 0; + + dest += SCREENWIDTH; + + frac += fracstep; + } while (count--); +} + +// low detail mode version + +void R_DrawFuzzColumnLow(void) { + int count; + pixel_t *dest; + pixel_t *dest2; + fixed_t frac; + fixed_t fracstep; + int x; + + // Adjust borders. Low... + if (!dc_yl) + dc_yl = 1; + + // .. and high. + if (dc_yh == viewheight - 1) + dc_yh = viewheight - 2; + + count = dc_yh - dc_yl; + + // Zero length. + if (count < 0) + return; + + // low detail mode, need to multiply by 2 + + x = dc_x << 1; + + if ((unsigned)x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) { + I_Error("R_DrawFuzzColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); + } + + dest = ylookup[dc_yl] + columnofs[x]; + dest2 = ylookup[dc_yl] + columnofs[x + 1]; + + // Looks familiar. + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl - centery) * fracstep; + + // Looks like an attempt at dithering, + // using the colormap #6 (of 0-31, a bit + // brighter than average). + do { + // Lookup framebuffer, and retrieve + // a pixel that is either one column + // left or right of the current one. + // Add index from colormap to index. + *dest = colormaps[6 * 256 + dest[fuzzoffset[fuzzpos]]]; + *dest2 = colormaps[6 * 256 + dest2[fuzzoffset[fuzzpos]]]; + + // Clamp table lookup index. + if (++fuzzpos == FUZZTABLE) + fuzzpos = 0; + + dest += SCREENWIDTH; + dest2 += SCREENWIDTH; + + frac += fracstep; + } while (count--); +} + +// +// R_DrawTranslatedColumn +// Used to draw player sprites +// with the green colorramp mapped to others. +// Could be used with different translation +// tables, e.g. the lighter colored version +// of the BaronOfHell, the HellKnight, uses +// identical sprites, kinda brightened up. +// +byte *dc_translation; +byte *translationtables; + +void R_DrawTranslatedColumn(void) { + int count; + pixel_t *dest; + fixed_t frac; + fixed_t fracstep; + + count = dc_yh - dc_yl; + if (count < 0) + return; + + if ((unsigned)dc_x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) { + I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, dc_x); + } + + dest = ylookup[dc_yl] + columnofs[dc_x]; + + // Looks familiar. + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl - centery) * fracstep; + + // Here we do an additional index re-mapping. + do { + // Translation tables are used + // to map certain colorramps to other ones, + // used with PLAY sprites. + // Thus the "green" ramp of the player 0 sprite + // is mapped to gray, red, black/indigo. + *dest = dc_colormap[dc_translation[dc_source[frac >> FRACBITS]]]; + dest += SCREENWIDTH; + + frac += fracstep; + } while (count--); +} + +void R_DrawTranslatedColumnLow(void) { + int count; + pixel_t *dest; + pixel_t *dest2; + fixed_t frac; + fixed_t fracstep; + int x; + + count = dc_yh - dc_yl; + if (count < 0) + return; + + // low detail, need to scale by 2 + x = dc_x << 1; + + if ((unsigned)x >= SCREENWIDTH || dc_yl < 0 || dc_yh >= SCREENHEIGHT) { + I_Error("R_DrawColumn: %i to %i at %i", dc_yl, dc_yh, x); + } + + dest = ylookup[dc_yl] + columnofs[x]; + dest2 = ylookup[dc_yl] + columnofs[x + 1]; + + // Looks familiar. + fracstep = dc_iscale; + frac = dc_texturemid + (dc_yl - centery) * fracstep; + + // Here we do an additional index re-mapping. + do { + // Translation tables are used + // to map certain colorramps to other ones, + // used with PLAY sprites. + // Thus the "green" ramp of the player 0 sprite + // is mapped to gray, red, black/indigo. + *dest = dc_colormap[dc_translation[dc_source[frac >> FRACBITS]]]; + *dest2 = dc_colormap[dc_translation[dc_source[frac >> FRACBITS]]]; + dest += SCREENWIDTH; + dest2 += SCREENWIDTH; + + frac += fracstep; + } while (count--); +} + +// +// R_InitTranslationTables +// Creates the translation tables to map +// the green color ramp to gray, brown, red. +// Assumes a given structure of the PLAYPAL. +// Could be read from a lump instead. +// +void R_InitTranslationTables(void) { + int i; + + translationtables = Z_Malloc(256 * 3, PU_STATIC, 0); + + // translate just the 16 green colors + for (i = 0; i < 256; i++) { + if (i >= 0x70 && i <= 0x7f) { + // map green ramp to gray, brown, red + translationtables[i] = 0x60 + (i & 0xf); + translationtables[i + 256] = 0x40 + (i & 0xf); + translationtables[i + 512] = 0x20 + (i & 0xf); + } else { + // Keep all other colors as is. + translationtables[i] = translationtables[i + 256] = + translationtables[i + 512] = i; + } + } +} + +// +// R_DrawSpan +// With DOOM style restrictions on view orientation, +// the floors and ceilings consist of horizontal slices +// or spans with constant z depth. +// However, rotation around the world z axis is possible, +// thus this mapping, while simpler and faster than +// perspective correct texture mapping, has to traverse +// the texture at an angle in all but a few cases. +// In consequence, flats are not stored by column (like walls), +// and the inner loop has to step in texture space u and v. +// +int ds_y; +int ds_x1; +int ds_x2; + +lighttable_t *ds_colormap; + +fixed_t ds_xfrac; +fixed_t ds_yfrac; +fixed_t ds_xstep; +fixed_t ds_ystep; + +// start of a 64*64 tile image +byte *ds_source; + +// just for profiling +int dscount; + +// +// Draws the actual span. +void R_DrawSpan(void) { + unsigned int position, step; + pixel_t *dest; + int count; + int spot; + unsigned int xtemp, ytemp; + + if (ds_x2 < ds_x1 || ds_x1 < 0 || ds_x2 >= SCREENWIDTH || + (unsigned)ds_y > SCREENHEIGHT) { + I_Error("R_DrawSpan: %i to %i at %i", ds_x1, ds_x2, ds_y); + } + // dscount++; + + // Pack position and step variables into a single 32-bit integer, + // with x in the top 16 bits and y in the bottom 16 bits. For + // each 16-bit part, the top 6 bits are the integer part and the + // bottom 10 bits are the fractional part of the pixel position. + + position = ((ds_xfrac << 10) & 0xffff0000) | ((ds_yfrac >> 6) & 0x0000ffff); + step = ((ds_xstep << 10) & 0xffff0000) | ((ds_ystep >> 6) & 0x0000ffff); + + dest = ylookup[ds_y] + columnofs[ds_x1]; + + // We do not check for zero spans here? + count = ds_x2 - ds_x1; + + do { + // Calculate current texture index in u,v. + ytemp = (position >> 4) & 0x0fc0; + xtemp = (position >> 26); + spot = xtemp | ytemp; + + // Lookup pixel from flat texture tile, + // re-index using light/colormap. + *dest++ = ds_colormap[ds_source[spot]]; + + position += step; + + } while (count--); +} + +// UNUSED. +// Loop unrolled by 4. +#if 0 +void R_DrawSpan (void) +{ + unsigned position, step; + + byte* source; + byte* colormap; + pixel_t* dest; + + unsigned count; + usingned spot; + unsigned value; + unsigned temp; + unsigned xtemp; + unsigned ytemp; + + position = ((ds_xfrac<<10)&0xffff0000) | ((ds_yfrac>>6)&0xffff); + step = ((ds_xstep<<10)&0xffff0000) | ((ds_ystep>>6)&0xffff); + + source = ds_source; + colormap = ds_colormap; + dest = ylookup[ds_y] + columnofs[ds_x1]; + count = ds_x2 - ds_x1 + 1; + + while (count >= 4) + { + ytemp = position>>4; + ytemp = ytemp & 4032; + xtemp = position>>26; + spot = xtemp | ytemp; + position += step; + dest[0] = colormap[source[spot]]; + + ytemp = position>>4; + ytemp = ytemp & 4032; + xtemp = position>>26; + spot = xtemp | ytemp; + position += step; + dest[1] = colormap[source[spot]]; + + ytemp = position>>4; + ytemp = ytemp & 4032; + xtemp = position>>26; + spot = xtemp | ytemp; + position += step; + dest[2] = colormap[source[spot]]; + + ytemp = position>>4; + ytemp = ytemp & 4032; + xtemp = position>>26; + spot = xtemp | ytemp; + position += step; + dest[3] = colormap[source[spot]]; + + count -= 4; + dest += 4; + } + while (count > 0) + { + ytemp = position>>4; + ytemp = ytemp & 4032; + xtemp = position>>26; + spot = xtemp | ytemp; + position += step; + *dest++ = colormap[source[spot]]; + count--; + } +} +#endif + +// +// Again.. +// +void R_DrawSpanLow(void) { + unsigned int position, step; + unsigned int xtemp, ytemp; + pixel_t *dest; + int count; + int spot; + + if (ds_x2 < ds_x1 || ds_x1 < 0 || ds_x2 >= SCREENWIDTH || + (unsigned)ds_y > SCREENHEIGHT) { + I_Error("R_DrawSpan: %i to %i at %i", ds_x1, ds_x2, ds_y); + } + // dscount++; + + position = ((ds_xfrac << 10) & 0xffff0000) | ((ds_yfrac >> 6) & 0x0000ffff); + step = ((ds_xstep << 10) & 0xffff0000) | ((ds_ystep >> 6) & 0x0000ffff); + + count = (ds_x2 - ds_x1); + + // Blocky mode, need to multiply by 2. + ds_x1 <<= 1; + ds_x2 <<= 1; + + dest = ylookup[ds_y] + columnofs[ds_x1]; + + do { + // Calculate current texture index in u,v. + ytemp = (position >> 4) & 0x0fc0; + xtemp = (position >> 26); + spot = xtemp | ytemp; + + // Lowres/blocky mode does it twice, + // while scale is adjusted appropriately. + *dest++ = ds_colormap[ds_source[spot]]; + *dest++ = ds_colormap[ds_source[spot]]; + + position += step; + + } while (count--); +} + +// +// R_InitBuffer +// Creats lookup tables that avoid +// multiplies and other hazzles +// for getting the framebuffer address +// of a pixel to draw. +// +void R_InitBuffer(int width, int height) { + int i; + + // Handle resize, + // e.g. smaller view windows + // with border and/or status bar. + viewwindowx = (SCREENWIDTH - width) >> 1; + + // Column offset. For windows. + for (i = 0; i < width; i++) + columnofs[i] = viewwindowx + i; + + // Samw with base row offset. + if (width == SCREENWIDTH) + viewwindowy = 0; + else + viewwindowy = (SCREENHEIGHT - SBARHEIGHT - height) >> 1; + + // Preclaculate all row offsets. + for (i = 0; i < height; i++) + ylookup[i] = I_VideoBuffer + (i + viewwindowy) * SCREENWIDTH; +} + +// +// R_FillBackScreen +// Fills the back screen with a pattern +// for variable screen sizes +// Also draws a beveled edge. +// +void R_FillBackScreen(void) { + byte *src; + pixel_t *dest; + int x; + int y; + patch_t *patch; + + // DOOM border patch. + char *name1 = ("FLOOR7_2"); + + // DOOM II border patch. + char *name2 = ("GRNROCK"); + + char *name; + + // If we are running full screen, there is no need to do any of this, + // and the background buffer can be freed if it was previously in use. + + if (scaledviewwidth == SCREENWIDTH) { + if (background_buffer != NULL) { + Z_Free(background_buffer); + background_buffer = NULL; + } + + return; + } + + // Allocate the background buffer if necessary + + if (background_buffer == NULL) { + background_buffer = Z_Malloc(SCREENWIDTH * (SCREENHEIGHT - SBARHEIGHT) * + sizeof(*background_buffer), + PU_STATIC, NULL); + } + + if (gamemode == commercial) + name = name2; + else + name = name1; + + src = W_CacheLumpName(name, PU_CACHE); + dest = background_buffer; + + for (y = 0; y < SCREENHEIGHT - SBARHEIGHT; y++) { + for (x = 0; x < SCREENWIDTH / 64; x++) { + memcpy(dest, src + ((y & 63) << 6), 64); + dest += 64; + } + + if (SCREENWIDTH & 63) { + memcpy(dest, src + ((y & 63) << 6), SCREENWIDTH & 63); + dest += (SCREENWIDTH & 63); + } + } + + // Draw screen and bezel; this is done to a separate screen buffer. + + V_UseBuffer(background_buffer); + + patch = W_CacheLumpName(("brdr_t"), PU_CACHE); + + for (x = 0; x < scaledviewwidth; x += 8) + V_DrawPatch(viewwindowx + x, viewwindowy - 8, patch); + patch = W_CacheLumpName(("brdr_b"), PU_CACHE); + + for (x = 0; x < scaledviewwidth; x += 8) + V_DrawPatch(viewwindowx + x, viewwindowy + viewheight, patch); + patch = W_CacheLumpName(("brdr_l"), PU_CACHE); + + for (y = 0; y < viewheight; y += 8) + V_DrawPatch(viewwindowx - 8, viewwindowy + y, patch); + patch = W_CacheLumpName(("brdr_r"), PU_CACHE); + + for (y = 0; y < viewheight; y += 8) + V_DrawPatch(viewwindowx + scaledviewwidth, viewwindowy + y, patch); + + // Draw beveled edge. + V_DrawPatch(viewwindowx - 8, viewwindowy - 8, + W_CacheLumpName(("brdr_tl"), PU_CACHE)); + + V_DrawPatch(viewwindowx + scaledviewwidth, viewwindowy - 8, + W_CacheLumpName(("brdr_tr"), PU_CACHE)); + + V_DrawPatch(viewwindowx - 8, viewwindowy + viewheight, + W_CacheLumpName(("brdr_bl"), PU_CACHE)); + + V_DrawPatch(viewwindowx + scaledviewwidth, viewwindowy + viewheight, + W_CacheLumpName(("brdr_br"), PU_CACHE)); + + V_RestoreBuffer(); +} + +// +// Copy a screen buffer. +// +void R_VideoErase(unsigned ofs, int count) { + // LFB copy. + // This might not be a good idea if memcpy + // is not optiomal, e.g. byte by byte on + // a 32bit CPU, as GNU GCC/Linux libc did + // at one point. + + if (background_buffer != NULL) { + memcpy(I_VideoBuffer + ofs, background_buffer + ofs, + count * sizeof(*I_VideoBuffer)); + } +} + +// +// R_DrawViewBorder +// Draws the border around the view +// for different size windows? +// +void R_DrawViewBorder(void) { + int top; + int side; + int ofs; + int i; + + if (scaledviewwidth == SCREENWIDTH) + return; + + top = ((SCREENHEIGHT - SBARHEIGHT) - viewheight) / 2; + side = (SCREENWIDTH - scaledviewwidth) / 2; + + // copy top and one line of left side + R_VideoErase(0, top * SCREENWIDTH + side); + + // copy one line of right side and bottom + ofs = (viewheight + top) * SCREENWIDTH - side; + R_VideoErase(ofs, top * SCREENWIDTH + side); + + // copy sides using wraparound + ofs = top * SCREENWIDTH + SCREENWIDTH - side; + side <<= 1; + + for (i = 1; i < viewheight; i++) { + R_VideoErase(ofs, side); + ofs += SCREENWIDTH; + } + + // ? + V_MarkRect(0, 0, SCREENWIDTH, SCREENHEIGHT - SBARHEIGHT); +} + +*/ \ No newline at end of file diff --git a/src/ipu/r_main.c b/src/ipu/r_main.c index cfced9d..3c13df1 100644 --- a/src/ipu/r_main.c +++ b/src/ipu/r_main.c @@ -738,7 +738,7 @@ void R_RenderPlayerView(player_t *player) { R_SetupFrame(player); // Clear buffers. - // R_ClearClipSegs(); // TODO + // R_ClearClipSegs(); // TODO // R_ClearDrawSegs(); // TODO // R_ClearPlanes(); // TODO // R_ClearSprites(); // TODO @@ -747,7 +747,7 @@ void R_RenderPlayerView(player_t *player) { // NetUpdate(); // TODO // The head node is the last node output. - // R_RenderBSPNode(numnodes - 1); // TODO + R_RenderBSPNode(numnodes - 1); // Check for new console commands. // NetUpdate(); // TODO diff --git a/src/ipu_host.cpp b/src/ipu_host.cpp index 6a5e69b..0f7c09b 100644 --- a/src/ipu_host.cpp +++ b/src/ipu_host.cpp @@ -137,7 +137,7 @@ void IpuDoom::buildIpuGraph() { poplar::program::Sequence G_DoLoadLevel_prog({ poplar::program::Copy(miscValuesStream, m_miscValuesBuf), poplar::program::Execute(G_DoLoadLevel_CS), - poplar::program::Repeat(9, poplar::program::Sequence({ + poplar::program::Repeat(10, poplar::program::Sequence({ poplar::program::Execute(P_SetupLevel_CS), poplar::program::Copy(m_lumpNum, lumpNumStream), poplar::program::Sync(poplar::SyncType::GLOBAL), // lumpnum must arrive before lump is loaded