Annotation of quake1/vid_vga.c, revision 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.