/* bg.cpp - Don Yang (uguu.org) Assume hicolor / truecolor. Assume screen width is multiple of 4. Assume cell width is multiple of 4. 12/21/00 */ #include"global.h" #include"bg.h" #include"bgfx.h" #include"main.h" static void (*RenderBGfx)(DWORD screen); static void (*RenderBGfxA)(DWORD screen, int x, int y, int w, int h); static void (*RenderBGfxP)(DWORD screen, int c, int r); static void FillBackground15(DWORD screen); static void FillBackground16(DWORD screen); static void FillBackground24(DWORD screen); static void FillBackground32(DWORD screen); static void PaintBackground16(DWORD screen); static void PaintBackground24(DWORD screen); static void PaintBackground32(DWORD screen); static void RenderBackground15(void); static void RenderBackground16(void); static void RenderBackground24(void); static void RenderBackground32(void); static void RefillBackground15(DWORD screen, int c, int r); static void RefillBackground15a(DWORD screen, int x, int y, int w, int h); static void RefillBackground16(DWORD screen, int c, int r); static void RefillBackground16a(DWORD screen, int x, int y, int w, int h); static void RepaintBackground16(DWORD screen, int c, int r); static void RepaintBackground16a(DWORD screen, int x, int y, int w, int h); static void RefillBackground24(DWORD screen, int c, int r); static void RefillBackground24a(DWORD screen, int x, int y, int w, int h); static void RepaintBackground24(DWORD screen, int c, int r); static void RepaintBackground24a(DWORD screen, int x, int y, int w, int h); static void RefillBackground32(DWORD screen, int c, int r); static void RefillBackground32a(DWORD screen, int x, int y, int w, int h); static void RepaintBackground32(DWORD screen, int c, int r); static void RepaintBackground32a(DWORD screen, int x, int y, int w, int h); static void VMirror16(void); static void VMirror24(void); static void VMirror32(void); /************************************************************* CaptureScreen Capture desktop to memory. */ BOOL CaptureScreen(void) { HBITMAP bitmap, tmp_bitmap; BITMAP bmp; BITMAPINFO bmp_info; HDC screen_dc, mem_dc; MSG msg; // Delete old background image (for recapturing desktops) ReleaseBackground(); BGImage = NULL; // Get screen dimensions screen_dc = CreateDC("DISPLAY", NULL, NULL, NULL); mem_dc = CreateCompatibleDC(screen_dc); ScreenWidth = GetDeviceCaps(screen_dc, HORZRES); ScreenHeight = GetDeviceCaps(screen_dc, VERTRES); // Wait for everyone to repaint while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0 ) { TranslateMessage(&msg); DispatchMessage(&msg); } Sleep(1000); // Capture bitmap = CreateCompatibleBitmap(screen_dc, ScreenWidth, ScreenHeight); tmp_bitmap = (HBITMAP)SelectObject(mem_dc, bitmap); BitBlt(mem_dc, 0, 0, ScreenWidth, ScreenHeight, screen_dc, 0, 0, SRCCOPY); bitmap = (HBITMAP)SelectObject(mem_dc, tmp_bitmap); // Dump DIB to memory GetObject(bitmap, sizeof(BITMAP), &bmp); bmp_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmp_info.bmiHeader.biWidth = bmp.bmWidth; bmp_info.bmiHeader.biHeight = bmp.bmHeight; bmp_info.bmiHeader.biPlanes = bmp.bmPlanes; bmp_info.bmiHeader.biBitCount = bmp.bmBitsPixel; bmp_info.bmiHeader.biXPelsPerMeter = 0xb12; bmp_info.bmiHeader.biYPelsPerMeter = 0xb12; bmp_info.bmiHeader.biClrUsed = 0; bmp_info.bmiHeader.biClrImportant = 0; bmp_info.bmiHeader.biCompression = 0; bmp_info.bmiHeader.biSizeImage = bmp.bmWidth * bmp.bmHeight * bmp.bmBitsPixel / 8; if( (BGImage = (BYTE *)Malloc(bmp_info.bmiHeader.biSizeImage)) == NULL ) { DeleteDC(mem_dc); DeleteDC(screen_dc); return Croak("Not enough memory."); // (main.cpp) } GetDIBits(mem_dc, bitmap, 0, bmp.bmHeight, BGImage, &bmp_info, DIB_RGB_COLORS); // Success DeleteDC(mem_dc); DeleteDC(screen_dc); return RedrawAll = TRUE; } // CaptureScreen() /********************************************************** InitBackground15 Select background functions. */ void InitBackground15(void) { // Background rendering/drawing functions RenderBackground = RenderBackground15; if( GameOptions & OPTION_BG_BACKGROUND ) { PaintBackground = PaintBackground16; RepaintBackground = RepaintBackground16; RepaintBackgroundA = RepaintBackground16a; } else { PaintBackground = FillBackground15; RepaintBackground = RefillBackground15; RepaintBackgroundA = RefillBackground15a; } // Particle rendering functions if( GameOptions & OPTION_BG_WHITE_PARTICLE ) { RenderBGfx = WRenderParticle15; // (bgfx.cpp) RenderBGfxA = WRenderParticle15a; // (bgfx.cpp) RenderBGfxP = WRenderParticle15p; // (bgfx.cpp) } else { RenderBGfx = RenderParticle16; // (bgfx.cpp) RenderBGfxA = RenderParticle16a; // (bgfx.cpp) RenderBGfxP = RenderParticle16p; // (bgfx.cpp) } // Particle animation/initialization functions switch( GameOptions & OPTION_BG_FX ) { case OPTION_BG_FRACTAL: InitFractal(); // (bgfx.cpp) AnimateBackground = AnimateFractal; // (bgfx.cpp) break; case OPTION_BG_DUST: InitDust(); // (bgfx.cpp) AnimateBackground = AnimateDust; // (bgfx.cpp) break; case OPTION_BG_SWARM: InitSwarm(); // (bgfx.cpp) AnimateBackground = AnimateSwarm; // (bgfx.cpp) break; default: AnimateBackground = NullFunc; // (global.cpp) break; } } // InitBackground15() /********************************************************** InitBackground16 Select background functions. */ void InitBackground16(void) { // Background rendering/drawing functions RenderBackground = RenderBackground16; if( GameOptions & OPTION_BG_BACKGROUND ) { PaintBackground = PaintBackground16; RepaintBackground = RepaintBackground16; RepaintBackgroundA = RepaintBackground16a; } else { PaintBackground = FillBackground16; RepaintBackground = RefillBackground16; RepaintBackgroundA = RefillBackground16a; } // Particle rendering functions if( GameOptions & OPTION_BG_WHITE_PARTICLE ) { RenderBGfx = WRenderParticle16; // (bgfx.cpp) RenderBGfxA = WRenderParticle16a; // (bgfx.cpp) RenderBGfxP = WRenderParticle16p; // (bgfx.cpp) } else { RenderBGfx = RenderParticle16; // (bgfx.cpp) RenderBGfxA = RenderParticle16a; // (bgfx.cpp) RenderBGfxP = RenderParticle16p; // (bgfx.cpp) } // Particle animation/initialization functions switch( GameOptions & OPTION_BG_FX ) { case OPTION_BG_FRACTAL: InitFractal(); // (bgfx.cpp) AnimateBackground = AnimateFractal; // (bgfx.cpp) break; case OPTION_BG_DUST: InitDust(); // (bgfx.cpp) AnimateBackground = AnimateDust; // (bgfx.cpp) break; case OPTION_BG_SWARM: InitSwarm(); // (bgfx.cpp) AnimateBackground = AnimateSwarm; // (bgfx.cpp) break; default: AnimateBackground = NullFunc; // (global.cpp) break; } } // InitBackground16() /********************************************************** InitBackground24 Select background functions. */ void InitBackground24(void) { // Background rendering/drawing functions RenderBackground = RenderBackground24; if( GameOptions & OPTION_BG_BACKGROUND ) { PaintBackground = PaintBackground24; RepaintBackground = RepaintBackground24; RepaintBackgroundA = RepaintBackground24a; } else { PaintBackground = FillBackground24; RepaintBackground = RefillBackground24; RepaintBackgroundA = RefillBackground24a; } // Particle rendering functions if( GameOptions & OPTION_BG_WHITE_PARTICLE ) { RenderBGfx = WRenderParticle24; // (bgfx.cpp) RenderBGfxA = WRenderParticle24a; // (bgfx.cpp) RenderBGfxP = WRenderParticle24p; // (bgfx.cpp) } else { RenderBGfx = RenderParticle24; // (bgfx.cpp) RenderBGfxA = RenderParticle24a; // (bgfx.cpp) RenderBGfxP = RenderParticle24p; // (bgfx.cpp) } // Particle animation/initialization functions switch( GameOptions & OPTION_BG_FX ) { case OPTION_BG_FRACTAL: InitFractal(); // (bgfx.cpp) AnimateBackground = AnimateFractal; // (bgfx.cpp) break; case OPTION_BG_DUST: InitDust(); // (bgfx.cpp) AnimateBackground = AnimateDust; // (bgfx.cpp) break; case OPTION_BG_SWARM: InitSwarm(); // (bgfx.cpp) AnimateBackground = AnimateSwarm; // (bgfx.cpp) break; default: AnimateBackground = NullFunc; // (global.cpp) break; } } // InitBackground24() /********************************************************** InitBackground32 Select background functions. */ void InitBackground32(void) { // Background rendering/drawing functions RenderBackground = RenderBackground32; if( GameOptions & OPTION_BG_BACKGROUND ) { PaintBackground = PaintBackground32; RepaintBackground = RepaintBackground32; RepaintBackgroundA = RepaintBackground32a; } else { PaintBackground = FillBackground32; RepaintBackground = RefillBackground32; RepaintBackgroundA = RefillBackground32a; } // Particle rendering functions if( GameOptions & OPTION_BG_WHITE_PARTICLE ) { RenderBGfx = WRenderParticle32; // (bgfx.cpp) RenderBGfxA = WRenderParticle32a; // (bgfx.cpp) RenderBGfxP = WRenderParticle32p; // (bgfx.cpp) } else { RenderBGfx = RenderParticle32; // (bgfx.cpp) RenderBGfxA = RenderParticle32a; // (bgfx.cpp) RenderBGfxP = RenderParticle32p; // (bgfx.cpp) } // Particle animation/initialization functions switch( GameOptions & OPTION_BG_FX ) { case OPTION_BG_FRACTAL: InitFractal(); // (bgfx.cpp) AnimateBackground = AnimateFractal; // (bgfx.cpp) break; case OPTION_BG_DUST: InitDust(); // (bgfx.cpp) AnimateBackground = AnimateDust; // (bgfx.cpp) break; case OPTION_BG_SWARM: InitSwarm(); // (bgfx.cpp) AnimateBackground = AnimateSwarm; // (bgfx.cpp) break; default: AnimateBackground = NullFunc; // (global.cpp) break; } } // InitBackground32() /***************************************************************** Recapture Recapture desktop. */ void Recapture(void) { ShowWindow(AppWindow, SW_HIDE); InvalidateRect(NULL, NULL, TRUE); // Force desktop repaint CaptureScreen(); RenderBackground(); ShowWindow(AppWindow, SW_SHOW); } // Recapture() /********************************************************* ReleaseBackground Free memory allocated by desktop image. */ void ReleaseBackground(void) { if( BGImage != NULL ) { Free(BGImage); BGImage = NULL; } } // ReleaseBackground() /********************************************************** FillBackground15 Fill background with uniform color. */ static void FillBackground15(DWORD screen) { __asm { pushf cld mov edi, screen mov eax, 701f701fh ; (28, 28, 31) x 2 mov ebx, APP_HEIGHT mov edx, DDPitch sub edx, (APP_WIDTH * 2) ; EDX = delta between scanlines FillBackground15_loop: mov ecx, (APP_WIDTH / 2) rep stosd add edi, edx dec ebx jnz FillBackground15_loop popf } if( GameOptions & OPTION_BG_FX ) RenderBGfx(screen); } // FillBackground15() /********************************************************** FillBackground16 Fill background with uniform color. */ static void FillBackground16(DWORD screen) { __asm { pushf cld mov edi, screen mov eax, 0e73fe73fh ; (28, 57, 31) x 2 mov ebx, APP_HEIGHT mov edx, DDPitch sub edx, (APP_WIDTH * 2) ; EDX = delta between scanlines FillBackground16_loop: mov ecx, (APP_WIDTH / 2) rep stosd add edi, edx dec ebx jnz FillBackground16_loop popf } if( GameOptions & OPTION_BG_FX ) RenderBGfx(screen); } // FillBackground16() /********************************************************** FillBackground24 Fill background with uniform color. */ static void FillBackground24(DWORD screen) { __asm { pushf cld mov edi, screen mov eax, 0ffe7e7ffh ; (231, 231, 255) mov ebx, APP_HEIGHT mov edx, DDPitch sub edx, (APP_WIDTH * 3) ; EDX = delta between scanlines FillBackground24_yloop: mov ecx, APP_WIDTH FillBackground24_xloop: stosd dec edi loop FillBackground24_xloop add edi, edx dec ebx jnz FillBackground24_yloop popf } if( GameOptions & OPTION_BG_FX ) RenderBGfx(screen); } // FillBackground24() /********************************************************** FillBackground32 Fill background with uniform color. */ static void FillBackground32(DWORD screen) { __asm { pushf cld mov edi, screen mov eax, 00e7e7ffh ; (231, 231, 255) mov ebx, APP_HEIGHT mov edx, DDPitch sub edx, (APP_WIDTH * 4) ; EDX = delta between scanlines FillBackground32_loop: mov ecx, APP_WIDTH rep stosd add edi, edx dec ebx jnz FillBackground32_loop popf } if( GameOptions & OPTION_BG_FX ) RenderBGfx(screen); } // FillBackground32() /********************************************************* PaintBackground16 Draw background image. */ static void PaintBackground16(DWORD screen) { POINT offset; DWORD src, y; // Translate application offset to screen offset offset.x = offset.y = 0; ClientToScreen(AppWindow, &offset); // copy memory block src = (DWORD)(BGImage + 2 * (offset.y * ScreenWidth + offset.x)); __asm { pushf cld mov eax, APP_HEIGHT mov y, eax mov esi, src mov edi, screen mov edx, DDPitch sub edx, (APP_WIDTH * 2) ; EDX = delta between screen scanlines mov ebx, ScreenWidth shl ebx, 1 sub ebx, (APP_WIDTH * 2) ; EBX = delta between buffer scanlines PaintBackground16_loop: mov ecx, (APP_WIDTH / 2) rep movsd add esi, ebx add edi, edx dec dword ptr [y] jnz PaintBackground16_loop popf } if( GameOptions & OPTION_BG_FX ) RenderBGfx(screen); } // PaintBackground16() /********************************************************* PaintBackground24 Draw background image. */ static void PaintBackground24(DWORD screen) { POINT offset; DWORD src, y; // Translate application offset to screen offset offset.x = offset.y = 0; ClientToScreen(AppWindow, &offset); // Copy memory block src = (DWORD)(BGImage + 3 * (offset.y * ScreenWidth + offset.x)); __asm { pushf cld mov eax, APP_HEIGHT mov y, eax mov esi, src mov edi, screen mov edx, DDPitch sub edx, (APP_WIDTH * 3) ; EDX = delta between screen scanlines mov ebx, ScreenWidth shl ebx, 1 add ebx, ScreenWidth sub ebx, (APP_WIDTH * 3) ; EBX = delta between buffer scanlines PaintBackground24_loop: mov ecx, (3 * APP_WIDTH / 4) rep movsd add esi, ebx add edi, edx dec dword ptr [y] jnz PaintBackground24_loop popf } if( GameOptions & OPTION_BG_FX ) RenderBGfx(screen); } // PaintBackground24() /********************************************************* PaintBackground32 Draw background image. */ static void PaintBackground32(DWORD screen) { POINT offset; DWORD src, y; // Translate application offset to screen offset offset.x = offset.y = 0; ClientToScreen(AppWindow, &offset); // Copy memory block src = (DWORD)(BGImage + 4 * (offset.y * ScreenWidth + offset.x)); __asm { pushf cld mov eax, APP_HEIGHT mov y, eax mov esi, src mov edi, screen mov edx, DDPitch sub edx, (APP_WIDTH * 4) ; EDX = delta between screen scanlines mov ebx, ScreenWidth shl ebx, 2 sub ebx, (APP_WIDTH * 4) ; EBX = delta between buffer scanlines PaintBackground32_loop: mov ecx, APP_WIDTH rep movsd add esi, ebx add edi, edx dec dword ptr [y] jnz PaintBackground32_loop popf } if( GameOptions & OPTION_BG_FX ) RenderBGfx(screen); } // PaintBackground32() /******************************************************** RenderBackground15 Prepare background image (surface pixel format is 1:5:5:5). */ static void RenderBackground15(void) { DWORD *image; image = (DWORD*)BGImage; __asm { pushf cld mov esi, image mov edi, esi mov eax, ScreenWidth mov ebx, ScreenHeight mul ebx mov ecx, eax ; ECX = number of pixels mov edx, 0c60h ; 00001100 01100000 RenderBackground15_loop: lodsw ; 00000000 00000000 0rrrrrgg gggbbbbb shr eax, 1 ; 00000000 00000000 00rrrrrg ggggbbbb or eax, 4210h ; 00000000 00000000 01rrrr1g ggg1bbbb sub eax, edx stosw loop RenderBackground15_loop popf } // Correct orientation (DIB is bottom to top, screen is top to bottom) VMirror16(); } // RenderBackground15() /******************************************************** RenderBackground16 Prepare background image (surface pixel format is 5:6:5). */ static void RenderBackground16(void) { DWORD *image; // Note that surface is 5:6:5 format while DIB is 1:5:5:5 format. image = (DWORD*)BGImage; __asm { pushf cld mov esi, image mov edi, esi mov eax, ScreenWidth mov ebx, ScreenHeight mul ebx mov ecx, eax ; ECX = number of pixels mov edx, 18c0h ; 00011000 11000000 RenderBackground16_loop: lodsw ; 00000000 00000000 0rrrrrgg gggbbbbb rol eax, 3 ; 00000000 000000rr rrrggggg bbbbb000 shr al, 1 ; 00000000 000000rr rrrggggg 0bbbbb00 shr eax, 3 ; 00000000 00000000 0rrrrrgg ggg0bbbb or eax, 8410h ; 00000000 00000000 1rrrr1gg ggg1bbbb sub eax, edx stosw loop RenderBackground16_loop popf } // Correct orientation (DIB is bottom to top, screen is top to bottom) VMirror16(); } // RenderBackground16() /******************************************************** RenderBackground24 Prepare background image (surface pixel format is 8:8:8). */ static void RenderBackground24(void) { DWORD *image; image = (DWORD*)BGImage; __asm { pushf cld mov esi, image mov edi, esi mov eax, ScreenWidth mov ebx, ScreenHeight mul ebx mov ecx, eax ; ECX = number of pixels mov edx, 1f1fh ; 00000000 00000000 00011111 00011111 mov ebx, 8080h ; 00000000 00000000 10000000 10000000 RenderBackground24_loop: lodsb ; bbbbbbbb shr eax, 1 ; 0bbbbbbb or eax, ebx ; 1bbbbbbb stosb lodsw ; rrrrrrrr gggggggg shr eax, 1 ; 0rrrrrrr rggggggg or eax, ebx ; 1rrrrrrr 1ggggggg sub eax, edx stosw loop RenderBackground24_loop popf } // Correct orientation (DIB is bottom to top, screen is top to bottom) VMirror24(); } // RenderBackground24() /******************************************************** RenderBackground32 Prepare background image (surface pixel format is 8:8:8). */ static void RenderBackground32(void) { DWORD *image; image = (DWORD*)BGImage; __asm { pushf cld mov esi, image mov edi, esi mov eax, ScreenWidth mov ebx, ScreenHeight mul ebx mov ecx, eax ; ECX = number of pixels mov edx, 181800h ; 00000000 00011000 00011000 00000000 mov ebx, 808080h ; 00000000 10000000 10000000 10000000 RenderBackground32_loop: lodsd ; 00000000 rrrrrrrr gggggggg bbbbbbbb shr eax, 1 ; 00000000 0rrrrrrr rggggggg gbbbbbbb or eax, ebx ; 00000000 1rrrrrrr 1ggggggg 1bbbbbbb sub eax, edx stosd loop RenderBackground32_loop popf } // Correct orientation (DIB is bottom to top, screen is top to bottom) VMirror32(); } // RenderBackground32() /******************************************************** RefillBackground15 Fill part of background with solid color (at grid coordinates). */ static void RefillBackground15(DWORD screen, int c, int r) { DWORD screen0; screen0 = screen + SpriteOffset[c][r]; __asm { pushf cld mov edi, screen0 mov eax, 701f701fh mov ebx, CELL_SIZE mov edx, DDPitch sub edx, (CELL_SIZE * 2) RefillBackground15_loop: mov ecx, (CELL_SIZE / 2) rep stosd add edi, edx dec ebx jnz RefillBackground15_loop popf } if( GameOptions & OPTION_BG_FX ) RenderBGfxP(screen, c, r); } // RefillBackground15() /******************************************************* RefillBackground15a Fill part of background with solid color (at screen coordinates). */ static void RefillBackground15a(DWORD screen, int x, int y, int w, int h) { __asm { pushf cld mov edi, screen mov eax, y mov ebx, DDPitch mul ebx add edi, eax mov eax, x shl eax, 1 add edi, eax ; EDI = start offset mov edx, ebx mov esi, w shl esi, 1 sub edx, esi ; EDX = delta between scanlines mov ebx, h shr esi, 2 mov eax, 701f701fh RefillBackground15a_loop: mov ecx, esi rep stosd add edi, edx dec ebx jnz RefillBackground15a_loop popf } if( GameOptions & OPTION_BG_FX ) RenderBGfxA(screen, x, y, w, h); } // RefillBackground15a() /******************************************************** RefillBackground16 Fill part of background with solid color (at grid coordinates). */ static void RefillBackground16(DWORD screen, int c, int r) { DWORD screen0; screen0 = screen + SpriteOffset[c][r]; __asm { pushf cld mov edi, screen0 mov eax, 0e73fe73fh mov ebx, CELL_SIZE mov edx, DDPitch sub edx, (CELL_SIZE * 2) RefillBackground16_loop: mov ecx, (CELL_SIZE / 2) rep stosd add edi, edx dec ebx jnz RefillBackground16_loop popf } if( GameOptions & OPTION_BG_FX ) RenderBGfxP(screen, c, r); } // RefillBackground16() /******************************************************* RefillBackground16a Fill part of background with solid color (at screen coordinates). */ static void RefillBackground16a(DWORD screen, int x, int y, int w, int h) { __asm { pushf cld mov edi, screen mov eax, y mov ebx, DDPitch mul ebx add edi, eax mov eax, x shl eax, 1 add edi, eax ; EDI = start offset mov edx, ebx mov esi, w shl esi, 1 sub edx, esi ; EDX = delta between scanlines mov ebx, h shr esi, 2 mov eax, 0e73fe73fh RefillBackground16a_loop: mov ecx, esi rep stosd add edi, edx dec ebx jnz RefillBackground16a_loop popf } if( GameOptions & OPTION_BG_FX ) RenderBGfxA(screen, x, y, w, h); } // RefillBackground16a() /******************************************************* RepaintBackground16 Repaint part of background (at grid coordinates). */ static void RepaintBackground16(DWORD screen, int c, int r) { POINT offset; DWORD src, dst, y; // Get screen offset offset.x = c * CELL_SIZE + GRID_MARGIN; offset.y = APP_HEIGHT - ((r + 1) * CELL_SIZE) - GRID_MARGIN; ClientToScreen(AppWindow, &offset); // Copy memory block src = (DWORD)(BGImage + 2 * (offset.y * ScreenWidth + offset.x)); dst = screen + SpriteOffset[c][r]; __asm { pushf cld mov eax, CELL_SIZE mov y, eax mov esi, src mov edi, dst mov edx, DDPitch sub edx, (CELL_SIZE * 2) ; EDX = delta between screen scanlines mov ebx, ScreenWidth shl ebx, 1 sub ebx, (CELL_SIZE * 2) ; EBX = delta between buffer scanlines RepaintBackground16_loop: mov ecx, (CELL_SIZE / 2) rep movsd add esi, ebx add edi, edx dec dword ptr [y] jnz RepaintBackground16_loop popf } if( GameOptions & OPTION_BG_FX ) RenderBGfxP(screen, c, r); } // RepaintBackground16() /****************************************************** RepaintBackground16a Repaint part of background (at screen coordinates). */ static void RepaintBackground16a(DWORD screen, int x, int y, int w, int h) { POINT offset; DWORD src, dst, y0; // Get screen offset offset.x = x; offset.y = y; ClientToScreen(AppWindow, &offset); // Copy memory block src = (DWORD)(BGImage + 2 * (offset.y * ScreenWidth + offset.x)); dst = screen + y * DDPitch + x * 2; __asm { pushf cld mov eax, h mov y0, eax mov esi, src mov edi, dst mov eax, w shl eax, 1 mov edx, DDPitch sub edx, eax ; EDX = delta between screen scanlines mov ebx, ScreenWidth shl ebx, 1 sub ebx, eax ; EBX = delta between buffer scanlines RepaintBackground16a_loop: mov ecx, w rep movsw add esi, ebx add edi, edx dec dword ptr [y0] jnz RepaintBackground16a_loop popf } if( GameOptions & OPTION_BG_FX ) RenderBGfxA(screen, x, y, w, h); } // RepaintBackground16a() /******************************************************** RefillBackground24 Fill part of background with solid color (at grid coordinates). */ static void RefillBackground24(DWORD screen, int c, int r) { DWORD screen0; screen0 = screen + SpriteOffset[c][r]; __asm { pushf cld mov edi, screen0 mov eax, 0ffffe7e7h mov ebx, CELL_SIZE mov edx, DDPitch sub edx, (CELL_SIZE * 3) RefillBackground24_yloop: mov ecx, CELL_SIZE RefillBackground24_xloop: mov byte ptr [edi], 0ffh inc edi stosw loop RefillBackground24_xloop add edi, edx dec ebx jnz RefillBackground24_yloop popf } if( GameOptions & OPTION_BG_FX ) RenderBGfxP(screen, c, r); } // RefillBackground24() /******************************************************* RefillBackground24a Fill part of background with solid color (at screen coordinates). */ static void RefillBackground24a(DWORD screen, int x, int y, int w, int h) { __asm { pushf cld mov edi, screen mov eax, y mov ebx, DDPitch mul ebx add edi, eax mov eax, x add edi, eax shl eax, 1 add edi, eax ; EDI = start offset mov edx, ebx mov eax, w mov esi, eax sub edx, eax shl eax, 1 sub edx, eax ; EDX = delta between scanlines mov ebx, h mov eax, 0e7e7h RefillBackground24a_yloop: mov ecx, esi RefillBackground24a_xloop: mov byte ptr [edi], 0ffh inc edi stosw loop RefillBackground24a_xloop add edi, edx dec ebx jnz RefillBackground24a_yloop popf } if( GameOptions & OPTION_BG_FX ) RenderBGfxA(screen, x, y, w, h); } // RefillBackground24a() /******************************************************* RepaintBackground24 Repaint part of background (at grid coordinates). */ static void RepaintBackground24(DWORD screen, int c, int r) { POINT offset; DWORD src, dst, y; // Get screen offset offset.x = c * CELL_SIZE + GRID_MARGIN; offset.y = APP_HEIGHT - ((r + 1) * CELL_SIZE) - GRID_MARGIN; ClientToScreen(AppWindow, &offset); // Copy memory block src = (DWORD)(BGImage + 3 * (offset.y * ScreenWidth + offset.x)); dst = screen + SpriteOffset[c][r]; __asm { pushf cld mov eax, CELL_SIZE mov y, eax mov esi, src mov edi, dst mov edx, DDPitch sub edx, (CELL_SIZE * 3) ; EDX = delta between screen scanlines mov ebx, ScreenWidth shl ebx, 1 add ebx, ScreenWidth sub ebx, (CELL_SIZE * 3) ; EBX = delta between buffer scanlines RepaintBackground24_loop: mov ecx, (3 * CELL_SIZE / 4) rep movsd add esi, ebx add edi, edx dec dword ptr [y] jnz RepaintBackground24_loop popf } if( GameOptions & OPTION_BG_FX ) RenderBGfxP(screen, c, r); } // RepaintBackground24() /****************************************************** RepaintBackground24a Repaint part of background (at screen coordinates). */ static void RepaintBackground24a(DWORD screen, int x, int y, int w, int h) { POINT offset; DWORD src, dst, y0, w0; // Get screen offset offset.x = x; offset.y = y; ClientToScreen(AppWindow, &offset); // Copy memory block src = (DWORD)(BGImage + 3 * (offset.y * ScreenWidth + offset.x)); dst = screen + y * DDPitch + x * 3; __asm { pushf cld mov eax, h mov y0, eax mov esi, src mov edi, dst mov eax, w shl eax, 1 add eax, w mov edx, DDPitch sub edx, eax ; EDX = delta between screen scanlines mov ebx, ScreenWidth shl ebx, 1 add ebx, ScreenWidth sub ebx, eax ; EBX = delta between buffer scanlines shr eax, 2 mov w0, eax RepaintBackground24a_loop: mov ecx, w0 rep movsd add esi, ebx add edi, edx dec dword ptr [y0] jnz RepaintBackground24a_loop popf } if( GameOptions & OPTION_BG_FX ) RenderBGfxA(screen, x, y, w, h); } // RepaintBackground24a() /******************************************************** RefillBackground32 Fill part of background with solid color (at grid coordinates). */ static void RefillBackground32(DWORD screen, int c, int r) { DWORD screen0; screen0 = screen + SpriteOffset[c][r]; __asm { pushf cld mov edi, screen0 mov eax, 00e7e7ffh mov ebx, CELL_SIZE mov edx, DDPitch sub edx, (CELL_SIZE * 4) RefillBackground32_loop: mov ecx, CELL_SIZE rep stosd add edi, edx dec ebx jnz RefillBackground32_loop popf } if( GameOptions & OPTION_BG_FX ) RenderBGfxP(screen, c, r); } // RefillBackground32() /******************************************************* RefillBackground32a Fill part of background with solid color (at screen coordinates). */ static void RefillBackground32a(DWORD screen, int x, int y, int w, int h) { __asm { pushf cld mov edi, screen mov eax, y mov ebx, DDPitch mul ebx add edi, eax mov eax, x shl eax, 2 add edi, eax ; EDI = start offset mov edx, ebx mov eax, w mov esi, eax shl eax, 2 sub edx, eax ; EDX = delta between scanlines mov ebx, h mov eax, 00e7e7ffh RefillBackground32a_loop: mov ecx, esi rep stosd add edi, edx dec ebx jnz RefillBackground32a_loop popf } if( GameOptions & OPTION_BG_FX ) RenderBGfxA(screen, x, y, w, h); } // RefillBackground32a() /******************************************************* RepaintBackground32 Repaint part of background (at grid coordinates). */ static void RepaintBackground32(DWORD screen, int c, int r) { POINT offset; DWORD src, dst, y; // Get screen offset offset.x = c * CELL_SIZE + GRID_MARGIN; offset.y = APP_HEIGHT - ((r + 1) * CELL_SIZE) - GRID_MARGIN; ClientToScreen(AppWindow, &offset); // Copy memory block src = (DWORD)(BGImage + 4 * (offset.y * ScreenWidth + offset.x)); dst = screen + SpriteOffset[c][r]; __asm { pushf cld mov eax, CELL_SIZE mov y, eax mov esi, src mov edi, dst mov edx, DDPitch sub edx, (CELL_SIZE * 4) ; EDX = delta between screen scanlines mov ebx, ScreenWidth shl ebx, 2 sub ebx, (CELL_SIZE * 4) ; EBX = delta between buffer scanlines RepaintBackground32_loop: mov ecx, CELL_SIZE rep movsd add esi, ebx add edi, edx dec dword ptr [y] jnz RepaintBackground32_loop popf } if( GameOptions & OPTION_BG_FX ) RenderBGfxP(screen, c, r); } // RepaintBackground32() /****************************************************** RepaintBackground32a Repaint part of background (at screen coordinates). */ static void RepaintBackground32a(DWORD screen, int x, int y, int w, int h) { POINT offset; DWORD src, dst, y0; // Get screen offset offset.x = x; offset.y = y; ClientToScreen(AppWindow, &offset); // Copy memory block src = (DWORD)(BGImage + 4 * (offset.y * ScreenWidth + offset.x)); dst = screen + y * DDPitch + x * 4; __asm { pushf cld mov eax, h mov y0, eax mov esi, src mov edi, dst mov eax, w shl eax, 2 mov edx, DDPitch sub edx, eax ; EDX = delta between screen scanlines mov ebx, ScreenWidth shl ebx, 2 sub ebx, eax ; EBX = delta between buffer scanlines RepaintBackground32a_loop: mov ecx, w rep movsd add esi, ebx add edi, edx dec dword ptr [y0] jnz RepaintBackground32a_loop popf } if( GameOptions & OPTION_BG_FX ) RenderBGfxA(screen, x, y, w, h); } // RepaintBackground32a() /***************************************************************** VMirror16 Mirror background image vertically. */ static void VMirror16(void) { BYTE *scanline; DWORD top, bottom; if( (scanline = (BYTE*)Malloc(ScreenWidth * 2)) == NULL ) { LogMessage("Not enough memory"); return; } top = (DWORD)BGImage; bottom = top + (ScreenHeight - 1) * ScreenWidth * 2; __asm { pushf cld mov edx, ScreenHeight shr edx, 1 mov ebx, ScreenWidth shr ebx, 1 VMirror16_loop: mov esi, top mov edi, scanline mov ecx, ebx rep movsd ; scanline = top mov esi, bottom mov edi, top mov ecx, ebx rep movsd ; top = bottom mov esi, scanline mov edi, bottom mov ecx, ebx rep movsd ; bottom = scanline mov eax, ebx shl eax, 2 add top, eax ; Set top to next scanline down sub bottom, eax ; Set bottom to next scanline up dec edx jnz VMirror16_loop popf } Free(scanline); } // VMirror16() /***************************************************************** VMirror24 Mirror background image vertically. */ static void VMirror24(void) { BYTE *scanline; DWORD top, bottom; if( (scanline = (BYTE*)Malloc(ScreenWidth * 3)) == NULL ) { LogMessage("Not enough memory"); return; } top = (DWORD)BGImage; bottom = top + (ScreenHeight - 1) * ScreenWidth * 3; __asm { pushf cld mov edx, ScreenHeight shr edx, 1 mov ebx, ScreenWidth shl ebx, 1 add ebx, ScreenWidth shr ebx, 2 ; EBX = ScreenWidth * 3 / 4 VMirror24_loop: mov esi, top mov edi, scanline mov ecx, ebx rep movsd ; scanline = top mov esi, bottom mov edi, top mov ecx, ebx rep movsd ; top = bottom mov esi, scanline mov edi, bottom mov ecx, ebx rep movsd ; bottom = scanline mov eax, ebx shl eax, 2 add top, eax ; Set top to next scanline down sub bottom, eax ; Set bottom to next scanline up dec edx jnz VMirror24_loop popf } Free(scanline); } // VMirror24() /***************************************************************** VMirror32 Mirror background image vertically. */ static void VMirror32(void) { BYTE *scanline; DWORD top, bottom; if( (scanline = (BYTE*)Malloc(ScreenWidth * 4)) == NULL ) { LogMessage("Not enough memory"); return; } top = (DWORD)BGImage; bottom = top + (ScreenHeight - 1) * ScreenWidth * 4; __asm { pushf cld mov edx, ScreenHeight shr edx, 1 mov ebx, ScreenWidth VMirror32_loop: mov esi, top mov edi, scanline mov ecx, ebx rep movsd ; scanline = top mov esi, bottom mov edi, top mov ecx, ebx rep movsd ; top = bottom mov esi, scanline mov edi, bottom mov ecx, ebx rep movsd ; bottom = scanline mov eax, ebx shl eax, 2 add top, eax ; Set top to next scanline down sub bottom, eax ; Set bottom to next scanline up dec edx jnz VMirror32_loop popf } Free(scanline); } // VMirror32() char *BgObjTime = __TIME__ " " __DATE__; int BgObjLines = __LINE__;