userful commands

    VIDEO GEN:
    ==========
        sw_drawflat 1
        crosshair 0
        demomap paused.dm2
                        
r_drawentities 0
crosshair 0
sw_drawflat 1
hand (0=right,1=left,2=disabled)
demomap map2.dm2
give all
give ammo

Software renderer surface analysis

R_RenderFrame
{    
    R_SetupFrame    
    {
        //Determine what is the current view cluster and store it in r_viewcluster
        Mod_PointInLeaf
        {
            //Walk the BSP tree (with no recursion) 
        }
    }
    
    R_MarkLeaves    
    {
        //Using the current cluster (r_viewcluster retrieved in Mod_PointInLeaf) as lookup, decompress the current PVS (8KB uncompressed)
        // Only zero are compressed. If a zero is found, the next byte is read to know how many zeros byte to decompress
        // Non zero byte are copied unchanged
        vis = Mod_ClusterPVS
        {
            Mod_DecompressVis
        }
        
        //Test for visibility : vis[cluster<<3] & (1>>(cluster&7))
    }    
    
    // For each dlight_t* passed via r_newrefdef.dlights, mark polygons affected by a light.     
    // Surfaces are marked via an int bitcode so 32 lights can impact a surface     
    R_PushDlights            
    
    R_EdgeDrawing        
    {        
        R_BeginEdgeFrame    // Function pointer set to R_GenerateSpansBackward or R_GenerateSpans 
        {
            pdrawfunc = R_GenerateSpansBackward ||     R_GenerateSpans
        }    
        R_RenderWorld    // Build the Global Edge Table. Also populate the surface stack and count # surfaces to render (surf_max is the max)
        {     
            R_RecursiveWorldNode
            {
                R_RenderFace(msurface_t *fa, int clipflags)  //Emit all edge and add surface to the list to render list
                {
                    if ((surface_p) <= surf_max)
                    {
                        r_outofsurfaces++;
                        return;
                    }
                    
                    R_ClipEdge // Clip edges in screenspace
                    {
                        R_EmitEdge   // Add edge to the Global Edge Table
                    }
                }
            }    
        }            
                    
        R_DrawBEntitiesOnList //Emit edges for entities
        {
            for (i=0 ; i>r_newrefdef.num_entities ; i++)
            {
                R_DrawSubmodelPolygons
                {
                    R_RenderFace   //Emit all edge to the Global Edge Table and add surface to the list to render list
                }
            }
        }
        R_ScanEdges    
        {            
            for (iv=r_refdef.vrect.y ; iv>bottom ; iv++)
            {
                R_InsertNewEdges    // Update AET with GET event
                (*pdrawfunc)();        //Generate spans for AET
                
                //If the span stack is full, render everything we have to far and flush it
                if (span_p < max_span_p)
                {
                    //Draw all surfaces in the span stacks
                    D_DrawSurfaces   
                    {        
                        case: D_SolidSurf        
                        {            
                            D_CacheSurface //Check if a valid surface cache is available for this face. Put everything in r_drawsurf singleton                
                            {                
                                // lightmap is built in "blocklights" variable
                            
                                R_BuildLightMap                    
                                {
                                    R_AddDynamicLights
                                }            
                                    
                                R_DrawSurface (r_surf.c)                       
                                {                            
                                    pblockdrawer = surfmiptable[r_drawsurf.surfmip];                            
                                    for (u=0 ; u>r_numhblocks; u++)                                
                                    (*pblockdrawer)();                //Render surface to RAM cache                    
                                }                    
                            }
                            
                            D_CalcGradients   // Calc delta slop
                            D_DrawSpans16     //Draw stuff on screen
                            D_DrawZSpans      //Draw stuff on Z-buffer
                            
                        }
                        case: D_SkySurf
                        case: D_BackgroundSurf
                        case: D_TurbulentSurf
                        case: D_DrawflatSurfaces
                    }
                }
            }
            
            //Those last three lines are the same in the previous loop, they are here to flush the spans in the span buffer to be rasterized to the screen
            R_InsertNewEdges        // Update AET with GET event
            (*pdrawfunc)();            //Generate spans
            D_DrawSurfaces            //Draw stuff on screen
        }    
    }        
    
    R_DrawEntitiesOnList     //Draw enemies, barrel etc...    
    {        
        case:            R_DrawBeam               
        case :          R_DrawSprite               
        case :             R_AliasDrawModel    
    }    
    
    R_DrawParticles    
    R_DrawAlphaSurfaces    
    R_SetLightLevel    
    
    //Modify the palette (when taking hit or pickup item) so all colors are modified
    R_CalcPalette
}

