/* sprite.cpp - Don Yang (uguu.org) Assume DirectDraw initialized before calling initializing sprites. Assume sprite buffers are orientated vertically, such that delta between sprite scanlines is zero. Assume no direct color images. Assume CELL_SIZE == w_tiles == (h_tiles / 6). 12/21/00 */ #include"global.h" #include"images.h" #include"main.h" #include"sprite.h" #include"spritefx.h" enum { SPRITE_LABEL0, SPRITE_LABEL1, SPRITE_LABEL2, SPRITE_LABEL3, SPRITE_TILE, SPRITE_TILE_G, SPRITE_TILE_R, SPRITE_NUMBERS, SPRITE_TITLE, SPRITE_FONT, SPRITE_COUNT }; static int Sbpp = 0; static DWORD FontOffset[256]; static BYTE Palette[4 * 256]; static BYTE *SprImg[SPRITE_COUNT]; static BOOL ReinitSprites = FALSE; static int CharIndex[256] = { // Depends on font.bmp 59,59,59,59, 59,59,59,59, 59,36,36,36, 59,36,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 36,38,65,40, 41,42,44,64, 46,47,45,53, 54,50,55,58, 26,27,28,29, 30,31,32,33, 34,35,63,62, 56,51,57,59, 39, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, 15,16,17,18, 19,20,21,22, 23,24,25,48, 60,49,43,52, 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, 15,16,17,18, 19,20,21,22, 23,24,25,48, 61,49,37,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59, 59,59,59,59 }; static void (*DrawSprite)(BYTE *src, BYTE *dst, int width, int height); static void (*TDrawSprite)(BYTE *src, BYTE *dst, int width, int height); static void ConvertPalette15(unsigned char src[][3], int size); static void ConvertPalette16(unsigned char src[][3], int size); static void ConvertPalette24(unsigned char src[][3], int size); static void ConvertPalette32(unsigned char src[][3], int size); static void DrawSprite16(BYTE *src, BYTE *dst, int width, int height); static void DrawSprite24(BYTE *src, BYTE *dst, int width, int height); static void DrawSprite32(BYTE *src, BYTE *dst, int width, int height); static void GeneratePalette15(int r0, int g0, int b0, int r1, int g1, int b1); static void GeneratePalette16(int r0, int g0, int b0, int r1, int g1, int b1); static void GeneratePalette24(int r0, int g0, int b0, int r1, int g1, int b1); static void GeneratePalette32(int r0, int g0, int b0, int r1, int g1, int b1); static void RenderSprite16(BYTE *src, BYTE *dst, BYTE *pal, int psize); static void RenderSprite24(BYTE *src, BYTE *dst, BYTE *pal, int psize); static void RenderSprite32(BYTE *src, BYTE *dst, BYTE *pal, int psize); /**************************************************************** DrawLabel1 Draw time label. */ void DrawLabel1(DWORD screen) { TDrawSprite( SprImg[SPRITE_LABEL1], (BYTE*)(screen + TIME_LABEL_Y * DDPitch + TIME_LABEL_X * Sbpp), w_label1, h_label1); } // DrawLabel1() /**************************************************************** DrawLabel2 Draw level label. */ void DrawLabel2(DWORD screen) { TDrawSprite( SprImg[SPRITE_LABEL2], (BYTE*)(screen + LEVEL_LABEL_Y * DDPitch + LEVEL_LABEL_X * Sbpp), w_label2, h_label2); } // DrawLabel2() /**************************************************************** DrawLabel3 Draw score label. */ void DrawLabel3(DWORD screen) { TDrawSprite( SprImg[SPRITE_LABEL3], (BYTE*)(screen + SCORE_LABEL_Y * DDPitch + SCORE_LABEL_X * Sbpp), w_label3, h_label3); } // DrawLabel3() /**************************************************************** DrawNumber Draw decimal number. */ void DrawNumber(DWORD screen, int x, int y, int number, int length) { char string[16]; int i; sprintf(string, "%0*d",length, number); for(i = 0; i < length; i++) { TDrawSprite( (BYTE*)(SprImg[SPRITE_NUMBERS] + (string[i] - '0') * (s_numbers / 11) * Sbpp), (BYTE*)(screen + y * DDPitch + (x + i * w_numbers) * Sbpp), w_numbers, h_numbers / 11); } } // DrawNumber() /****************************************************************** DrawText Draw string. */ void DrawText(DWORD screen, int x, int y, char *text) { DWORD x0, dx; int i; x0 = screen + y * DDPitch + x * Sbpp; dx = w_font * Sbpp; for(i = 0; text[i]; i++) { if( text[i] != '\t' ) { TDrawSprite( (BYTE*)(SprImg[SPRITE_FONT] + FontOffset[(BYTE)(text[i])]), (BYTE*)x0, w_font, h_font / FONT_CHAR_COUNT); } x0 += dx; } } // DrawText() /****************************************************************** DrawTile Draw tile (at grid coordinates). */ void DrawTile(DWORD screen, int c, int r, int tile, int color) { TDrawSprite( (BYTE*)(SprImg[SPRITE_TILE + color] + (tile - 1) * (CELL_SIZE * CELL_SIZE) * Sbpp), (BYTE*)(screen + SpriteOffset[c][r]), CELL_SIZE, CELL_SIZE); } // DrawTile() /****************************************************************** DrawTime Draw elapsed time. */ void DrawTime(DWORD screen) { char string[8]; int i, o; sprintf(string, "%02d:%02d", (CurrentPlayer.data[HISTORY_TIME] / ExpectedFPS) / 60, (CurrentPlayer.data[HISTORY_TIME] / ExpectedFPS) % 60); o = TIME_LABEL_Y * DDPitch + (TIME_LABEL_X + w_label1 + 7) * Sbpp; for(i = 0; i < 5; i++) { if( i == 2 ) { TDrawSprite( (BYTE*)(SprImg[SPRITE_NUMBERS] + 10 * (s_numbers / 11) * Sbpp), (BYTE*)(screen + o + 2 * w_numbers * Sbpp), w_numbers, h_numbers / 11); } else { TDrawSprite( (BYTE*)(SprImg[SPRITE_NUMBERS] + (string[i] - '0') * (s_numbers / 11) * Sbpp), (BYTE*)(screen + o + (i * w_numbers) * Sbpp), w_numbers, h_numbers / 11); } } } // DrawTime() /***************************************************************** DrawTitle Draw title image. */ void DrawTitle(DWORD screen) { DrawSprite( SprImg[SPRITE_TITLE], (BYTE*)(screen + ((APP_HEIGHT - h_title) / 2) * DDPitch + ((APP_WIDTH - w_title) / 2) * Sbpp), w_title, h_title); } // DrawTitle() /************************************************************* DrawWaitLabel Draw "press any key" message. */ void DrawWaitLabel(DWORD screen) { TDrawSprite( SprImg[SPRITE_LABEL0], (BYTE*)(screen + (APP_HEIGHT - GRID_MARGIN - h_label0) * DDPitch + ((APP_WIDTH - w_label0) / 2) * Sbpp), w_label0, h_label0); } // DrawWaitLabel() /************************************************************* InitSprites15 Convert grayscale sprites for use with current pixel format. */ BOOL InitSprites15(void) { int c, r, x, y; DrawSprite = DrawSprite16; TDrawSprite = DrawSprite16; Sbpp = 2; // Allocate if( ReinitSprites ) { UninitSprites(); } else { for(x = 0; x < SPRITE_COUNT; SprImg[x++] = NULL); ReinitSprites = TRUE; } if( (SprImg[SPRITE_LABEL0] = (BYTE*)Malloc(s_label0 * 2)) == NULL || (SprImg[SPRITE_LABEL1] = (BYTE*)Malloc(s_label1 * 2)) == NULL || (SprImg[SPRITE_LABEL2] = (BYTE*)Malloc(s_label2 * 2)) == NULL || (SprImg[SPRITE_LABEL3] = (BYTE*)Malloc(s_label3 * 2)) == NULL || (SprImg[SPRITE_NUMBERS] = (BYTE*)Malloc(s_numbers * 2)) == NULL || (SprImg[SPRITE_TITLE] = (BYTE*)Malloc(s_title * 2)) == NULL || (SprImg[SPRITE_TILE] = (BYTE*)Malloc(s_tiles * 2)) == NULL || (SprImg[SPRITE_TILE_R] = (BYTE*)Malloc(s_tiles * 2)) == NULL || (SprImg[SPRITE_TILE_G] = (BYTE*)Malloc(s_tiles * 2)) == NULL || (SprImg[SPRITE_FONT] = (BYTE*)Malloc(s_font * 2)) == NULL ) return Croak("Not enough memory."); // (main.cpp) // Paletted sprites ConvertPalette15(p_title, c_title); RenderSprite16(i_title, SprImg[SPRITE_TITLE], Palette, s_title); // Grayscale -> grayscale GeneratePalette15(0, 0, 0, 28, 28, 31); RenderSprite16(i_label0, SprImg[SPRITE_LABEL0], Palette, s_label0); RenderSprite16(i_label1, SprImg[SPRITE_LABEL1], Palette, s_label1); RenderSprite16(i_label2, SprImg[SPRITE_LABEL2], Palette, s_label2); RenderSprite16(i_label3, SprImg[SPRITE_LABEL3], Palette, s_label3); RenderSprite16(i_numbers, SprImg[SPRITE_NUMBERS], Palette, s_numbers); RenderSprite16(i_tiles, SprImg[SPRITE_TILE], Palette, s_tiles); RenderSprite16(i_font, SprImg[SPRITE_FONT], Palette, s_font); // Grayscale -> green GeneratePalette15(0, 24, 0, 28, 28, 31); RenderSprite16(i_tiles, SprImg[SPRITE_TILE_G], Palette, s_tiles); // Grayscale -> red GeneratePalette15(31, 0, 0, 28, 28, 31); RenderSprite16(i_tiles, SprImg[SPRITE_TILE_R], Palette, s_tiles); // Set offsets for(c = 0; c < GRID_WIDTH; c++) { x = c * CELL_SIZE + GRID_MARGIN; for(r = 0; r <= GRID_HEIGHT; r++) { y = (APP_HEIGHT - GRID_MARGIN - CELL_SIZE) - r * CELL_SIZE; SpriteOffset[c][r] = y * DDPitch + x * 2; } } for(c = 0; c < 256; c++) FontOffset[c] = CharIndex[c] * (s_font / FONT_CHAR_COUNT) * 2; // Postprocess if( (GameOptions & OPTION_SPR) != OPTION_SPR_MODE0 ) { PostProcess15(SprImg[SPRITE_TILE], i_tiles, s_tiles); // (spritefx.cpp) PostProcess15(SprImg[SPRITE_TILE_G], i_tiles, s_tiles); PostProcess15(SprImg[SPRITE_TILE_R], i_tiles, s_tiles); PostProcess15(SprImg[SPRITE_LABEL0], i_label0, s_label0); PostProcess15(SprImg[SPRITE_LABEL1], i_label1, s_label1); PostProcess15(SprImg[SPRITE_LABEL2], i_label2, s_label2); PostProcess15(SprImg[SPRITE_LABEL3], i_label3, s_label3); PostProcess15(SprImg[SPRITE_NUMBERS], i_numbers, s_numbers); PostProcess15(SprImg[SPRITE_FONT], i_font, s_font); if( (GameOptions & OPTION_SPR) == OPTION_SPR_MODE1 ) TDrawSprite = TDrawSprite16_1; // (spritefx.cpp) else if( (GameOptions & OPTION_SPR) == OPTION_SPR_MODE2 ) TDrawSprite = TDrawSprite15_2; // (spritefx.cpp) else TDrawSprite = TDrawSprite15_3; // (spritefx.cpp) } return TRUE; } // InitSprites15() /************************************************************* InitSprites16 Convert grayscale sprites for use with current pixel format. */ BOOL InitSprites16(void) { int c, r, x, y; DrawSprite = DrawSprite16; TDrawSprite = DrawSprite16; Sbpp = 2; // Allocate if( ReinitSprites ) { UninitSprites(); } else { for(x = 0; x < SPRITE_COUNT; SprImg[x++] = NULL); ReinitSprites = TRUE; } if( (SprImg[SPRITE_LABEL0] = (BYTE*)Malloc(s_label0 * 2)) == NULL || (SprImg[SPRITE_LABEL1] = (BYTE*)Malloc(s_label1 * 2)) == NULL || (SprImg[SPRITE_LABEL2] = (BYTE*)Malloc(s_label2 * 2)) == NULL || (SprImg[SPRITE_LABEL3] = (BYTE*)Malloc(s_label3 * 2)) == NULL || (SprImg[SPRITE_NUMBERS] = (BYTE*)Malloc(s_numbers * 2)) == NULL || (SprImg[SPRITE_TITLE] = (BYTE*)Malloc(s_title * 2)) == NULL || (SprImg[SPRITE_TILE] = (BYTE*)Malloc(s_tiles * 2)) == NULL || (SprImg[SPRITE_TILE_R] = (BYTE*)Malloc(s_tiles * 2)) == NULL || (SprImg[SPRITE_TILE_G] = (BYTE*)Malloc(s_tiles * 2)) == NULL || (SprImg[SPRITE_FONT] = (BYTE*)Malloc(s_font * 2)) == NULL ) return Croak("Not enough memory."); // (main.cpp) // Paletted sprites ConvertPalette16(p_title, c_title); RenderSprite16(i_title, SprImg[SPRITE_TITLE], Palette, s_title); // Grayscale -> grayscale GeneratePalette16(0, 0, 0, 28, 57, 31); RenderSprite16(i_label0, SprImg[SPRITE_LABEL0], Palette, s_label0); RenderSprite16(i_label1, SprImg[SPRITE_LABEL1], Palette, s_label1); RenderSprite16(i_label2, SprImg[SPRITE_LABEL2], Palette, s_label2); RenderSprite16(i_label3, SprImg[SPRITE_LABEL3], Palette, s_label3); RenderSprite16(i_numbers, SprImg[SPRITE_NUMBERS], Palette, s_numbers); RenderSprite16(i_tiles, SprImg[SPRITE_TILE], Palette, s_tiles); RenderSprite16(i_font, SprImg[SPRITE_FONT], Palette, s_font); // Grayscale -> green GeneratePalette16(0, 48, 0, 28, 57, 31); RenderSprite16(i_tiles, SprImg[SPRITE_TILE_G], Palette, s_tiles); // Grayscale -> red GeneratePalette16(31, 0, 0, 28, 57, 31); RenderSprite16(i_tiles, SprImg[SPRITE_TILE_R], Palette, s_tiles); // Set offsets for(c = 0; c < GRID_WIDTH; c++) { x = c * CELL_SIZE + GRID_MARGIN; for(r = 0; r <= GRID_HEIGHT; r++) { y = (APP_HEIGHT - GRID_MARGIN - CELL_SIZE) - r * CELL_SIZE; SpriteOffset[c][r] = y * DDPitch + x * 2; } } for(c = 0; c < 256; c++) FontOffset[c] = CharIndex[c] * (s_font / FONT_CHAR_COUNT) * 2; // Postprocess if( (GameOptions & OPTION_SPR) != OPTION_SPR_MODE0 ) { PostProcess16(SprImg[SPRITE_TILE], i_tiles, s_tiles); // (spritefx.cpp) PostProcess16(SprImg[SPRITE_TILE_G], i_tiles, s_tiles); PostProcess16(SprImg[SPRITE_TILE_R], i_tiles, s_tiles); PostProcess16(SprImg[SPRITE_LABEL0], i_label0, s_label0); PostProcess16(SprImg[SPRITE_LABEL1], i_label1, s_label1); PostProcess16(SprImg[SPRITE_LABEL2], i_label2, s_label2); PostProcess16(SprImg[SPRITE_LABEL3], i_label3, s_label3); PostProcess16(SprImg[SPRITE_NUMBERS], i_numbers, s_numbers); PostProcess16(SprImg[SPRITE_FONT], i_font, s_font); if( (GameOptions & OPTION_SPR) == OPTION_SPR_MODE1 ) TDrawSprite = TDrawSprite16_1; // (spritefx.cpp) else if( (GameOptions & OPTION_SPR) == OPTION_SPR_MODE2 ) TDrawSprite = TDrawSprite16_2; // (spritefx.cpp) else TDrawSprite = TDrawSprite16_3; // (spritefx.cpp) } return TRUE; } // InitSprites16() /************************************************************* InitSprites24 Convert grayscale sprites for use with current pixel format. */ BOOL InitSprites24(void) { int c, r, x, y; DrawSprite = DrawSprite24; TDrawSprite = DrawSprite24; Sbpp = 3; // Allocate if( ReinitSprites ) { UninitSprites(); } else { for(x = 0; x < SPRITE_COUNT; SprImg[x++] = NULL); ReinitSprites = TRUE; } if( (SprImg[SPRITE_LABEL0] = (BYTE*)Malloc(s_label0 * 3)) == NULL || (SprImg[SPRITE_LABEL1] = (BYTE*)Malloc(s_label1 * 3)) == NULL || (SprImg[SPRITE_LABEL2] = (BYTE*)Malloc(s_label2 * 3)) == NULL || (SprImg[SPRITE_LABEL3] = (BYTE*)Malloc(s_label3 * 3)) == NULL || (SprImg[SPRITE_NUMBERS] = (BYTE*)Malloc(s_numbers * 3)) == NULL || (SprImg[SPRITE_TITLE] = (BYTE*)Malloc(s_title * 3)) == NULL || (SprImg[SPRITE_TILE] = (BYTE*)Malloc(s_tiles * 3)) == NULL || (SprImg[SPRITE_TILE_R] = (BYTE*)Malloc(s_tiles * 3)) == NULL || (SprImg[SPRITE_TILE_G] = (BYTE*)Malloc(s_tiles * 3)) == NULL || (SprImg[SPRITE_FONT] = (BYTE*)Malloc(s_font * 3)) == NULL ) return Croak("Not enough memory."); // (main.cpp) // Paletted sprites ConvertPalette24(p_title, c_title); RenderSprite24(i_title, SprImg[SPRITE_TITLE], Palette, s_title); // Grayscale -> grayscale GeneratePalette24(0, 0, 0, 231, 231, 255); RenderSprite24(i_label0, SprImg[SPRITE_LABEL0], Palette, s_label0); RenderSprite24(i_label1, SprImg[SPRITE_LABEL1], Palette, s_label1); RenderSprite24(i_label2, SprImg[SPRITE_LABEL2], Palette, s_label2); RenderSprite24(i_label3, SprImg[SPRITE_LABEL3], Palette, s_label3); RenderSprite24(i_numbers, SprImg[SPRITE_NUMBERS], Palette, s_numbers); RenderSprite24(i_tiles, SprImg[SPRITE_TILE], Palette, s_tiles); RenderSprite24(i_font, SprImg[SPRITE_FONT], Palette, s_font); // Grayscale -> green GeneratePalette24(0, 192, 0, 231, 231, 255); RenderSprite24(i_tiles, SprImg[SPRITE_TILE_G], Palette, s_tiles); // Grayscale -> red GeneratePalette24(255, 0, 0, 231, 231, 255); RenderSprite24(i_tiles, SprImg[SPRITE_TILE_R], Palette, s_tiles); // Set offsets for(c = 0; c < GRID_WIDTH; c++) { x = c * CELL_SIZE + GRID_MARGIN; for(r = 0; r <= GRID_HEIGHT; r++) { y = (APP_HEIGHT - GRID_MARGIN - CELL_SIZE) - r * CELL_SIZE; SpriteOffset[c][r] = y * DDPitch + x * 3; } } for(c = 0; c < 256; c++) FontOffset[c] = CharIndex[c] * (s_font / FONT_CHAR_COUNT) * 3; // Postprocess if( (GameOptions & OPTION_SPR) != OPTION_SPR_MODE0 ) { PostProcess24(SprImg[SPRITE_TILE], i_tiles, s_tiles); // (spritefx.cpp) PostProcess24(SprImg[SPRITE_TILE_G], i_tiles, s_tiles); PostProcess24(SprImg[SPRITE_TILE_R], i_tiles, s_tiles); PostProcess24(SprImg[SPRITE_LABEL0], i_label0, s_label0); PostProcess24(SprImg[SPRITE_LABEL1], i_label1, s_label1); PostProcess24(SprImg[SPRITE_LABEL2], i_label2, s_label2); PostProcess24(SprImg[SPRITE_LABEL3], i_label3, s_label3); PostProcess24(SprImg[SPRITE_NUMBERS], i_numbers, s_numbers); PostProcess24(SprImg[SPRITE_FONT], i_font, s_font); if( (GameOptions & OPTION_SPR) == OPTION_SPR_MODE1 ) TDrawSprite = TDrawSprite24_1; // (spritefx.cpp) else if( (GameOptions & OPTION_SPR) == OPTION_SPR_MODE2 ) TDrawSprite = TDrawSprite24_2; // (spritefx.cpp) else TDrawSprite = TDrawSprite24_3; // (spritefx.cpp) } return TRUE; } // InitSprites24() /************************************************************* InitSprites32 Convert grayscale sprites for use with current pixel format. */ BOOL InitSprites32(void) { int c, r, x, y; DrawSprite = DrawSprite32; TDrawSprite = DrawSprite32; Sbpp = 4; // Allocate if( ReinitSprites ) { UninitSprites(); } else { for(x = 0; x < SPRITE_COUNT; SprImg[x++] = NULL); ReinitSprites = TRUE; } if( (SprImg[SPRITE_LABEL0] = (BYTE*)Malloc(s_label0 * 4)) == NULL || (SprImg[SPRITE_LABEL1] = (BYTE*)Malloc(s_label1 * 4)) == NULL || (SprImg[SPRITE_LABEL2] = (BYTE*)Malloc(s_label2 * 4)) == NULL || (SprImg[SPRITE_LABEL3] = (BYTE*)Malloc(s_label3 * 4)) == NULL || (SprImg[SPRITE_NUMBERS] = (BYTE*)Malloc(s_numbers * 4)) == NULL || (SprImg[SPRITE_TITLE] = (BYTE*)Malloc(s_title * 4)) == NULL || (SprImg[SPRITE_TILE] = (BYTE*)Malloc(s_tiles * 4)) == NULL || (SprImg[SPRITE_TILE_R] = (BYTE*)Malloc(s_tiles * 4)) == NULL || (SprImg[SPRITE_TILE_G] = (BYTE*)Malloc(s_tiles * 4)) == NULL || (SprImg[SPRITE_FONT] = (BYTE*)Malloc(s_font * 4)) == NULL ) return Croak("Not enough memory."); // (main.cpp) // Paletted sprites ConvertPalette32(p_title, c_title); RenderSprite32(i_title, SprImg[SPRITE_TITLE], Palette, s_title); // Grayscale -> grayscale GeneratePalette32(0, 0, 0, 231, 231, 255); RenderSprite32(i_label0, SprImg[SPRITE_LABEL0], Palette, s_label0); RenderSprite32(i_label1, SprImg[SPRITE_LABEL1], Palette, s_label1); RenderSprite32(i_label2, SprImg[SPRITE_LABEL2], Palette, s_label2); RenderSprite32(i_label3, SprImg[SPRITE_LABEL3], Palette, s_label3); RenderSprite32(i_numbers, SprImg[SPRITE_NUMBERS], Palette, s_numbers); RenderSprite32(i_tiles, SprImg[SPRITE_TILE], Palette, s_tiles); RenderSprite32(i_font, SprImg[SPRITE_FONT], Palette, s_font); // Grayscale -> green GeneratePalette32(0, 192, 0, 231, 231, 255); RenderSprite32(i_tiles, SprImg[SPRITE_TILE_G], Palette, s_tiles); // Grayscale -> red GeneratePalette32(255, 0, 0, 231, 231, 255); RenderSprite32(i_tiles, SprImg[SPRITE_TILE_R], Palette, s_tiles); // Set offsets for(c = 0; c < GRID_WIDTH; c++) { x = c * CELL_SIZE + GRID_MARGIN; for(r = 0; r <= GRID_HEIGHT; r++) { y = (APP_HEIGHT - GRID_MARGIN - CELL_SIZE) - r * CELL_SIZE; SpriteOffset[c][r] = y * DDPitch + x * 4; } } for(c = 0; c < 256; c++) FontOffset[c] = CharIndex[c] * (s_font / FONT_CHAR_COUNT) * 4; // Postprocess if( (GameOptions & OPTION_SPR) != OPTION_SPR_MODE0 ) { PostProcess32(SprImg[SPRITE_TILE], i_tiles, s_tiles); // (spritefx.cpp) PostProcess32(SprImg[SPRITE_TILE_G], i_tiles, s_tiles); PostProcess32(SprImg[SPRITE_TILE_R], i_tiles, s_tiles); PostProcess32(SprImg[SPRITE_LABEL0], i_label0, s_label0); PostProcess32(SprImg[SPRITE_LABEL1], i_label1, s_label1); PostProcess32(SprImg[SPRITE_LABEL2], i_label2, s_label2); PostProcess32(SprImg[SPRITE_LABEL3], i_label3, s_label3); PostProcess32(SprImg[SPRITE_NUMBERS], i_numbers, s_numbers); PostProcess32(SprImg[SPRITE_FONT], i_font, s_font); if( (GameOptions & OPTION_SPR) == OPTION_SPR_MODE1 ) TDrawSprite = TDrawSprite32_1; // (spritefx.cpp) else if( (GameOptions & OPTION_SPR) == OPTION_SPR_MODE2 ) TDrawSprite = TDrawSprite32_2; // (spritefx.cpp) else TDrawSprite = TDrawSprite32_3; // (spritefx.cpp) } return TRUE; } // InitSprites32() /************************************************************* UninitSprites Release sprite buffers. */ void UninitSprites(void) { int i; for(i = 0; i < SPRITE_COUNT; i++) { if( SprImg[i] != NULL ) { Free(SprImg[i]); SprImg[i] = NULL; } } } // UninitSprites() /********************************************************** ConvertPalette15 Load 8:8:8 palette to memory. */ static void ConvertPalette15(unsigned char src[][3], int size) { WORD entry; int i; for(i = 0; i < size; i++) { entry = (WORD) ( (((unsigned int)src[i][0] & 0xf8) << 7) | (((unsigned int)src[i][1] & 0xf8) << 2) | ( (unsigned int)src[i][2] >> 3) ); Palette[i * 2] = (BYTE)(entry & 0xff); Palette[i * 2 + 1] = (BYTE)(entry >> 8); } } // ConvertPalette15() /********************************************************** ConvertPalette16 Load 8:8:8 palette to memory. */ static void ConvertPalette16(unsigned char src[][3], int size) { WORD entry; int i; for(i = 0; i < size; i++) { entry = (WORD) ( (((unsigned int)src[i][0] & 0xf8) << 8) | (((unsigned int)src[i][1] & 0xfc) << 3) | ( (unsigned int)src[i][2] >> 3) ); Palette[i * 2] = (BYTE)(entry & 0xff); Palette[i * 2 + 1] = (BYTE)(entry >> 8); } } // ConvertPalette16() /********************************************************** ConvertPalette24 Load 8:8:8 palette to memory. */ static void ConvertPalette24(unsigned char src[][3], int size) { int i; for(i = 0; i < size; i++) { Palette[i * 3] = src[i][2]; // B Palette[i * 3 + 1] = src[i][1]; // G Palette[i * 3 + 2] = src[i][0]; // R } } // ConvertPalette24() /********************************************************** ConvertPalette32 Load 8:8:8 palette to memory. */ static void ConvertPalette32(unsigned char src[][3], int size) { int i; for(i = 0; i < size; i++) { Palette[i * 4] = src[i][2]; // B Palette[i * 4 + 1] = src[i][1]; // G Palette[i * 4 + 2] = src[i][0]; // R } } // ConvertPalette32() /************************************************************** DrawSprite16 Copy sprite from memory to screen buffer. */ void DrawSprite16(BYTE *src, BYTE *dst, int width, int height) { __asm { pushf cld mov esi, src mov edi, dst mov ebx, height mov eax, width shl eax, 1 mov edx, DDPitch sub edx, eax ; EDX = offset between scanlines DrawSprite16_loop: mov ecx, width rep movsw add edi, edx dec ebx jnz DrawSprite16_loop popf } } // DrawSprite16() /************************************************************** DrawSprite24 Copy sprite from memory to screen buffer. */ void DrawSprite24(BYTE *src, BYTE *dst, int width, int height) { __asm { pushf cld mov esi, src mov edi, dst mov ebx, height mov eax, width mov edx, DDPitch sub edx, eax shl eax, 1 sub edx, eax ; EDX = delta between screen scanlines DrawSprite24_loop: mov ecx, width rep movsw mov ecx, width rep movsb add edi, edx dec ebx jnz DrawSprite24_loop popf } } // DrawSprite24() /************************************************************** DrawSprite32 Copy sprite from memory to screen buffer. */ void DrawSprite32(BYTE *src, BYTE *dst, int width, int height) { __asm { pushf cld mov esi, src mov edi, dst mov ebx, height mov eax, width shl eax, 2 mov edx, DDPitch sub edx, eax ; EDX = offset between scanlines DrawSprite32_loop: mov ecx, width rep movsd add edi, edx dec ebx jnz DrawSprite32_loop popf } } // DrawSprite32() /********************************************************* GeneratePalette15 Generate color ramp. */ static void GeneratePalette15(int r0, int g0, int b0, int r1, int g1, int b1) { WORD entry; int i, r, g, b; if( GameOptions & OPTION_SPR_TRANSPARENT ) { entry = (WORD)((r0 << 10) | (g0 << 5) | b0); for(i = 0; i < TRANSPARENT_THRESHOLD; i++) { Palette[i * 2] = (BYTE)(entry & 0xff); Palette[i * 2 + 1] = (BYTE)(entry >> 8); } entry = (WORD)((r1 << 10) | (g1 << 5) | b1); for(; i < 256; i++) { Palette[i * 2] = (BYTE)(entry & 0xff); Palette[i * 2 + 1] = (BYTE)(entry >> 8); } } else { for(i = 0; i < 256; i++) { r = (i * (r1 - r0)) / 255 + r0; g = (i * (g1 - g0)) / 255 + g0; b = (i * (b1 - b0)) / 255 + b0; entry = (WORD)((r << 10) | (g << 5) | b); Palette[i * 2] = (BYTE)(entry & 0xff); Palette[i * 2 + 1] = (BYTE)(entry >> 8); } } } // GeneratePalette15() /********************************************************* GeneratePalette16 Generate color ramp. */ static void GeneratePalette16(int r0, int g0, int b0, int r1, int g1, int b1) { WORD entry; int i, r, g, b; if( GameOptions & OPTION_SPR_TRANSPARENT ) { entry = (WORD)((r0 << 11) | (g0 << 5) | b0); for(i = 0; i < TRANSPARENT_THRESHOLD; i++) { Palette[i * 2] = (BYTE)(entry & 0xff); Palette[i * 2 + 1] = (BYTE)(entry >> 8); } entry = (WORD)((r1 << 11) | (g1 << 5) | b1); for(; i < 256; i++) { Palette[i * 2] = (BYTE)(entry & 0xff); Palette[i * 2 + 1] = (BYTE)(entry >> 8); } } else { for(i = 0; i < 256; i++) { r = (i * (r1 - r0)) / 255 + r0; g = (i * (g1 - g0)) / 255 + g0; b = (i * (b1 - b0)) / 255 + b0; entry = (WORD)((r << 11) | (g << 5) | b); Palette[i * 2] = (BYTE)(entry & 0xff); Palette[i * 2 + 1] = (BYTE)(entry >> 8); } } } // GeneratePalette16() /********************************************************* GeneratePalette24 Generate color ramp. */ static void GeneratePalette24(int r0, int g0, int b0, int r1, int g1, int b1) { int i; if( GameOptions & OPTION_SPR_TRANSPARENT ) { for(i = 0; i < TRANSPARENT_THRESHOLD; i++) { Palette[i * 3 + 2] = (BYTE)r0; Palette[i * 3 + 1] = (BYTE)g0; Palette[i * 3] = (BYTE)b0; } for(; i < 256; i++) { Palette[i * 3 + 2] = (BYTE)r1; Palette[i * 3 + 1] = (BYTE)g1; Palette[i * 3] = (BYTE)b1; } } else { for(i = 0; i < 256; i++) { Palette[i * 3 + 2] = (BYTE)((i * (r1 - r0)) / 255 + r0); Palette[i * 3 + 1] = (BYTE)((i * (g1 - g0)) / 255 + g0); Palette[i * 3] = (BYTE)((i * (b1 - b0)) / 255 + b0); } } } // GeneratePalette24() /********************************************************* GeneratePalette32 Generate color ramp. */ static void GeneratePalette32(int r0, int g0, int b0, int r1, int g1, int b1) { int i; if( GameOptions & OPTION_SPR_TRANSPARENT ) { for(i = 0; i < TRANSPARENT_THRESHOLD; i++) { Palette[i * 4 + 2] = (BYTE)r0; Palette[i * 4 + 1] = (BYTE)g0; Palette[i * 4] = (BYTE)b0; } for(; i < 256; i++) { Palette[i * 4 + 2] = (BYTE)r1; Palette[i * 4 + 1] = (BYTE)g1; Palette[i * 4] = (BYTE)b1; } } else { for(i = 0; i < 256; i++) { Palette[i * 4 + 2] = (BYTE)((i * (r1 - r0)) / 255 + r0); Palette[i * 4 + 1] = (BYTE)((i * (g1 - g0)) / 255 + g0); Palette[i * 4] = (BYTE)((i * (b1 - b0)) / 255 + b0); } } } // GeneratePalette32() /************************************************************ RenderSprite16 Convert grayscale sprite to 5:6:5 format. */ static void RenderSprite16(BYTE *src, BYTE *dst, BYTE *pal, int psize) { __asm { pushf cld mov esi, src mov edi, dst mov ebx, pal mov ecx, psize RenderSprite16_loop: movzx edx, byte ptr [esi] inc esi shl edx, 1 mov ax, word ptr [ebx+edx] stosw loop RenderSprite16_loop popf } } // RenderSprite16() /************************************************************ RenderSprite24 Convert grayscale sprite to 8:8:8 format. */ static void RenderSprite24(BYTE *src, BYTE *dst, BYTE *pal, int psize) { __asm { pushf cld mov esi, src mov edi, dst xor eax, eax mov ebx, pal mov ecx, psize RenderSprite24_loop: lodsb mov edx, eax shl edx, 1 add edx, eax ; EDX = 3 * AL mov al, byte ptr [ebx+edx] stosb mov al, byte ptr [ebx+edx+1] stosb mov al, byte ptr [ebx+edx+2] stosb loop RenderSprite24_loop popf } } // RenderSprite24() /************************************************************ RenderSprite32 Convert grayscale sprite to 8:8:8 format. */ static void RenderSprite32(BYTE *src, BYTE *dst, BYTE *pal, int psize) { __asm { pushf cld mov esi, src mov edi, dst xor eax, eax mov ebx, pal mov ecx, psize RenderSprite32_loop: lodsb movzx edx, al shl edx, 2 mov eax, dword ptr [ebx+edx] stosd loop RenderSprite32_loop popf } } // RenderSprite32() char *SpriteObjTime = __TIME__ " " __DATE__; int SpriteObjLines = __LINE__;