Annotation of quake1/vid_vga.c, revision 1.1.1.2

1.1       root        1: //
                      2: // vid_vga.c: VGA-specific DOS video stuff
                      3: //
                      4: 
                      5: // TODO: proper handling of page-swap failure
                      6: 
                      7: #include <dos.h>
                      8: 
                      9: #include "quakedef.h"
                     10: #include "d_local.h"
                     11: #include "dosisms.h"
                     12: #include "vid_dos.h"
                     13: #include <dpmi.h>
                     14: 
                     15: extern regs_t regs;
                     16: 
                     17: int            VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes;
                     18: byte   *VGA_pagebase;
                     19: vmode_t        *VGA_pcurmode;
                     20: 
                     21: static int             VGA_planar;
                     22: static int             VGA_numpages;
                     23: static int             VGA_buffersize;
                     24: 
                     25: void   *vid_surfcache;
                     26: int            vid_surfcachesize;
                     27: 
                     28: int            VGA_highhunkmark;
                     29: 
                     30: #include "vgamodes.h"
                     31: 
                     32: #define NUMVIDMODES            (sizeof(vgavidmodes) / sizeof(vgavidmodes[0]))
                     33: 
                     34: void VGA_UpdatePlanarScreen (void *srcbuffer);
                     35: 
                     36: static byte    backingbuf[48*24];
                     37: 
                     38: /*
                     39: ================
                     40: VGA_BeginDirectRect
                     41: ================
                     42: */
                     43: void VGA_BeginDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode, int x,
                     44:        int y, byte *pbitmap, int width, int height)
                     45: {
                     46:        int             i, j, k, plane, reps, repshift;
                     47: 
1.1.1.2 ! root       48:        if (!lvid->direct)
        !            49:                return;
        !            50: 
1.1       root       51:        if (lvid->aspect > 1.5)
                     52:        {
                     53:                reps = 2;
                     54:                repshift = 1;
                     55:        }
                     56:        else
                     57:        {
                     58:                reps = 1;
                     59:                repshift = 0;
                     60:        }
                     61: 
                     62:        if (pcurrentmode->planar)
                     63:        {
                     64:                for (plane=0 ; plane<4 ; plane++)
                     65:                {
                     66:                // select the correct plane for reading and writing
                     67:                        outportb (SC_INDEX, MAP_MASK);
                     68:                        outportb (SC_DATA, 1 << plane);
                     69:                        outportb (GC_INDEX, READ_MAP);
                     70:                        outportb (GC_DATA, plane);
                     71: 
                     72:                        for (i=0 ; i<(height << repshift) ; i += reps)
                     73:                        {
                     74:                                for (k=0 ; k<reps ; k++)
                     75:                                {
                     76:                                        for (j=0 ; j<(width >> 2) ; j++)
                     77:                                        {
                     78:                                                backingbuf[(i + k) * 24 + (j << 2) + plane] =
                     79:                                                                lvid->direct[(y + i + k) * VGA_rowbytes +
                     80:                                                                (x >> 2) + j];
                     81:                                                lvid->direct[(y + i + k) * VGA_rowbytes + (x>>2) + j] =
                     82:                                                                pbitmap[(i >> repshift) * 24 +
                     83:                                                                (j << 2) + plane];
                     84:                                        }
                     85:                                }
                     86:                        }
                     87:                }
                     88:        }
                     89:        else
                     90:        {
                     91:                for (i=0 ; i<(height << repshift) ; i += reps)
                     92:                {
                     93:                        for (j=0 ; j<reps ; j++)
                     94:                        {
                     95:                                memcpy (&backingbuf[(i + j) * 24],
                     96:                                                lvid->direct + x + ((y << repshift) + i + j) *
                     97:                                                 VGA_rowbytes,
                     98:                                                width);
                     99:                                memcpy (lvid->direct + x + ((y << repshift) + i + j) *
                    100:                                                 VGA_rowbytes,
                    101:                                                &pbitmap[(i >> repshift) * width],
                    102:                                                width);
                    103:                        }
                    104:                }
                    105:        }
                    106: }
                    107: 
                    108: 
                    109: /*
                    110: ================
                    111: VGA_EndDirectRect
                    112: ================
                    113: */
                    114: void VGA_EndDirectRect (viddef_t *lvid, struct vmode_s *pcurrentmode, int x,
                    115:        int y, int width, int height)
                    116: {
                    117:        int             i, j, k, plane, reps, repshift;
                    118: 
1.1.1.2 ! root      119:        if (!lvid->direct)
        !           120:                return;
        !           121: 
1.1       root      122:        if (lvid->aspect > 1.5)
                    123:        {
                    124:                reps = 2;
                    125:                repshift = 1;
                    126:        }
                    127:        else
                    128:        {
                    129:                reps = 1;
                    130:                repshift = 0;
                    131:        }
                    132: 
                    133:        if (pcurrentmode->planar)
                    134:        {
                    135:                for (plane=0 ; plane<4 ; plane++)
                    136:                {
                    137:                // select the correct plane for writing
                    138:                        outportb (SC_INDEX, MAP_MASK);
                    139:                        outportb (SC_DATA, 1 << plane);
                    140: 
                    141:                        for (i=0 ; i<(height << repshift) ; i += reps)
                    142:                        {
                    143:                                for (k=0 ; k<reps ; k++)
                    144:                                {
                    145:                                        for (j=0 ; j<(width >> 2) ; j++)
                    146:                                        {
                    147:                                                lvid->direct[(y + i + k) * VGA_rowbytes + (x>>2) + j] =
                    148:                                                                backingbuf[(i + k) * 24 + (j << 2) + plane];
                    149:                                        }
                    150:                                }
                    151:                        }
                    152:                }
                    153:        }
                    154:        else
                    155:        {
                    156:                for (i=0 ; i<(height << repshift) ; i += reps)
                    157:                {
                    158:                        for (j=0 ; j<reps ; j++)
                    159:                        {
                    160:                                memcpy (lvid->direct + x + ((y << repshift) + i + j) *
                    161:                                                 VGA_rowbytes,
                    162:                                                &backingbuf[(i + j) * 24],
                    163:                                                width);
                    164:                        }
                    165:                }
                    166:        }
                    167: }
                    168: 
                    169: 
                    170: /*
                    171: ================
                    172: VGA_Init
                    173: ================
                    174: */
                    175: void VGA_Init (void)
                    176: {
                    177:        int             i;
                    178: 
                    179: // link together all the VGA modes
                    180:        for (i=0 ; i<(NUMVIDMODES - 1) ; i++)
                    181:        {
                    182:                vgavidmodes[i].pnext = &vgavidmodes[i+1];
                    183:        }
                    184: 
                    185: // add the VGA modes at the start of the mode list
                    186:        vgavidmodes[NUMVIDMODES-1].pnext = pvidmodes;
                    187:        pvidmodes = &vgavidmodes[0];
                    188: 
                    189:        numvidmodes += NUMVIDMODES;
                    190: }
                    191: 
                    192: 
                    193: /*
                    194: ================
                    195: VGA_WaitVsync
                    196: ================
                    197: */
                    198: void VGA_WaitVsync (void)
                    199: {
                    200:        while ((inportb (0x3DA) & 0x08) == 0)
                    201:                ;
                    202: }
                    203: 
                    204: 
                    205: /*
                    206: ================
                    207: VGA_ClearVideoMem
                    208: ================
                    209: */
                    210: void VGA_ClearVideoMem (int planar)
                    211: {
                    212: 
                    213:        if (planar)
                    214:        {
                    215:        // enable all planes for writing
                    216:                outportb (SC_INDEX, MAP_MASK);
                    217:                outportb (SC_DATA, 0x0F);
                    218:        }
                    219: 
                    220:        Q_memset (VGA_pagebase, 0, VGA_rowbytes * VGA_height);
                    221: }
                    222: 
                    223: /*
                    224: ================
                    225: VGA_FreeAndAllocVidbuffer
                    226: ================
                    227: */
                    228: qboolean VGA_FreeAndAllocVidbuffer (viddef_t *lvid, int allocnewbuffer)
                    229: {
                    230:        int             tsize, tbuffersize;
                    231: 
                    232:        if (allocnewbuffer)
                    233:        {
                    234:        // alloc an extra line in case we want to wrap, and allocate the z-buffer
                    235:                tbuffersize = (lvid->rowbytes * (lvid->height + 1)) +
                    236:                                (lvid->width * lvid->height * sizeof (*d_pzbuffer));
                    237:        }
                    238:        else
                    239:        {
                    240:        // just allocate the z-buffer
                    241:                tbuffersize = lvid->width * lvid->height * sizeof (*d_pzbuffer);
                    242:        }
                    243: 
                    244:        tsize = D_SurfaceCacheForRes (lvid->width, lvid->height);
                    245: 
                    246:        tbuffersize += tsize;
                    247: 
                    248: // see if there's enough memory, allowing for the normal mode 0x13 pixel,
                    249: // z, and surface buffers
                    250:        if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 +
1.1.1.2 ! root      251:                 0x10000 * 3) < minimum_memory)
1.1       root      252:        {
                    253:                Con_Printf ("Not enough memory for video mode\n");
                    254:                VGA_pcurmode = NULL;    // so no further accesses to the buffer are
                    255:                                                                //  attempted, particularly when clearing
                    256:                return false;           // not enough memory for mode
                    257:        }
                    258: 
                    259:        VGA_buffersize = tbuffersize;
                    260:        vid_surfcachesize = tsize;
                    261: 
                    262:        if (d_pzbuffer)
                    263:        {
                    264:                D_FlushCaches ();
                    265:                Hunk_FreeToHighMark (VGA_highhunkmark);
                    266:                d_pzbuffer = NULL;
                    267:        }
                    268: 
                    269:        VGA_highhunkmark = Hunk_HighMark ();
                    270: 
                    271:        d_pzbuffer = Hunk_HighAllocName (VGA_buffersize, "video");
                    272: 
                    273:        vid_surfcache = (byte *)d_pzbuffer
                    274:                + lvid->width * lvid->height * sizeof (*d_pzbuffer);
                    275:        
                    276:        if (allocnewbuffer)
                    277:        {
                    278:                lvid->buffer = (void *)( (byte *)vid_surfcache + vid_surfcachesize);
                    279:                lvid->conbuffer = lvid->buffer;
                    280:        }
                    281: 
                    282:        return true;
                    283: }
                    284: 
                    285: 
                    286: /*
                    287: ================
                    288: VGA_CheckAdequateMem
                    289: ================
                    290: */
                    291: qboolean VGA_CheckAdequateMem (int width, int height, int rowbytes,
                    292:        int allocnewbuffer)
                    293: {
                    294:        int             tbuffersize;
                    295: 
                    296:        tbuffersize = width * height * sizeof (*d_pzbuffer);
                    297: 
                    298:        if (allocnewbuffer)
                    299:        {
                    300:        // alloc an extra line in case we want to wrap, and allocate the z-buffer
                    301:                tbuffersize += (rowbytes * (height + 1));
                    302:        }
                    303: 
                    304:        tbuffersize += D_SurfaceCacheForRes (width, height);
                    305: 
                    306: // see if there's enough memory, allowing for the normal mode 0x13 pixel,
                    307: // z, and surface buffers
                    308:        if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 +
1.1.1.2 ! root      309:                 0x10000 * 3) < minimum_memory)
1.1       root      310:        {
                    311:                return false;           // not enough memory for mode
                    312:        }
                    313: 
                    314:        return true;
                    315: }
                    316: 
                    317: 
                    318: /*
                    319: ================
                    320: VGA_InitMode
                    321: ================
                    322: */
                    323: int VGA_InitMode (viddef_t *lvid, vmode_t *pcurrentmode)
                    324: {
                    325:        vextra_t                *pextra;
                    326: 
                    327:        pextra = pcurrentmode->pextradata;
                    328: 
                    329:        if (!VGA_FreeAndAllocVidbuffer (lvid, pextra->vidbuffer))
                    330:                return -1;      // memory alloc failed
                    331: 
                    332:        if (VGA_pcurmode)
                    333:                VGA_ClearVideoMem (VGA_pcurmode->planar);
                    334: 
                    335: // mode 0x13 is the base for all the Mode X-class mode sets
                    336:        regs.h.ah = 0;
                    337:        regs.h.al = 0x13;
                    338:        dos_int86(0x10);
                    339: 
                    340:        VGA_pagebase = (void *)real2ptr(0xa0000);
                    341:        lvid->direct = (pixel_t *)VGA_pagebase;
                    342: 
                    343: // set additional registers as needed
                    344:        VideoRegisterSet (pextra->pregset);
                    345: 
                    346:        VGA_numpages = 1;
                    347:        lvid->numpages = VGA_numpages;
                    348: 
                    349:        VGA_width = (lvid->width + 0x1F) & ~0x1F;
                    350:        VGA_height = lvid->height;
                    351:        VGA_planar = pcurrentmode->planar;
                    352:        if (VGA_planar)
                    353:                VGA_rowbytes = lvid->rowbytes / 4;
                    354:        else
                    355:                VGA_rowbytes = lvid->rowbytes;
                    356:        VGA_bufferrowbytes = lvid->rowbytes;
                    357:        lvid->colormap = host_colormap;
                    358:        lvid->fullbright = 256 - LittleLong (*((int *)lvid->colormap + 2048));
                    359: 
                    360:        lvid->maxwarpwidth = WARP_WIDTH;
                    361:        lvid->maxwarpheight = WARP_HEIGHT;
                    362: 
                    363:        lvid->conbuffer = lvid->buffer;
                    364:        lvid->conrowbytes = lvid->rowbytes;
                    365:        lvid->conwidth = lvid->width;
                    366:        lvid->conheight = lvid->height;
                    367: 
                    368:        VGA_pcurmode = pcurrentmode;
                    369: 
                    370:        VGA_ClearVideoMem (pcurrentmode->planar);
                    371: 
                    372:        if (_vid_wait_override.value)
                    373:        {
                    374:                Cvar_SetValue ("vid_wait", (float)VID_WAIT_VSYNC);
                    375:        }
                    376:        else
                    377:        {
                    378:                Cvar_SetValue ("vid_wait", (float)VID_WAIT_NONE);
                    379:        }
                    380: 
                    381:        D_InitCaches (vid_surfcache, vid_surfcachesize);
                    382: 
                    383:        return 1;
                    384: }
                    385: 
                    386: 
                    387: /*
                    388: ================
                    389: VGA_SetPalette
                    390: ================
                    391: */
                    392: void VGA_SetPalette(viddef_t *lvid, vmode_t *pcurrentmode, unsigned char *pal)
                    393: {
                    394:        int shiftcomponents=2;
                    395:        int i;
                    396: 
                    397:        UNUSED(lvid);
                    398:        UNUSED(pcurrentmode);
                    399: 
                    400:        dos_outportb(0x3c8, 0);
                    401:        for (i=0 ; i<768 ; i++)
                    402:                outportb(0x3c9, pal[i]>>shiftcomponents);
                    403: }
                    404: 
                    405: 
                    406: /*
                    407: ================
                    408: VGA_SwapBuffersCopy
                    409: ================
                    410: */
                    411: void VGA_SwapBuffersCopy (viddef_t *lvid, vmode_t *pcurrentmode,
                    412:        vrect_t *rects)
                    413: {
                    414: 
                    415:        UNUSED(pcurrentmode);
                    416: 
                    417: // TODO: can write a dword at a time
                    418: // TODO: put in ASM
                    419: // TODO: copy only specified rectangles
                    420:        if (VGA_planar)
                    421:        {
                    422: 
                    423:        // TODO: copy only specified rectangles
                    424: 
                    425:                VGA_UpdatePlanarScreen (lvid->buffer);
                    426:        }
                    427:        else
                    428:        {
                    429:                while (rects)
                    430:                {
                    431:                        VGA_UpdateLinearScreen (
                    432:                                        lvid->buffer + rects->x + (rects->y * lvid->rowbytes),
                    433:                                        VGA_pagebase + rects->x + (rects->y * VGA_rowbytes),
                    434:                                        rects->width,
                    435:                                        rects->height,
                    436:                                        lvid->rowbytes,
                    437:                                        VGA_rowbytes);
                    438: 
                    439:                        rects = rects->pnext;
                    440:                }
                    441:        }
                    442: }
                    443: 
                    444: 
                    445: /*
                    446: ================
                    447: VGA_SwapBuffers
                    448: ================
                    449: */
                    450: void VGA_SwapBuffers (viddef_t *lvid, vmode_t *pcurrentmode, vrect_t *rects)
                    451: {
                    452:        UNUSED(lvid);
                    453: 
                    454:        if (vid_wait.value == VID_WAIT_VSYNC)
                    455:                VGA_WaitVsync ();
                    456: 
                    457:        VGA_SwapBuffersCopy (lvid, pcurrentmode, rects);
                    458: }
                    459: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.