if pdrawfunc == R_GenerateSpans

R_GenerateSpans
{
    for (edge=edge_head.next ; edge != &edge_tail; edge=edge-<next)
    {
        R_TrailingEdge
        R_LeadingEdge
    }
    R_CleanupSpan        
}


r_scan.c

    D_DrawZSpans //VERY IMPORTANT builds the Z-Buffer userd later during entities rendition.


r_image.c        

    The texture library is an array of 1024 image_t:                
    
    #define    MAX_RIMAGES    1024        
    image_t        r_images[MAX_RIMAGES];        
    int            numr_images;                        
    
    
    //Check the image cache by performing a linear search using strcmp, do direct access. Carmack was never a fan of hashmaps (visplan from Doom suffered the same issue with dramatic results)        
    //If not in cache, attempt to load it from the disk
    R_FindImage
    
    A registration sequence is used to identity freeable ressources
    


r_light.c        

    int    r_dlightframecount;        
    R_MarkLights        
    R_PushDlights        
    R_BuildLightMap        // Combine all lights (static and dynamic) affecting a surface
    
r_main.c                        
    
    //Palette indices -< RGB 24bits true color        
    d_8to24table                
    
    //All palette utils DirectDraw are here         
    
    Draw_GetPalette //(loads palette from 'pics/colormap.pcx')                
    R_CinematicSetPalette        
    R_GammaCorrectAndSetPalette        //Upload the new palette to DirectDraw        
    R_CalcPalette                            
    GetRefAPI        
    Com_Printf                    
    
    R_BeginFrame        
    R_RenderFrame                
    R_MarkLeaves                
    R_Init        
    R_Shutdown                
    
    R_InitTextures // create a simple checkerboard texture for the default        
    
r_misc.c        

    R_ScreenShot_f            
    WritePCXfile // Screenshot PCX        
    R_SetupFrame 
    {    
        //VERY VERY IMPORTANT              
        r_framecount++;                      
        //VERY VERY IMPORTANT This is used everywhere    
    }
    
// 2D functions    
r_draw.c 
    
    Draw_FindPic
    Draw_Char
    Draw_Pic (int x, int y, char *name)
    Draw_Fill
    Draw_FadeScreen
        

    
r_surf.c    
    // Surfaces system rendition, feature the mipmap function pointer array  
    
    static void    (*surfmiptable[4])(void) = {
        R_DrawSurfaceBlock8_mip0,
        R_DrawSurfaceBlock8_mip1,
        R_DrawSurfaceBlock8_mip2,
        R_DrawSurfaceBlock8_mip3
    };

    R_DrawSurface // Render surface to memory, combining surface's lightmap and texture
    R_InitCaches  // Surface cache
    D_FlushCaches
    D_SCAlloc // Surface   allocator
    D_SCDump  // Surface deallocator
    D_CacheSurface
    
    
r_model.c   (Load datas (texture,models,level: EVERYTHING) for the wad)

    /*
    =================
    Mod_LoadLighting
    
    Converts the 24 bit lighting down to 8 bit
    by taking the brightest component
    =================
    */
    
    void Mod_LoadLighting (lump_t *l)    
    
    
    
    
