diff --git a/REDALERT/VQAMOVIE.CPP b/REDALERT/VQAMOVIE.CPP index be52417..f4763d0 100644 --- a/REDALERT/VQAMOVIE.CPP +++ b/REDALERT/VQAMOVIE.CPP @@ -12,8 +12,7 @@ int vqa_upscale_hack_width = 0; int vqa_upscale_hack_height = 0; byte* vqa_output_buffer = nullptr; -byte* VQA_Dropsample(const byte* in, int inwidth, int inheight, - int outwidth, int outheight) { +byte* VQA_Dropsample(const byte* in, int inwidth, int inheight, int outwidth, int outheight) { int i, j, k; const byte* inrow; const byte* pix1; diff --git a/REDALERT/WIN32LIB/DrawMisc.cpp b/REDALERT/WIN32LIB/DrawMisc.cpp index 37bf9e7..5fad260 100644 --- a/REDALERT/WIN32LIB/DrawMisc.cpp +++ b/REDALERT/WIN32LIB/DrawMisc.cpp @@ -1379,480 +1379,6 @@ void __cdecl Buffer_Clear(void *this_object, unsigned char color) } } - - - - - - - - - - - - - -BOOL __cdecl Linear_Blit_To_Linear( void *this_object, void * dest, int x_pixel, int y_pixel, int dest_x0, int dest_y0, int pixel_width, int pixel_height, BOOL trans) -{ -/* - ;*=================================================================== - ;* define the arguements that our function takes. - ;*=================================================================== - ARG this_object :DWORD ; this is a member function - ARG dest :DWORD ; what are we blitting to - ARG x_pixel :DWORD ; x pixel position in source - ARG y_pixel :DWORD ; y pixel position in source - ARG dest_x0 :dword - ARG dest_y0 :dword - ARG pixel_width :DWORD ; width of rectangle to blit - ARG pixel_height:DWORD ; height of rectangle to blit - ARG trans :DWORD ; do we deal with transparents? - - ;*=================================================================== - ; Define some locals so that we can handle things quickly - ;*=================================================================== - LOCAL x1_pixel :dword - LOCAL y1_pixel :dword - LOCAL dest_x1 : dword - LOCAL dest_y1 : dword - LOCAL scr_ajust_width:DWORD - LOCAL dest_ajust_width:DWORD - LOCAL source_area : dword - LOCAL dest_area : dword -*/ - - int x1_pixel; - int y1_pixel; - int dest_x1; - int dest_y1; - int scr_adjust_width; - int dest_adjust_width; - int source_area; - int dest_area; - - __asm { - - ;This Clipping algorithm is a derivation of the very well known - ;Cohen-Sutherland Line-Clipping test. Due to its simplicity and efficiency - ;it is probably the most commontly implemented algorithm both in software - ;and hardware for clipping lines, rectangles, and convex polygons against - ;a rectagular clipping window. For reference see - ;"COMPUTER GRAPHICS principles and practice by Foley, Vandam, Feiner, Hughes - ; pages 113 to 177". - ; Briefly consist in computing the Sutherland code for both end point of - ; the rectangle to find out if the rectangle is: - ; - trivially accepted (no further clipping test, display rectangle) - ; - trivially rejected (return with no action) - ; - retangle must be iteratively clipped again edges of the clipping window - ; and the remaining retangle is display. - - ; Clip Source Rectangle against source Window boundaries. - mov esi,[this_object] ; get ptr to src - xor ecx,ecx ; Set sutherland code to zero - xor edx,edx ; Set sutherland code to zero - - ; compute the difference in the X axis and get the bit signs into ecx , edx - mov edi,[esi]GraphicViewPortClass.Width ; get width into register - mov ebx,[x_pixel] ; Get first end point x_pixel into register - mov eax,[x_pixel] ; Get second end point x_pixel into register - add ebx,[pixel_width] ; second point x1_pixel = x + width - shld ecx, eax,1 ; the sign bit of x_pixel is sutherland code0 bit4 - mov [x1_pixel],ebx ; save second for future use - inc edi ; move the right edge by one unit - shld edx,ebx,1 ; the sign bit of x1_pixel is sutherland code0 bit4 - sub eax,edi ; compute the difference x0_pixel - width - sub ebx,edi ; compute the difference x1_pixel - width - shld ecx,eax,1 ; the sign bit of the difference is sutherland code0 bit3 - shld edx,ebx,1 ; the sign bit of the difference is sutherland code0 bit3 - - ; the following code is just a repeticion of the above code - ; in the Y axis. - mov edi,[esi]GraphicViewPortClass.Height ; get height into register - mov ebx,[y_pixel] - mov eax,[y_pixel] - add ebx,[pixel_height] - shld ecx,eax,1 - mov [y1_pixel ],ebx - inc edi - shld edx,ebx,1 - sub eax,edi - sub ebx,edi - shld ecx,eax,1 - shld edx,ebx,1 - - ; Here we have the to Sutherland code into cl and dl - xor cl,5 ; bit 2 and 0 are complented, reverse then - xor dl,5 ; bit 2 and 0 are complented, reverse then - mov al,cl ; save code1 in case we have to clip iteratively - test dl,cl ; if any bit in code0 and its counter bit - jnz real_out ; in code1 is set then the rectangle in outside - or al,dl ; if all bit of code0 the counter bit in - jz clip_against_dest ; in code1 is set to zero, then all - ; end points of the rectangle are - ; inside the clipping window - - ; if we are here the polygon have to be clip iteratively - test cl,1000b ; if bit 4 in code0 is set then - jz scr_left_ok ; x_pixel is smaller than zero - mov [x_pixel],0 ; set x_pixel to cero. - - scr_left_ok: - test cl,0010b ; if bit 2 in code0 is set then - jz scr_bottom_ok ; y_pixel is smaller than zero - mov [ y_pixel ],0 ; set y_pixel to cero. - - scr_bottom_ok: - test dl,0100b ; if bit 3 in code1 is set then - jz scr_right_ok ; x1_pixel is greater than the width - mov eax,[esi]GraphicViewPortClass.Width ; get width into register - mov [ x1_pixel ],eax ; set x1_pixel to width. - scr_right_ok: - test dl,0001b ; if bit 0 in code1 is set then - jz clip_against_dest ; y1_pixel is greater than the width - mov eax,[esi]GraphicViewPortClass.Height ; get height into register - mov [ y1_pixel ],eax ; set y1_pixel to height. - - ; Clip Source Rectangle against destination Window boundaries. - clip_against_dest: - - ; build the destination rectangle before clipping - ; dest_x1 = dest_x0 + ( x1_pixel - x_pixel ) - ; dest_y1 = dest_y0 + ( y1_pixel - y_pixel ) - mov eax,[dest_x0] ; get dest_x0 into eax - mov ebx,[dest_y0] ; get dest_y0 into ebx - sub eax,[x_pixel] ; subtract x_pixel from eax - sub ebx,[y_pixel] ; subtract y_pixel from ebx - add eax,[x1_pixel] ; add x1_pixel to eax - add ebx,[y1_pixel] ; add y1_pixel to ebx - mov [dest_x1],eax ; save eax into dest_x1 - mov [dest_y1],ebx ; save eax into dest_y1 - - - ; The followin code is a repeticion of the Sutherland clipping - ; descrived above. - mov esi,[dest] ; get ptr to src - xor ecx,ecx - xor edx,edx - mov edi,[esi]GraphicViewPortClass.Width ; get width into register - mov eax,[dest_x0] - mov ebx,[dest_x1] - shld ecx,eax,1 - inc edi - shld edx,ebx,1 - sub eax,edi - sub ebx,edi - shld ecx,eax,1 - shld edx,ebx,1 - - mov edi,[esi]GraphicViewPortClass.Height ; get height into register - mov eax,[dest_y0] - mov ebx,[dest_y1] - shld ecx,eax,1 - inc edi - shld edx,ebx,1 - sub eax,edi - sub ebx,edi - shld ecx,eax,1 - shld edx,ebx,1 - - xor cl,5 - xor dl,5 - mov al,cl - test dl,cl - jnz real_out - or al,dl - jz do_blit - - test cl,1000b - jz dest_left_ok - mov eax,[ dest_x0 ] - mov [ dest_x0 ],0 - sub [ x_pixel ],eax - - dest_left_ok: - test cl,0010b - jz dest_bottom_ok - mov eax,[ dest_y0 ] - mov [ dest_y0 ],0 - sub [ y_pixel ],eax - - - dest_bottom_ok: - test dl,0100b - jz dest_right_ok - mov ebx,[esi]GraphicViewPortClass.Width ; get width into register - mov eax,[ dest_x1 ] - mov [ dest_x1 ],ebx - sub eax,ebx - sub [ x1_pixel ],eax - - dest_right_ok: - test dl,0001b - jz do_blit - mov ebx,[esi]GraphicViewPortClass.Height ; get width into register - mov eax,[ dest_y1 ] - mov [ dest_y1 ],ebx - sub eax,ebx - sub [ y1_pixel ],eax - - - ; Here is where we do the actual blit - do_blit: - cld - mov ebx,[this_object] - mov esi,[ebx]GraphicViewPortClass.Offset - mov eax,[ebx]GraphicViewPortClass.XAdd - add eax,[ebx]GraphicViewPortClass.Width - add eax,[ebx]GraphicViewPortClass.Pitch - mov ecx,eax - mul [y_pixel] - add esi,[x_pixel] - mov [source_area],ecx - add esi,eax - - add ecx,[x_pixel ] - sub ecx,[x1_pixel ] - mov [scr_adjust_width ],ecx - - mov ebx,[dest] - mov edi,[ebx]GraphicViewPortClass.Offset - mov eax,[ebx]GraphicViewPortClass.XAdd - add eax,[ebx]GraphicViewPortClass.Width - add eax,[ebx]GraphicViewPortClass.Pitch - mov ecx,eax - mul [ dest_y0 ] - add edi,[ dest_x0 ] - mov [ dest_area ],ecx - add edi,eax - - mov eax,[ dest_x1 ] - sub eax,[ dest_x0 ] - jle real_out - sub ecx,eax - mov [ dest_adjust_width ],ecx - - mov edx,[ dest_y1 ] - sub edx,[ dest_y0 ] - jle real_out - - cmp esi,edi - jz real_out - jl backupward_blit - - ; ******************************************************************** - ; Forward bitblit - - test [ trans ],1 - jnz forward_Blit_trans - - - ; the inner loop is so efficient that - ; the optimal consept no longer apply because - ; the optimal byte have to by a number greather than 9 bytes - cmp eax,10 - jl forward_loop_bytes - - forward_loop_dword: - mov ecx,edi - mov ebx,eax - neg ecx - and ecx,3 - sub ebx,ecx - rep movsb - mov ecx,ebx - shr ecx,2 - rep movsd - mov ecx,ebx - and ecx,3 - rep movsb - add esi,[ scr_adjust_width ] - add edi,[ dest_adjust_width ] - dec edx - jnz forward_loop_dword - jmp real_out //ret - - forward_loop_bytes: - mov ecx,eax - rep movsb - add esi,[ scr_adjust_width ] - add edi,[ dest_adjust_width ] - dec edx - jnz forward_loop_bytes - jmp real_out - - forward_Blit_trans: - mov ecx,eax - and ecx,01fh - lea ecx,[ ecx + ecx * 4 ] - neg ecx - shr eax,5 - lea ecx,[ transp_reference + ecx * 2 ] - mov [ y1_pixel ],ecx - - forward_loop_trans: - mov ecx,eax - jmp [ y1_pixel ] - forward_trans_line: - //REPT 32 - //local transp_pixel - //No REPT in msvc inline assembly. - // Save ECX and use as counter instead. ST - 12/19/2018 5:41PM - push ecx - mov ecx, 32 - - rept_loop: - mov bl,[ esi ] - test bl,bl - jz transp_pixel - mov [ edi ],bl - transp_pixel: - inc esi - inc edi - - dec ecx //ST - 12/19/2018 5:44PM - jnz rept_loop //ST - 12/19/2018 5:44PM - - pop ecx //ST - 12/19/2018 5:44PM - - //ENDM - transp_reference: - dec ecx - jge forward_trans_line - add esi,[ scr_adjust_width ] - add edi,[ dest_adjust_width ] - dec edx - jnz forward_loop_trans - jmp real_out //ret - - - ; ************************************************************************ - ; backward bitblit - - backupward_blit: - - mov ebx,[ source_area ] - dec edx - add esi,eax - imul ebx,edx - std - lea esi,[ esi + ebx - 1 ] - - mov ebx,[ dest_area ] - add edi,eax - imul ebx,edx - lea edi,[ edi + ebx - 1] - - test [ trans ],1 - jnz backward_Blit_trans - - cmp eax,15 - jl backward_loop_bytes - - backward_loop_dword: - push edi - push esi - lea ecx,[edi+1] - mov ebx,eax - and ecx,3 ; Get non aligned bytes. - sub ebx,ecx ; remove that from the total size to be copied later. - rep movsb ; do the copy. - sub esi,3 - mov ecx,ebx ; Get number of bytes left. - sub edi,3 - shr ecx,2 ; Do 4 bytes at a time. - rep movsd ; do the dword copy. - mov ecx,ebx - add esi,3 - add edi,3 - and ecx,03h - rep movsb ; finnish the remaining bytes. - pop esi - pop edi - sub esi,[ source_area ] - sub edi,[ dest_area ] - dec edx - jge backward_loop_dword - cld - jmp real_out //ret - - backward_loop_bytes: - push edi - mov ecx,eax ; remove that from the total size to be copied later. - push esi - rep movsb ; do the copy. - pop esi - pop edi - sub esi,[ source_area ] - sub edi,[ dest_area ] - dec edx - jge backward_loop_bytes - cld - jmp real_out //ret - - backward_Blit_trans: - mov ecx,eax - and ecx,01fh - lea ecx,[ ecx + ecx * 4 ] - neg ecx - shr eax,5 - lea ecx,[ back_transp_reference + ecx * 2 ] - mov [ y1_pixel ],ecx - - backward_loop_trans: - mov ecx,eax - push edi - push esi - jmp [ y1_pixel ] - backward_trans_line: - //REPT 32 - //local transp_pixel2 - //No REPT in msvc inline assembly. - // Save ECX and use as counter instead. ST - 12/19/2018 5:41PM - push ecx - mov ecx, 32 - rept_loop2: - mov bl,[ esi ] - test bl,bl - jz transp_pixel2 - mov [ edi ],bl - transp_pixel2: - dec esi - dec edi - - dec ecx //ST - 12/19/2018 5:44PM - jnz rept_loop2 //ST - 12/19/2018 5:44PM - - pop ecx //ST - 12/19/2018 5:44PM - - //ENDM - - back_transp_reference: - dec ecx - jge backward_trans_line - pop esi - pop edi - sub esi,[ source_area ] - sub edi,[ dest_area ] - dec edx - jge backward_loop_trans - cld - //ret - - real_out: - } -} - - - - - - - - - - - - /* ;*************************************************************************** ;* VVC::SCALE -- Scales a virtual viewport to another virtual viewport * @@ -1871,7 +1397,7 @@ BOOL __cdecl Linear_Blit_To_Linear( void *this_object, void * dest, int x_pixel, */ // jmarshall - ported to c -void Nearest_CopyImage(byte* source, int sourceX, int sourceY, int sourceWidth, byte* dest, int destX, int destY, int destWidth, int width, int height) +void Nearest_CopyImage(byte* source, int sourceX, int sourceY, int sourceWidth, int sourceHeight, byte* dest, int destX, int destY, int destWidth, int width, int height, bool trans) { for (int y = 0; y < height; y++) { @@ -1882,7 +1408,10 @@ void Nearest_CopyImage(byte* source, int sourceX, int sourceY, int sourceWidth, int destPos = (destWidth * (_y + (destY))) + (_x + (destX)); int sourcePos = (sourceWidth * (_y + (sourceY))) + (_x + (sourceX)); - if(source[sourcePos] != 0) + if (sourcePos > sourceWidth * sourceHeight) + return; + + if(source[sourcePos] != 0 || trans == false) dest[destPos] = source[sourcePos]; } } @@ -1915,25 +1444,61 @@ byte* Draw_Dropsample(const byte* in, int inwidth, int inheight, int outwidth, i BOOL __cdecl Linear_Scale_To_Linear(void *this_object, void *dest, int src_x, int src_y, int dst_x, int dst_y, int src_width, int src_height, int dst_width, int dst_height, BOOL trans, char *remap) { - if (src_x != 0 || src_y != 0) - return false; - GraphicViewPortClass* viewportClass = (GraphicViewPortClass*)this_object; GraphicViewPortClass* destViewportClass = (GraphicViewPortClass*)dest; - if (destViewportClass->Get_Graphic_Buffer()->Get_Buffer() == NULL) - return false; - - byte* viewportBuffer = ((byte*)viewportClass->Get_Graphic_Buffer()->Get_Buffer()); + byte* viewportBuffer = ((byte*)viewportClass->Get_Offset()); // Scale the GraphicViewPortClass to dest_x, dest_y byte* scaled_buffer = Draw_Dropsample((byte *)viewportBuffer, viewportClass->Get_Width(), viewportClass->Get_Height(), dst_width, dst_height); // Blit the scaled_buffer to dest. - Nearest_CopyImage(scaled_buffer, 0, 0, dst_width, (byte *)destViewportClass->Get_Graphic_Buffer()->Get_Buffer(), dst_x, dst_y, destViewportClass->Get_Width(), dst_width, dst_height); + Nearest_CopyImage(scaled_buffer, src_x, src_y, dst_width, dst_height, (byte *)destViewportClass->Get_Offset(), dst_x, dst_y, destViewportClass->Get_Width(), dst_width, dst_height, trans); return true; } + +BOOL __cdecl Linear_Blit_To_Linear(void* this_object, void* dest, int x_pixel, int y_pixel, int dest_x0, int dest_y0, int pixel_width, int pixel_height, BOOL trans) +{ + GraphicViewPortClass* viewportClass = (GraphicViewPortClass*)this_object; + GraphicViewPortClass* destViewportClass = (GraphicViewPortClass*)dest; + bool needsUnlock = false; + bool sourceNeedsUnlock = false; + + byte* viewportBuffer = NULL; + viewportBuffer = ((byte*)viewportClass->Get_Offset()); + + byte* destBuffer = NULL; + destBuffer = ((byte*)destViewportClass->Get_Offset()); + + //if (destViewportClass->Get_Graphic_Buffer()->Get_Buffer() != NULL) { + // destBuffer = (byte*)destViewportClass->Get_Graphic_Buffer()->Get_Buffer(); + //} + //else { + // destViewportClass->Get_Graphic_Buffer()->Lock(); + // destBuffer = ((byte*)destViewportClass->Get_Graphic_Buffer()->GetMemoryBuffer()); + // needsUnlock = true; + //} + // + //if (viewportBuffer == NULL) { + // viewportClass->Get_Graphic_Buffer()->Lock(); + // viewportBuffer = ((byte*)viewportClass->Get_Graphic_Buffer()->GetMemoryBuffer()); + // sourceNeedsUnlock = true; + //} + + // Blit the buffer to dest. + Nearest_CopyImage(viewportBuffer, x_pixel, y_pixel, viewportClass->Get_Width(), viewportClass->Get_Height(), (byte*)destBuffer, dest_x0, dest_y0, destViewportClass->Get_Width(), pixel_width, pixel_height, trans); + + //if (needsUnlock) { + // destViewportClass->Get_Graphic_Buffer()->Unlock(); + //} + // + //if (sourceNeedsUnlock) { + // viewportClass->Get_Graphic_Buffer()->Unlock(); + //} + return true; +} + // jmarshall end diff --git a/REDALERT/WIN32LIB/GBUFFER.H b/REDALERT/WIN32LIB/GBUFFER.H index 4ee79eb..8d9707e 100644 --- a/REDALERT/WIN32LIB/GBUFFER.H +++ b/REDALERT/WIN32LIB/GBUFFER.H @@ -374,7 +374,11 @@ class GraphicBufferClass : public GraphicViewPortClass, public BufferClass { // Member to get a pointer to a direct draw surface LPDIRECTDRAWSURFACE Get_DD_Surface ( void ); - +// jmarshall + void* GetMemoryBuffer(void) { + return VideoSurfaceDescription.lpSurface; + } +// jmarshall end protected: LPDIRECTDRAWSURFACE VideoSurfacePtr; //Pointer to the related direct draw surface DDSURFACEDESC VideoSurfaceDescription;//Description of the said surface