// draw.c -- this is the only file outside the refresh that touches the// vid buffer #include "quakedef.h" typedef struct { vrect_t rect; int width; int height; uint8_t *ptexbytes; int rowbytes;} rectdesc_t; static rectdesc_t r_rectdesc; uint8_t *draw_chars; // 8*8 graphic charactersqpic_t *draw_disc;qpic_t *draw_backtile; //=============================================================================/* Support Routines */ typedef struct cachepic_s{ char name[MAX_QPATH]; cache_user_t cache;} cachepic_t; #define MAX_CACHED_PICS 128cachepic_t menu_cachepics[MAX_CACHED_PICS];int menu_numcachepics; qpic_t *Draw_PicFromWad (char *name){ return W_GetLumpName (name);} /*================Draw_CachePic================*/qpic_t *Draw_CachePic (char *path){ cachepic_t *pic; int i; qpic_t *dat; for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++) if (!strcmp (path, pic->name)) break; if (i == menu_numcachepics) { if (menu_numcachepics == MAX_CACHED_PICS) Sys_Error ("menu_numcachepics == MAX_CACHED_PICS"); menu_numcachepics++; strcpy (pic->name, path); } dat = Cache_Check (&pic->cache); if (dat) return dat; //// load the pic from disk// COM_LoadCacheFile (path, &pic->cache); dat = (qpic_t *)pic->cache.data; if (!dat) { Sys_Error ("Draw_CachePic: failed to load %s", path); } SwapPic (dat); return dat;} /*===============Draw_Init===============*/void Draw_Init (void){ draw_chars = W_GetLumpName ("conchars"); draw_disc = W_GetLumpName ("disc"); draw_backtile = W_GetLumpName ("backtile"); r_rectdesc.width = draw_backtile->width; r_rectdesc.height = draw_backtile->height; r_rectdesc.ptexbytes = draw_backtile->data; r_rectdesc.rowbytes = draw_backtile->width;} /*================Draw_Character Draws one 8*8 graphics character with 0 being transparent.It can be clipped to the top of the screen to allow the console to besmoothly scrolled off.================*/void Draw_Character (int x, int y, int num){ uint8_t *dest; uint8_t *source; unsigned short *pusdest; int drawline; int row, col; num &= 255; if (y <= -8) return; // totally off screen #ifdef PARANOID if (y > vid.height - 8 || x < 0 || x > vid.width - 8) Sys_Error ("Con_DrawCharacter: (%i, %i)", x, y); if (num < 0 || num > 255) Sys_Error ("Con_DrawCharacter: char %i", num);#endif row = num>>4; col = num&15; source = draw_chars + (row<<10) + (col<<3); if (y < 0) { // clipped drawline = 8 + y; source -= 128*y; y = 0; } else drawline = 8; if (r_pixbytes == 1) { dest = vid.conbuffer + y*vid.conrowbytes + x; while (drawline--) { if (source[0]) dest[0] = source[0]; if (source[1]) dest[1] = source[1]; if (source[2]) dest[2] = source[2]; if (source[3]) dest[3] = source[3]; if (source[4]) dest[4] = source[4]; if (source[5]) dest[5] = source[5]; if (source[6]) dest[6] = source[6]; if (source[7]) dest[7] = source[7]; source += 128; dest += vid.conrowbytes; } } else { // FIXME: pre-expand to native format? pusdest = (unsigned short *) ((uint8_t *)vid.conbuffer + y*vid.conrowbytes + (x<<1)); while (drawline--) { if (source[0]) pusdest[0] = d_8to16table[source[0]]; if (source[1]) pusdest[1] = d_8to16table[source[1]]; if (source[2]) pusdest[2] = d_8to16table[source[2]]; if (source[3]) pusdest[3] = d_8to16table[source[3]]; if (source[4]) pusdest[4] = d_8to16table[source[4]]; if (source[5]) pusdest[5] = d_8to16table[source[5]]; if (source[6]) pusdest[6] = d_8to16table[source[6]]; if (source[7]) pusdest[7] = d_8to16table[source[7]]; source += 128; pusdest += (vid.conrowbytes >> 1); } }} /*================Draw_String================*/void Draw_String (int x, int y, char *str){ while (*str) { Draw_Character (x, y, *str); str++; x += 8; }} /*================Draw_DebugChar Draws a single character directly to the upper right corner of the screen.This is for debugging lockups by drawing different chars in different partsof the code.================*/void Draw_DebugChar (char num){ uint8_t *dest; uint8_t *source; int drawline; extern uint8_t *draw_chars; int row, col; if (!vid.direct) return; // don't have direct FB access, so no debugchars... drawline = 8; row = num>>4; col = num&15; source = draw_chars + (row<<10) + (col<<3); dest = vid.direct + 312; while (drawline--) { dest[0] = source[0]; dest[1] = source[1]; dest[2] = source[2]; dest[3] = source[3]; dest[4] = source[4]; dest[5] = source[5]; dest[6] = source[6]; dest[7] = source[7]; source += 128; dest += 320; }} /*=============Draw_Pic=============*/void Draw_Pic (int x, int y, qpic_t *pic){ uint8_t *dest, *source; unsigned short *pusdest; int v, u; if ((x < 0) || (x + pic->width > vid.width) || (y < 0) || (y + pic->height > vid.height)) { Sys_Error ("Draw_Pic: bad coordinates"); } source = pic->data; if (r_pixbytes == 1) { dest = vid.buffer + y * vid.rowbytes + x; for (v=0 ; v<pic->height ; v++) { memmove (dest, source, pic->width); dest += vid.rowbytes; source += pic->width; } } else { // FIXME: pretranslate at load time? pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x; for (v=0 ; v<pic->height ; v++) { for (u=0 ; u<pic->width ; u++) { pusdest[u] = d_8to16table[source[u]]; } pusdest += vid.rowbytes >> 1; source += pic->width; } }} /*=============Draw_TransPic=============*/void Draw_TransPic (int x, int y, qpic_t *pic){ uint8_t *dest, *source, tbyte; unsigned short *pusdest; int v, u; if (x < 0 || (x + pic->width) > vid.width || y < 0 || (y + pic->height) > vid.height) { Sys_Error ("Draw_TransPic: bad coordinates"); } source = pic->data; if (r_pixbytes == 1) { dest = vid.buffer + y * vid.rowbytes + x; if (pic->width & 7) { // general for (v=0 ; v<pic->height ; v++) { for (u=0 ; u<pic->width ; u++) if ( (tbyte=source[u]) != TRANSPARENT_COLOR) dest[u] = tbyte; dest += vid.rowbytes; source += pic->width; } } else { // unwound for (v=0 ; v<pic->height ; v++) { for (u=0 ; u<pic->width ; u+=8) { if ( (tbyte=source[u]) != TRANSPARENT_COLOR) dest[u] = tbyte; if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR) dest[u+1] = tbyte; if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR) dest[u+2] = tbyte; if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR) dest[u+3] = tbyte; if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR) dest[u+4] = tbyte; if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR) dest[u+5] = tbyte; if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR) dest[u+6] = tbyte; if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR) dest[u+7] = tbyte; } dest += vid.rowbytes; source += pic->width; } } } else { // FIXME: pretranslate at load time? pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x; for (v=0 ; v<pic->height ; v++) { for (u=0 ; u<pic->width ; u++) { tbyte = source[u]; if (tbyte != TRANSPARENT_COLOR) { pusdest[u] = d_8to16table[tbyte]; } } pusdest += vid.rowbytes >> 1; source += pic->width; } }} /*=============Draw_TransPicTranslate=============*/void Draw_TransPicTranslate (int x, int y, qpic_t *pic, uint8_t *translation){ uint8_t *dest, *source, tbyte; unsigned short *pusdest; int v, u; if (x < 0 || (x + pic->width) > vid.width || y < 0 || (y + pic->height) > vid.height) { Sys_Error ("Draw_TransPic: bad coordinates"); } source = pic->data; if (r_pixbytes == 1) { dest = vid.buffer + y * vid.rowbytes + x; if (pic->width & 7) { // general for (v=0 ; v<pic->height ; v++) { for (u=0 ; u<pic->width ; u++) if ( (tbyte=source[u]) != TRANSPARENT_COLOR) dest[u] = translation[tbyte]; dest += vid.rowbytes; source += pic->width; } } else { // unwound for (v=0 ; v<pic->height ; v++) { for (u=0 ; u<pic->width ; u+=8) { if ( (tbyte=source[u]) != TRANSPARENT_COLOR) dest[u] = translation[tbyte]; if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR) dest[u+1] = translation[tbyte]; if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR) dest[u+2] = translation[tbyte]; if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR) dest[u+3] = translation[tbyte]; if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR) dest[u+4] = translation[tbyte]; if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR) dest[u+5] = translation[tbyte]; if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR) dest[u+6] = translation[tbyte]; if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR) dest[u+7] = translation[tbyte]; } dest += vid.rowbytes; source += pic->width; } } } else { // FIXME: pretranslate at load time? pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x; for (v=0 ; v<pic->height ; v++) { for (u=0 ; u<pic->width ; u++) { tbyte = source[u]; if (tbyte != TRANSPARENT_COLOR) { pusdest[u] = d_8to16table[tbyte]; } } pusdest += vid.rowbytes >> 1; source += pic->width; } }} void Draw_CharToConback (int num, uint8_t *dest){ int row, col; uint8_t *source; int drawline; int x; row = num>>4; col = num&15; source = draw_chars + (row<<10) + (col<<3); drawline = 8; while (drawline--) { for (x=0 ; x<8 ; x++) if (source[x]) dest[x] = 0x60 + source[x]; source += 128; dest += 320; } } /*Lines 1–500 of 849. Load more
// draw.c -- this is the only file outside the refresh that touches the // vid buffer #include "quakedef.h" typedef struct { vrect_t rect; int width; int height; uint8_t *ptexbytes; int rowbytes; } rectdesc_t; static rectdesc_t r_rectdesc; uint8_t *draw_chars; // 8*8 graphic characters qpic_t *draw_disc; qpic_t *draw_backtile; //============================================================================= /* Support Routines */ typedef struct cachepic_s { char name[MAX_QPATH]; cache_user_t cache; } cachepic_t; #define MAX_CACHED_PICS 128 cachepic_t menu_cachepics[MAX_CACHED_PICS]; int menu_numcachepics; qpic_t *Draw_PicFromWad (char *name) { return W_GetLumpName (name); } /* ================ Draw_CachePic ================ */ qpic_t *Draw_CachePic (char *path) { cachepic_t *pic; int i; qpic_t *dat; for (pic=menu_cachepics, i=0 ; i<menu_numcachepics ; pic++, i++) if (!strcmp (path, pic->name)) break; if (i == menu_numcachepics) { if (menu_numcachepics == MAX_CACHED_PICS) Sys_Error ("menu_numcachepics == MAX_CACHED_PICS"); menu_numcachepics++; strcpy (pic->name, path); } dat = Cache_Check (&pic->cache); if (dat) return dat; // // load the pic from disk // COM_LoadCacheFile (path, &pic->cache); dat = (qpic_t *)pic->cache.data; if (!dat) { Sys_Error ("Draw_CachePic: failed to load %s", path); } SwapPic (dat); return dat; } /* =============== Draw_Init =============== */ void Draw_Init (void) { draw_chars = W_GetLumpName ("conchars"); draw_disc = W_GetLumpName ("disc"); draw_backtile = W_GetLumpName ("backtile"); r_rectdesc.width = draw_backtile->width; r_rectdesc.height = draw_backtile->height; r_rectdesc.ptexbytes = draw_backtile->data; r_rectdesc.rowbytes = draw_backtile->width; } /* ================ Draw_Character Draws one 8*8 graphics character with 0 being transparent. It can be clipped to the top of the screen to allow the console to be smoothly scrolled off. ================ */ void Draw_Character (int x, int y, int num) { uint8_t *dest; uint8_t *source; unsigned short *pusdest; int drawline; int row, col; num &= 255; if (y <= -8) return; // totally off screen #ifdef PARANOID if (y > vid.height - 8 || x < 0 || x > vid.width - 8) Sys_Error ("Con_DrawCharacter: (%i, %i)", x, y); if (num < 0 || num > 255) Sys_Error ("Con_DrawCharacter: char %i", num); #endif row = num>>4; col = num&15; source = draw_chars + (row<<10) + (col<<3); if (y < 0) { // clipped drawline = 8 + y; source -= 128*y; y = 0; } else drawline = 8; if (r_pixbytes == 1) { dest = vid.conbuffer + y*vid.conrowbytes + x; while (drawline--) { if (source[0]) dest[0] = source[0]; if (source[1]) dest[1] = source[1]; if (source[2]) dest[2] = source[2]; if (source[3]) dest[3] = source[3]; if (source[4]) dest[4] = source[4]; if (source[5]) dest[5] = source[5]; if (source[6]) dest[6] = source[6]; if (source[7]) dest[7] = source[7]; source += 128; dest += vid.conrowbytes; } } else { // FIXME: pre-expand to native format? pusdest = (unsigned short *) ((uint8_t *)vid.conbuffer + y*vid.conrowbytes + (x<<1)); while (drawline--) { if (source[0]) pusdest[0] = d_8to16table[source[0]]; if (source[1]) pusdest[1] = d_8to16table[source[1]]; if (source[2]) pusdest[2] = d_8to16table[source[2]]; if (source[3]) pusdest[3] = d_8to16table[source[3]]; if (source[4]) pusdest[4] = d_8to16table[source[4]]; if (source[5]) pusdest[5] = d_8to16table[source[5]]; if (source[6]) pusdest[6] = d_8to16table[source[6]]; if (source[7]) pusdest[7] = d_8to16table[source[7]]; source += 128; pusdest += (vid.conrowbytes >> 1); } } } /* ================ Draw_String ================ */ void Draw_String (int x, int y, char *str) { while (*str) { Draw_Character (x, y, *str); str++; x += 8; } } /* ================ Draw_DebugChar Draws a single character directly to the upper right corner of the screen. This is for debugging lockups by drawing different chars in different parts of the code. ================ */ void Draw_DebugChar (char num) { uint8_t *dest; uint8_t *source; int drawline; extern uint8_t *draw_chars; int row, col; if (!vid.direct) return; // don't have direct FB access, so no debugchars... drawline = 8; row = num>>4; col = num&15; source = draw_chars + (row<<10) + (col<<3); dest = vid.direct + 312; while (drawline--) { dest[0] = source[0]; dest[1] = source[1]; dest[2] = source[2]; dest[3] = source[3]; dest[4] = source[4]; dest[5] = source[5]; dest[6] = source[6]; dest[7] = source[7]; source += 128; dest += 320; } } /* ============= Draw_Pic ============= */ void Draw_Pic (int x, int y, qpic_t *pic) { uint8_t *dest, *source; unsigned short *pusdest; int v, u; if ((x < 0) || (x + pic->width > vid.width) || (y < 0) || (y + pic->height > vid.height)) { Sys_Error ("Draw_Pic: bad coordinates"); } source = pic->data; if (r_pixbytes == 1) { dest = vid.buffer + y * vid.rowbytes + x; for (v=0 ; v<pic->height ; v++) { memmove (dest, source, pic->width); dest += vid.rowbytes; source += pic->width; } } else { // FIXME: pretranslate at load time? pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x; for (v=0 ; v<pic->height ; v++) { for (u=0 ; u<pic->width ; u++) { pusdest[u] = d_8to16table[source[u]]; } pusdest += vid.rowbytes >> 1; source += pic->width; } } } /* ============= Draw_TransPic ============= */ void Draw_TransPic (int x, int y, qpic_t *pic) { uint8_t *dest, *source, tbyte; unsigned short *pusdest; int v, u; if (x < 0 || (x + pic->width) > vid.width || y < 0 || (y + pic->height) > vid.height) { Sys_Error ("Draw_TransPic: bad coordinates"); } source = pic->data; if (r_pixbytes == 1) { dest = vid.buffer + y * vid.rowbytes + x; if (pic->width & 7) { // general for (v=0 ; v<pic->height ; v++) { for (u=0 ; u<pic->width ; u++) if ( (tbyte=source[u]) != TRANSPARENT_COLOR) dest[u] = tbyte; dest += vid.rowbytes; source += pic->width; } } else { // unwound for (v=0 ; v<pic->height ; v++) { for (u=0 ; u<pic->width ; u+=8) { if ( (tbyte=source[u]) != TRANSPARENT_COLOR) dest[u] = tbyte; if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR) dest[u+1] = tbyte; if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR) dest[u+2] = tbyte; if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR) dest[u+3] = tbyte; if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR) dest[u+4] = tbyte; if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR) dest[u+5] = tbyte; if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR) dest[u+6] = tbyte; if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR) dest[u+7] = tbyte; } dest += vid.rowbytes; source += pic->width; } } } else { // FIXME: pretranslate at load time? pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x; for (v=0 ; v<pic->height ; v++) { for (u=0 ; u<pic->width ; u++) { tbyte = source[u]; if (tbyte != TRANSPARENT_COLOR) { pusdest[u] = d_8to16table[tbyte]; } } pusdest += vid.rowbytes >> 1; source += pic->width; } } } /* ============= Draw_TransPicTranslate ============= */ void Draw_TransPicTranslate (int x, int y, qpic_t *pic, uint8_t *translation) { uint8_t *dest, *source, tbyte; unsigned short *pusdest; int v, u; if (x < 0 || (x + pic->width) > vid.width || y < 0 || (y + pic->height) > vid.height) { Sys_Error ("Draw_TransPic: bad coordinates"); } source = pic->data; if (r_pixbytes == 1) { dest = vid.buffer + y * vid.rowbytes + x; if (pic->width & 7) { // general for (v=0 ; v<pic->height ; v++) { for (u=0 ; u<pic->width ; u++) if ( (tbyte=source[u]) != TRANSPARENT_COLOR) dest[u] = translation[tbyte]; dest += vid.rowbytes; source += pic->width; } } else { // unwound for (v=0 ; v<pic->height ; v++) { for (u=0 ; u<pic->width ; u+=8) { if ( (tbyte=source[u]) != TRANSPARENT_COLOR) dest[u] = translation[tbyte]; if ( (tbyte=source[u+1]) != TRANSPARENT_COLOR) dest[u+1] = translation[tbyte]; if ( (tbyte=source[u+2]) != TRANSPARENT_COLOR) dest[u+2] = translation[tbyte]; if ( (tbyte=source[u+3]) != TRANSPARENT_COLOR) dest[u+3] = translation[tbyte]; if ( (tbyte=source[u+4]) != TRANSPARENT_COLOR) dest[u+4] = translation[tbyte]; if ( (tbyte=source[u+5]) != TRANSPARENT_COLOR) dest[u+5] = translation[tbyte]; if ( (tbyte=source[u+6]) != TRANSPARENT_COLOR) dest[u+6] = translation[tbyte]; if ( (tbyte=source[u+7]) != TRANSPARENT_COLOR) dest[u+7] = translation[tbyte]; } dest += vid.rowbytes; source += pic->width; } } } else { // FIXME: pretranslate at load time? pusdest = (unsigned short *)vid.buffer + y * (vid.rowbytes >> 1) + x; for (v=0 ; v<pic->height ; v++) { for (u=0 ; u<pic->width ; u++) { tbyte = source[u]; if (tbyte != TRANSPARENT_COLOR) { pusdest[u] = d_8to16table[tbyte]; } } pusdest += vid.rowbytes >> 1; source += pic->width; } } } void Draw_CharToConback (int num, uint8_t *dest) { int row, col; uint8_t *source; int drawline; int x; row = num>>4; col = num&15; source = draw_chars + (row<<10) + (col<<3); drawline = 8; while (drawline--) { for (x=0 ; x<8 ; x++) if (source[x]) dest[x] = 0x60 + source[x]; source += 128; dest += 320; } } /*