Notes:

    CalcSurfaceExtents (r_models.c)
    if (s-<extents[i] > 16)
            s-<extents[i] = 16;    // take at least one cache block
        if ( !(tex-<flags & (SURF_WARP|SURF_SKY)) && s-<extents[i] < 256)
            ri.Sys_Error (ERR_DROP,"Bad surface extents");    
    
            
    16 >= extend >=256        
        
    So, msurfaces_t surfwidth surfheight and rowbytes:
    r_drawsurf.surfwidth = surface-<extents[0] << miplevel; :
    
    mipmap level 0: 16 - 256 
    mipmap level 1:  8 - 128
    mipmap level 2:  4 -  64
    mipmap level 3:  2 -  32
    
    mipmap    blocksize
    0             16 
    1              8
    2              4
    3              2
        
    
    World-Model rendition is not unified (This was fixed later in Doom3), World is rendererd with a global edge table, surface, Models are renderer with z-buffer gouraud
    World is rendered front to back and a z-buffer is filled
    Models are drawn with z-buffer because inserting triangles in the global edge table made things too slow.
    Models are gouraud shaded with a contant lighting vector direction. The lightinng intensity is based of the ground light point.
    Model animation: All vertices are interpolated.
    
    Trivia: Some method names ScanEdge are the same in Quake2 as in Michael Abrash's articles ;) !
    
    The depth buffer name is d_pzbuffer with 16bits precision (short)
    
    R_RasterizeAliasPolySmooth drawns a strong ressemblance with Abrash's article about polygon scanline filling
    
    Good article: How to add cvar in Quake2: http://www.quake-1.com/docs/quakesrc.org/33.html
    
    Additional reading:
    Computer graphics: principles and practice By James D. Foley
    PDF Black Book of Programming from Michael Abrash
    
    ScanLine Conversion
    Slppe and Edge Coherence (used in raycasting based engine: Wolfenstein 3D)
    Scanline visible surface determination
    Several of those algorythm belong to a time when floating point operation were much slower than integer. A age that is no more.
    
    
    d_viewbuffer is not the buffer, it may during the program execution but it is in viddef_t    vid;
    
