Annotation of quake1/vid_vga.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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