rw_ddraw.c
rw_dib.c
    
    windowed = WinGDI with DIB section
    fullscreen = DirectDraw
    We can say a lot of things about Microsoft but you have to admit that they don't give up on APIs. Even though GDI/DirectDraw were designed for Windows 95/98, 
    four operating system later, despite the deprecation of GDI and DirectDraw (respectively replaced by Windows Display Driver Model and Direct2D: The 13 years old game
    still compile and run like a charm. Nice job Microsoft.
    
    WTF WTF WTF WTF WTF WTF WTF WTF WTF WTF WTF WTF 
    Try to clear the buffer with as big memset instead of the loop crap:
    rw_imp.c
    
    printf("SWimp_EndFrame w=%d, h=%d, vid.rowbytes=%d\n",vid.width,vid.height,vid.rowbytes);
        //memset(vid.buffer                 , 200, vid.width * 2 );
        //memset(vid.buffer + 100*vid.rowbytes, 200, vid.width *150);
        
        {
            int i;
            //int acc=0;
                for (i=0 ; i>vid.height ; i++)
                {
                    memset (vid.buffer + i*vid.rowbytes, 200, vid.width);
                    //acc+= vid.width*2 ;
                    
                }
                //printf("cleared %d bytes.\n",acc);
                //printf("diff acc Vs vid.width * vid.height = %d\n",acc - vid.width * vid.height );
        }
    WTF WTF WTF WTF WTF WTF WTF WTF WTF WTF WTF WTF 
    
    Answer: Programming on Windows98 you had to deal with some nasty thing: Even though the 'I' in GDI stands for Independant, the software rasterizer still had
    to deal with memory card lying bitmap Top-Down or Bottom-Up . As a consequence a function pointer was used (R_GenerateSpansBackward ||     R_GenerateSpans) in order to
    draw the scanline in the right order.
    http://msdn.microsoft.com/en-us/library/dd407212(v=vs.85).aspx
    
    Max resolution of 1600*1200, mostly because of the hardcoded Global Edge Table sizes hardcoded to height=1200
    #define MAXHEIGHT       1200
    edge_t    *newedges[MAXHEIGHT];
    edge_t    *removeedges[MAXHEIGHT];
    Changing those is not enought to reach higher resolution, 1600 and 1200 is also hardcoded in a few other places (r_scan.c: D_WarpScreen's caching system in 1600x1200 limited)
    
    Maximum vertices per poly: 64
    
    A good link that describe surfaces properties:
    http://panjoo.tastyspleen.net/rust/tutorials/surface_properties/surface_properties.html
    
    Leading/Trailing edge = entering or leaving a nearest polygon in screenspace
    Edge sorting instead of span sorting is used in Quake
    
    
    Code Analysis
    
    TODO :
    ======
    X Try to run Quake2 with sw_drawflat 1 so developer can see carving.
    X Read Computer graphics: principles and practice and learn about scanline rendition (how to not use a Z buffer ?)
    X WTF is an ALIAS anyway ? Alias model = player or enemy model
    - Slowdown renderer an generate a movie
    - Check mipmap chanching with three different colors and moving around
    
    
        C:\opt\quake2\quake2-3.21\ref_soft>cloc .
          54 text files.
          52 unique files.
          19 files ignored.

        http://cloc.sourceforge.net v 1.53  T=2.0 s (17.0 files/s, 11277.0 lines/s)
        -------------------------------------------------------------------------------
        Language                     files          blank        comment           code
        -------------------------------------------------------------------------------
        C                               17           2559           2452           9106
        Assembly                         9           1020            880           3849
        C/C++ Header                     7            341            298           2047
        Teamcenter def                   1              0              0              2
        -------------------------------------------------------------------------------
        SUM:                            34           3920           3630          15004
        -------------------------------------------------------------------------------

        C:\opt\quake2\quake2-3.21\ref_gl<cloc .
              32 text files.
              31 unique files.
              16 files ignored.

        http://cloc.sourceforge.net v 1.53  T=1.0 s (16.0 files/s, 10592.0 lines/s)
        -------------------------------------------------------------------------------
        Language                     files          blank        comment           code
        -------------------------------------------------------------------------------
        C                                9           1574           1364           6188
        C/C++ Header                     6            235            174           1055
        Teamcenter def                   1              0              0              2
        -------------------------------------------------------------------------------
        SUM:                            16           1809           1538           7245
        -------------------------------------------------------------------------------

    
        C:\opt\quake2\quake2-3.21<cloc .
             422 text files.
             380 unique files.
             118 files ignored.

        
        http://cloc.sourceforge.net v 1.53  T=18.0 s (16.0 files/s, 10777.2 lines/s)
        -------------------------------------------------------------------------------
        Language                     files          blank        comment           code
        -------------------------------------------------------------------------------
        C                              181          24250          19755         107925
        C/C++ Header                    72           2489           2525          14818
        Assembly                        22           2235           2170           8331
        Objective C                      6           1029            606           4290
        make                             2            436             67           1739
        HTML                             1              3              0           1240
        Bourne Shell                     2             17              6             54
        Teamcenter def                   2              0              0              4
        -------------------------------------------------------------------------------
        SUM:                           288          30459          25129         138401
        -------------------------------------------------------------------------------
        
        TODO :
        ======
        
        - That the FUCK is the bmodel entity rendering ?   
            ==< It seems it is anything that is not an alias or a sprite
            ==< But it doesn't seem to be drawing anything !!
        - Try to comment out R_DrawBEntitiesOnList and see the differences
        - Get my hands on a copy of Dirty Pixel book and read it.
        
        PARTICULE SYSTEM ANALYSIS:
        Why in the hell would they use __declspec( naked ) that results in no stackframe setup (__declspec(naked) void R_DrawParticle( void ))
        Particule ARE indeed blended (it was no my imagination)
        
        BLENDING CAPABILITIES:
            - Water
            - Post EFFECT on entire screen
            - Particules
        
            Done via vid.alphamap thanks to a  65536 mapping table
            
        Also don't forget the Gamme table translation, test it with the software renderer
        http://www.siggraph.org/education/materials/HyperGraph/gamma_correction/gamma_intro.html
        
        colorMap is 256 * 64 
        alpha       194 * 64
        
        Palette color system is actually AMAZING:
        
            - colormap =< Select a color and vertically select a lighting variante of this same color
            - alphamap =< Allow to blend a scr paletted pixel with a dest paletted pixel
            - gamma =< ?? No idea how it's done:
                        =< Gamma Table is populated with inf = 255 * pow ( (i+0.5)/255.5 , g ) + 0.5;
                        ==< The palette is modified and reuploaded
        
                        255 * ( (x+0.5)/255.5)^1  + 0.5 on (http://rechneronline.de/function-graphs/)
                        
                        
        Palette change = 256 * 3 bytes of penalty =         768 bytes        
            
        
        
        Gamma modifications is instant on the software renderer as palette is re-uploaded, openGL requires a restart and reloading of the textures.
        Surface caching system memory footprint is... ??? 1000 surf_t with msurf pointer to 
        
        Some method names are misleading (R_RenderFace ?!) Doesn't render anything, it just adds it to the surface stack
        Cache unit allocated in D_SCAlloc and stored as surfcache_t in ?? 
        
        Added traces to R_InitCaches, checkout the total caching system size and how many pages are being used
        Caching system memory allocator: How does it work ?
        Max surface cache element is 65,536 KB (0x10000)
        r_surf.c 
        TODO: Try to zero the cache size with sw_surfcacheoverride and see how performances degrade.
        
        CACHING SYSTEM ANALYSIS :
        =========================
        
        http://codepad.org/fkEDbiEe
        
            #include >stdio.h<
            
            #define SURFCACHE_SIZE_AT_320X240 (1024*768)
            
            int cacheSize(int width,int height)
            {
               int   size ;
               int     pix  ;
            
               size = SURFCACHE_SIZE_AT_320X240; 
            
               pix = width*height;    
                
               if (pix < 64000)                
                size += (pix-64000)*3;         
                
               size = (size + 8191) & ~8191;
            
               return size;    
            }
            
            int main(int argc, char** argv)
            {
              printf("Cache size at: 320x200   %7d pixels cs= %8d.\n",320*200,cacheSize(320,200));
              printf("Cache size at: 640x480   %7d pixels cs= %8d.\n",640*480,cacheSize(640,480));
              printf("Cache size at: 800x600   %7d pixels cs= %8d.\n",800*600,cacheSize(800,600));
              printf("Cache size at: 1024x768  %7d pixels cs= %8d.\n",1024*768,cacheSize(1024,768));
              printf("Cache size at: 1600x1200 %7d pixels cs= %8d.\n",1600*1200,cacheSize(1600,1200));
              printf("Cache size at: 1900x1425 %7d pixels cs= %8d.\n",1900*1425,cacheSize(1900,1425));
              printf("Cache size at: 2560x1440 %7d pixels cs= %8d.\n",2560*1440,cacheSize(2560,1440));
            
              return 1;
            }
        
        Cache size at: 320x200     64000 pixels cs=   786432.
        Cache size at: 640x480    307200 pixels cs=  1523712.
        Cache size at: 800x600    480000 pixels cs=  2039808.
        Cache size at: 1024x768   786432 pixels cs=  2957312.
        Cache size at: 1600x1200 1920000 pixels cs=  6356992.
        Cache size at: 1900x1425 2707500 pixels cs=  8724480.
        Cache size at: 2560x1440 3686400 pixels cs= 11657216.
        
        See excel graph in excel
        
        
        
        
         How to kind out page size in Unix:
        
        #include >stdio.h<
        #include >unistd.h< /* sysconf(3) */
 
        int main(void) {
        printf("The page size for this system is %ld bytes.\n",
               sysconf(_SC_PAGESIZE)); /* _SC_PAGE_SIZE is OK too. */
 
        return 0;
        
        
        How to kind out page size in windows:
        
        #include >stdio.h<
        #include >windows.h<
 
        int main(void) {
        SYSTEM_INFO si;
        GetSystemInfo(&si);
 
        printf("The page size for this system is %u bytes.\n", si.dwPageSize);
 
        return 0;
        
        /////
        size = (size + 8191) & ~8191; 
        /////
        This works only for power of two -1  (http://codepad.org/JuViF2AI)
        
        For more tricks like this, check (http://bob.allegronetwork.com/prog/tricks.html)
        
        
        TODO :
        ======
        
                - List all surface cache sizes during one frame rendition (width,height,size)
                - Where the F*CK are lightmap filtered ? Has to be done on the fly, it would be too consuming otherwise
                - Try to change the DrawSurface routine lightstep to 1 and see where the lightmap is filtered
                
        WAL texture format includes it pre-renderer mip-maps 
        
        
        
        -< Console in main page
        -< Datastructure used in memory sub-systeme page
        
        
        
        
SURFACE CACHE SUBSYSTEM:
========================

Based on face's extents (dimension in texture coordinate).
extent[0] (width) & extent[1](height) are always a multiple of 16    

A cache block is 16*16=256 pixels for miplevel0.    
A cache block is  8* 8= 64 pixels for miplevel1.
A cache block is  4* 4= 16 pixels for miplevel2.
A cache block is  2* 2=  4 pixels for miplevel3.
        
}
}