Pascal Vga
Pascal
Download (.zip)
UNIT VGA;
(****************************************************************************) INTERFACE (****************************************************************************)
(****************************************************************************) (* Here we go ... procedure definitions. :) *) (****************************************************************************)
(** This one changes the screenmode to N ***********************************) PROCEDURE SetMode(N : DWORD);
(** Set a certain color in the VGA palette. ********************************) PROCEDURE SetColor(N, R, G, B : BYTE);
(** Set a color fade between two given colors. *****************************) PROCEDURE SetColorFade(N1,N2,R1,G1,B1,R2,G2,B2 : LONGINT);
(** Allocate a new fake screen. Returns offset *****************************) FUNCTION NewPage : DWORD;
(** Disposes a fake screen. ************************************************) PROCEDURE DisposePage(PageOFfset : DWORD);
(** The standard pixel procedures. *****************************************) PROCEDURE PutPixel(WHERE : DWORD; X,Y : DWORD; C : BYTE); PROCEDURE AddPixel(WHERE : DWORD; X,Y : DWORD; C : BYTE); FUNCTION GetPixel(WHERE : DWORD; X,Y : DWORD) : BYTE;
(* Line drawing procedures *************************************************) PROCEDURE Line(WHERE : DWORD; X1, Y1, X2, Y2 : LONGINT; C : BYTE); PROCEDURE AddLine(WHERE : DWORD; X1, Y1, X2, Y2 : LONGINT; C : BYTE); PROCEDURE GshadeLine(WHERE : DWORD; X1, Y1, X2, Y2 : LONGINT; C1, C2 : BYTE);
(* Clear a given fake screen ***********************************************) VAR ClearPage : PROCEDURE(WHERE : DWORD);
(* Fills a screen with a given value. **************************************) PROCEDURE FillPage(WHERE : DWORD; Color : BYTE);
(* Copies one page to another. *********************************************) VAR CopyPage : PROCEDURE(From, Too : DWORD);
(* Transparant copy (no color 0) *******************************************) PROCEDURE CopyPageT(FROM, TOO : DWORD);
(* Loads a 256*256 RAW image. (as source for rotate) ***********************) PROCEDURE LoadRAW(Where : DWORD; Name : STRING);
(* Plots a pixel on a 256*256 image. ***************************************) PROCEDURE PutPixel255(Where : DWORD; X, Y, C : BYTE);
(* Grabs a pixel from a 256*256 image. *************************************) FUNCTION GetPixel255(Where : DWORD; X, Y : BYTE): BYTE;
(* This one rotates a 256*256 source to a 320*200 screen. ******************) PROCEDURE Rotate(From, Too : DWORD; Rot : DWORD; X, Y, SCALE : LONGINT);
(* Transparant rotate. (No color 0) ****************************************) PROCEDURE RotateT(From, Too : DWORD; Rot : DWORD; X, Y, SCALE : LONGINT);
(* Transparant Rotate Warp. (WarpX and WarpY should be < 8) ****************) PROCEDURE RotateTW(From, Too : DWORD; Rot : DWORD; X, Y, SCALE : LONGINT; WARPX, WARPY : WORD);
(* Same as above but high precision warp. warpx and warpy < 2048 ***********) PROCEDURE RotateTW2(From, Too : DWORD; Rot : DWORD; X, Y, SCALE, WARPX, WARPY : LONGINT);
(* Copying pages (320*200) whilst smudging them ****************************) VAR CopyPageSmudge:PROCEDURE(FROM,TOO : DWORD);
(* Copy smudge, check out to know difference :) ***************************) PROCEDURE CopyPageSmudge2(FROM, TOO : DWORD);
(* Average two pages. Too := (From1+From2)/2 *******************************) VAR MixPages :PROCEDURE(From1,From2,Too : DWORD);
(* Saturate two pages. too := (From1+From2)<255 ****************************) VAR MixPages2 :PROCEDURE(From1,From2,Too : DWORD);
(* Alpha blend two pages. amount = 255 -> 100% from1 ***********************) VAR MixPages3 :PROCEDURE(From1,From2,Too : DWORD; Amount : BYTE);
(* Bumpmapping with mutliple lightsources **********************************) PROCEDURE BumpMap(FROM, TOO, LIGHT : DWORD; LX, LY : WORD);
(* Bumpmapping with one lightsource. ***************************************) PROCEDURE BumpMap2(FROM, TOO, LIGHT : DWORD; LX, LY : INTEGER);
(* Bumpmapping with one lightsource. (no zeros) ****************************) PROCEDURE BumpMap2t(FROM, TOO, LIGHT : DWORD; LX, LY : INTEGER);
(* Bumpmapping with one lightsource. height+slope **************************) PROCEDURE BumpMap3(FROM, TOO, LIGHT : DWORD; LX, LY : INTEGER);
(* Bumpmapping with one lightsource. height+slope+transparent **************) PROCEDURE BumpMap3t(FROM, TOO, LIGHT : DWORD; LX, LY : INTEGER);
(* Scale a 320*200 to 256*256 (to use as rotatesource) *********************) PROCEDURE Scale320to256(FROM, TOO : DWORD); PROCEDURE Scale256to320(FROM, TOO : DWORD);
(* Apply distort relocation maps to 256*256 source giving 320*200 **********) PROCEDURE Relocate(From, Too, Distort1, Distort2, D1Ofs, D2Ofs : LONGINT);
(* Relocate not doing color 0. *********************************************) PROCEDURE RelocateT(From, Too, Distort1, Distort2, D1Ofs, D2Ofs : LONGINT);
(* This one does a fire effect. ********************************************) PROCEDURE DoFire(From, Too, Flame : DWORD);
(* Use this one to init the standard light for the bumpmap. ****************) PROCEDURE InitBump(Light : DWORD); PROCEDURE InitBumpSmall(Light : DWORD);
(* This one does a ripple. *************************************************) VAR Ripple : PROCEDURE(VAR Page1, Page2 : DWORD);
(* This one does the displacement effect. **********************************) PROCEDURE DisPlace(From, Too, Disp : DWORD);
(* Use these to produce some standard distort maps. ************************) PROCEDURE InitTunnel(Distort1, Distort2 : DWORD); PROCEDURE InitTunnel2(Distort1, Distort2 : DWORD); PROCEDURE InitTunnelFast(Distort1, Distort2 : DWORD); PROCEDURE InitFlashke(Distort1, Distort2 : DWORD); PROCEDURE InitSpiral(Distort1, Distort2 : DWORD);
(****************************************************************************) IMPLEMENTATION (****************************************************************************) (* MMX instructions don't take direct operands ... that would btw mean an *) (* opcode with 8 bytes extra :) ... so ... here's some mask I use to mask *) (* out the upper bit of every byte since mmx doesn't have PSRLB !! .. *) (****************************************************************************) CONST SomeBitsOutMask : ARRAY[0..7] OF CHAR = ('','','','','','','',''); Mask512W : ARRAY[0..3] OF WORD = (512,512,512,512); Mask128W : ARRAY[0..3] OF WORD = (128,128,128,128); (****************************************************************************) (* This procedure sets the screenmode to a desired mode number. *) (****************************************************************************) PROCEDURE SetMode(N : DWORD); ASSEMBLER; ASM MOV EAX, [N] (* Get modenr. *) INT $10 (* Call video interrupt. *) END;
(****************************************************************************) (* This one plots a pixel on a 320*200 screen. *) (****************************************************************************) PROCEDURE PutPixel(WHERE : DWORD; (* Offset of destination screen. *) X,Y : DWORD; (* Positions in destination. *) C : BYTE); (* Color of pixel to plot. *) ASSEMBLER; ASM (* What we do here : MEM[Where + X*320 + Y] := C. Just a lot faster :) *) MOV EAX, [X] (* Get the line. *) MOV EDI, [Y] (* Get the column number. *) SHL EAX, 6 (* Line*64 *) ADD EDI, [WHERE] (* Add source pointer to column. *) MOV BL, [C] (* Get Color. *) LEA EAX, [EAX+4*EAX] (* Eax := (Line*64) + 4*(line*64) = Line*320 *) MOV [EDI+EAX], BL (* Put the color in its place. *) END;
(****************************************************************************) (* This one adds a pixel to the value current on screen *) (****************************************************************************) PROCEDURE AddPixel(WHERE : DWORD; (* Offset of destination. *) X,Y : DWORD; (* Positions of destination pixel. *) C : BYTE); (* Amount to add to pixel. *) ASSEMBLER; ASM (* What we do here : MEM[Where + X*320 + Y] +:= C. Just a lot faster :) *) MOV EAX, [X] (* Get the line. *) MOV EDI, [Y] (* Get the column number. *) SHL EAX, 6 (* Line*64 *) ADD EDI, [WHERE] (* Add source pointer to column. *) MOV BL, [C] (* Get Color. *) LEA EAX, [EAX+4*EAX] (* Eax := (Line*64) + 4*(line*64) = Line*320 *) ADD [EDI+EAX], BL (* Add the color to the pixel there. *) END;
(****************************************************************************) (* This one grabs a pixel from a given screen. *) (****************************************************************************) FUNCTION GetPixel(WHERE : DWORD; (* Offset of page to grab pixel from. *) X, Y : DWORD) (* Positions of pixel. *) : BYTE; (* The color returned. *) ASSEMBLER; ASM MOV EDX, [X] (* Get line *) MOV EDI, [Y] (* Get column. *) SHL EDX, 6 (* EDX = Line*64 *) ADD EDI, [WHERE] (* Add offset of source to column. *) LEA EDX, [EDX+4*EDX] (* EDX = (Line*64)+4*(Line*64) = Line*320 *) MOV AL, [EDI+EDX] (* Grab pixel. *) END;
(****************************************************************************) (* This one draws a line on screen in color C *) (****************************************************************************) PROCEDURE Line(WHERE : DWORD; (* Offset of destination. *) X1, Y1, (* Positions of begin pixel. *) X2, Y2 : LONGINT; (* Positions of ending pixel. *) C : BYTE); (* Color to plot line in. *) VAR CX, CY : LONGINT; (* Current X and Current Y. 16:16 fixed point. *) DX, DY : LONGINT; (* Delta X and Delta Y. 16:16 fp. *) L1, L2 : LONGINT; (* Length(L1) and Loop(L2). Temporary variables. *) BEGIN (** Step 0 : Figure out length of line. ***********************************) IF ABS(X2-X1) > ABS(Y2-Y1) THEN L1 := ABS(X2-X1) ELSE L1 := ABS(Y2-Y1); (** Step 1 : Avoid lines that are of 0 length. ****************************) IF L1 = 0 THEN INC(L1); (** Step 2 : Calculate starting positions. ********************************) CX := X1 SHL 16; CY := Y1 SHL 16; (** Step 3 : Calculate delta's. What do we need to add every pixel ? ******) DX := ((X2-X1) SHL 16) DIV L1; DY := ((Y2-Y1) SHL 16) DIV L1; (** Step 4 : Loop for as many pixels as there are in the line. ************) FOR L2 := 0 TO L1 DO BEGIN (** Step 4a : Plot the current pixel. ***********************************) PutPixel(Where, CX SHR 16, CY SHR 16, C); (** Step 4b : Update the positions. *************************************) CX +:= DX; CY +:= DY; END; END;
(****************************************************************************) (* Same thing, but this time adds a line. *) (****************************************************************************) PROCEDURE AddLine(WHERE : DWORD; (* Offset of destination screen. *) X1, Y1, (* Beginpixel positions *) X2, Y2 : LONGINT;(* Endpixel positions. *) C : BYTE); (* Amount to add. *) VAR CX, CY : LONGINT; (* Current X and Current Y. 16:16 fixed point. *) DX, DY : LONGINT; (* Delta X and Delta Y. 16:16 fp. *) L1, L2 : LONGINT; (* Length(L1) and Loop(L2). Temporary variables. *) BEGIN (** Step 0 : Figure out length of line. ***********************************) IF ABS(X2-X1) > ABS(Y2-Y1) THEN L1 := ABS(X2-X1) ELSE L1 := ABS(Y2-Y1); (** Step 1 : Avoid lines that are of 0 length. ****************************) IF L1 = 0 THEN INC(L1); (** Step 2 : Calculate starting positions. ********************************) CX := X1 SHL 16; CY := Y1 SHL 16; (** Step 3 : Calculate delta's. What do we need to add every pixel ? ******) DX := ((X2-X1) SHL 16) DIV L1; DY := ((Y2-Y1) SHL 16) DIV L1; (** Step 4 : Loop for as many pixels as there are in the line. ************) FOR L2 := 0 TO L1 DO BEGIN (** Step 4a : Add to the current pixel. *********************************) AddPixel(Where, CX SHR 16, CY SHR 16, C); (** Step 4b : Update the positions. *************************************) CX +:= DX; CY +:= DY; END; END;
(****************************************************************************) (* This procedure draws a shaded line on where. *) (****************************************************************************) PROCEDURE GshadeLine(WHERE : DWORD; (* Offset of destination. *) X1, Y1, (* Positions of begin pixel. *) X2, Y2 : LONGINT; (* Positions of ending pixel. *) C1, C2 : BYTE); (* Color to plot line in. *) VAR CX, CY, CC : LONGINT; DX, DY, DC : LONGINT; L1, L2 : LONGINT; BEGIN (** Step 0 : Figure out length of line. ***********************************) IF ABS(X2-X1) > ABS(Y2-Y1) THEN L1 := ABS(X2-X1) ELSE L1 := ABS(Y2-Y1); (** Step 1 : Avoid lines that are of 0 length. ****************************) IF L1 = 0 THEN INC(L1); (** Step 2 : Calculate starting positions. ********************************) CX := X1 SHL 16; CY := Y1 SHL 16; CC := C1 SHL 16; (** Step 3 : Calculate delta's. What do we need to add every pixel ? ******) DX := ((X2-X1) SHL 16) DIV L1; DY := ((Y2-Y1) SHL 16) DIV L1; DC := ((C2-C1) SHL 16) DIV L1; (** Step 4 : Loop for as many pixels as there are in the line. ************) FOR L2 := 0 TO L1 DO BEGIN (** Step 4a : Plot the current pixel. ***********************************) PutPixel(Where, CX SHR 16, CY SHR 16, CC SHR 16); (** Step 4b : Update the positions. *************************************) CX +:= DX; CY +:= DY; CC +:= DC; END; END;
(****************************************************************************) (* This procedure sets one palette entry of the VGA to specified colors. *) (****************************************************************************) PROCEDURE SetColor(N, (* Nr of color to set. *) R, G, B : BYTE); (* Red green and blue component. *) (* Color components are expected to be 0-255 !!!!!!!!!!!!!!!!!!!!!!!!!!! *) ASSEMBLER; ASM MOV DX, $3C7 (* Port $3c7 = Set palette write index. *) MOV AL, [N] (* Get the colorNr *) OUT DX, AL (* Send it to the VGA card. *) ADD DX, 2 (* Port $3c9 = Palette data Write/read *) MOV AL, [R] (* Get the red component. *) SHR AL, 2 (* Rescale from 0-255 to standard vga 0-63 *) OUT DX, AL (* Send it to the VGA card. *) MOV AL, [G] (* Get the green component. *) SHR AL, 2 (* Rescale it. *) OUT DX, AL (* Send it. *) MOV AL, [B] (* Get the blue component. *) SHR AL, 2 (* Rescale it. *) OUT DX, AL (* send it. *) END;
(****************************************************************************) (* This procedure creates a shade of colors between N1 and N2 *) (****************************************************************************) PROCEDURE SetColorFade(N1, (* Starting color nr. *) N2, (* Ending color nr. (N1 < N2) *) R1,G1,B1, (* Starting color components. *) R2,G2,B2 : LONGINT);(* Ending color components. *) VAR CR, CG, CB : LONGINT; (* Current red, green and blue values. 16:16 *) DR, DG, DB : LONGINT; (* Delta red, green and blue. 16:16 *) Counter : BYTE; (* a counter. To count shit :) *) BEGIN (** Step 1 : Calculate delta values. **************************************) DR := ( (R2-R1) SHL 16) DIV (N2-N1); DG := ( (G2-G1) SHL 16) DIV (N2-N1); DB := ( (B2-B1) SHL 16) DIV (N2-N1); (** Step 2 : Get starting values. *****************************************) CR := R1 SHL 16; CG := G1 SHL 16; CB := B1 SHL 16; (** Step 3 : Do the shit :) ***********************************************) FOR Counter := N1 TO N2-1 DO BEGIN (* Repeat for all colors. *) PORT[$3c7] := Counter; (* Send color nr. *) PORT[$3c9] := CR SHR 18; CR+:=DR;(* Send current red and update. *) PORT[$3c9] := CG SHR 18; CG+:=DG;(* Send current green and update. *) PORT[$3c9] := CB SHR 18; CB+:=DB;(* Send current blue and update. *) END; END;
(****************************************************************************) (* This one fills the screen with a certain color. *) (****************************************************************************) PROCEDURE FillPage(WHERE : DWORD; Color : BYTE); ASSEMBLER; ASM MOV EDI, [WHERE] MOV AL, [COLOR] MOV AH, AL MOV BX, AX SHL EAX, 16 MOV AX, BX MOV ECX, 16384 @LOOP: MOV [EDI], EAX ADD EDI, 4 DEC ECX JNZ @LOOP END;
(****************************************************************************) (* This one fills the screen completely with 0. mmx version. *) (****************************************************************************) PROCEDURE ClearPage_mmx(Where : DWORD); ASSEMBLER; ASM MOV EDI, [Where] (* Get destination pointer. *) PSLLW mm0, 32 (* Clear mm0 register. *) MOVQ mm1, mm0 (* Clear mm1 too. *) MOV ECX, 4096 (* Repeat 4096 times. (4096*16=65536) *) @LOOP: MOVQ [EDI], mm0 (* Send mm0. *) MOVQ [EDI+8], mm1 (* Send mm1. *) ADD EDI, 16 (* Voila, 16 bytes done. *) DEC ECX (* Decrement counter. *) JNZ @LOOP (* Jump when counter is not zero. *) EMMS (* Exit multimediastate. *) END;
(****************************************************************************) (* This one fills the screen completely with zeroes, x86 version *) (****************************************************************************) PROCEDURE ClearPage_x86(Where : DWORD); ASSEMBLER; ASM MOV EDI, [Where] (* Get destination pointer. *) XOR EAX, EAX (* Clear EAX. *) MOV ECX, 8192 (* Repeat 8192 times. (8192*8=65536) *) @LOOP: MOV [EDI], EAX (* Send EAX. *) MOV [EDI+4], EAX (* Send EAX one dword further. *) ADD EDI, 8 (* Increase destination pointer with 8. *) DEC ECX (* Decrease pixelcounter. *) JNZ @LOOP (* Jump when counter is not zero. *) END;
(****************************************************************************) (* This one copies one page to another, mmx version *) (****************************************************************************) PROCEDURE CopyPage_mmx(From, (* Offset of source page. *) Too : DWORD); (* Offset of destination page. *) ASSEMBLER; ASM MOV EDI, [TOO] (* Get destination pointer. *) MOV ECX, 4096 (* Set counter. (4096*16=65536) *) MOV ESI, [FROM] (* Get source pointer *) @LOOP: MOVQ mm0, [ESI] (* Read First 8 bytes into mm0 *) MOVQ mm1, [ESI+8] (* Read next 8 bytes into mm1 *) ADD ESI, 16 (* Increase sourcepointer with 16 *) MOVQ [EDI], mm0 (* Store first 8 bytes. *) MOVQ [EDI+8], mm1 (* Store next 8 bytes. *) ADD EDI, 16 (* Increase destination pointer with 16 *) DEC ECX (* Decrease loop counter. *) JNZ @LOOP (* Jump unless counter = 0 *) EMMS (* Exit multimediastate *) END;
(****************************************************************************) (* This one copies one page to another, x86 version *) (****************************************************************************) PROCEDURE CopyPage_X86(From, (* Offset of source page. *) Too : DWORD); (* Offset of destination page. *) ASSEMBLER; ASM MOV EDI, [TOO] (* Get destination pointer. *) MOV ECX, 8192 (* Set loop count. *) MOV ESI, [FROM] (* Get source pointer. *) @LOOP: MOV EAX, [ESI] (* Read first four bytes. *) MOV EBX, [ESI+4] (* Read next four bytes. *) ADD ESI, 8 (* Update sourcep pointer. *) MOV [EDI], EAX (* Store first four bytes. *) MOV [EDI+4], EBX (* Store next four bytes. *) ADD EDI, 8 (* Update destination pointer. *) DEC ECX (* Decrease loop counter. *) JNZ @LOOP (* Jump unless counter is zero. *) END;
(****************************************************************************) (* This one copies one page to another, not copying color 0, x86 version *) (****************************************************************************) PROCEDURE CopyPageT(From, Too : DWORD); ASSEMBLER; ASM MOV EDI, [Too] (* Get destination pointer. *) MOV ECX, 65536 (* Set pixel count. *) MOV ESI, [From] (* Get source pointer. *) @LOOP: MOV AL, [ESI] (* Get source pixel. *) CMP AL, 0 (* Compare to 0 *) JZ @SKIP (* If 0 then skip plotting. *) MOV [EDI], AL (* Plot pixel. *) @SKIP: INC ESI (* Increase source pointer. *) INC EDI (* Increase destination pointer. *) DEC ECX (* Decrease loop counter. *) JNZ @LOOP (* Jump unless loopcounter = 0 *) END;
(****************************************************************************) (* This one smudges one page to another. x86 version *) (****************************************************************************) PROCEDURE CopyPageSmudge_x86(From, Too : DWORD); ASSEMBLER; ASM MOV EDI, [TOO] (* Get destination pointer. *) MOV ECX, 63360 (* Set pixel count (skip top/bottom) *) MOV ESI, [FROM] (* Get source addres *) ADD EDI, 320 (* Skip first line on destination. *) ADD ESI, 320 (* And skip first line on source. *) @LOOP: MOVZX EAX, BYTE PTR [ESI-320] (* Get pixel above. *) MOVZX EBX, BYTE PTR [ESI-1] (* Get pixel left. *) MOVZX EDX, BYTE PTR [ESI+1] (* Get pixel right. *) ADD EAX, EBX MOVZX EBX, BYTE PTR [ESI+320] (* Get pixel below. *) ADD EAX, EDX ADD EAX, EBX (* Count four pixels together. *) SHR EAX, 2 (* Divide by four. *) MOV [EDI], AL (* And store the result. *) INC ESI (* Increase source pointer. *) INC EDI (* Increase destination pointer. *) DEC ECX (* Decrease loop count. *) JNZ @LOOP (* Loop until 0 *) END;
(****************************************************************************) (* This one smudges one page to another, mmx version *) (****************************************************************************) PROCEDURE CopyPageSmudge_mmx(From, Too : DWORD); ASSEMBLER; ASM MOV EDI, [TOO] (* Get destination page. *) MOV ECX, 7920 (* Loop count. (7920*8=65536-640) *) MOV ESI, [FROM] (* Get source page. *) ADD EDI, 320 (* Skip first line. *) ADD ESI, 320 (* Also on source. *) PSLLQ mm7, 64 (* Clear mm7 *) @LOOP: MOVQ mm0, QWORD PTR [ESI-320] (* Get 8 pixels above. *) MOVQ mm1, QWORD PTR [ESI-1] (* Get 8 pixels left. *) MOVQ mm2, mm0 (* Copy above pixels. *) MOVQ mm3, mm1 (* Copy left pixels. *) PUNPCKHBW mm0, mm7 (* Unpack 4 above pxls in mm0 to words*) PUNPCKHBW mm1, mm7 (* Unpack 4 left pxls in mm1 to words *) PUNPCKLBW mm2, mm7 (* Unpack low above pxls to words. *) PUNPCKLBW mm3, mm7 (* Unpack low left pxls to words. *) PADDUSW mm0, mm1 (* Add above and left pixels. *) PADDUSW mm2, mm3 (* Add 4 next above and left pixels. *) MOVQ mm4, QWORD PTR [ESI+1] (* Get 8 right pixels. *) MOVQ mm5, QWORD PTR [ESI+320] (* Get 8 below pixels. *) MOVQ mm1, mm4 (* Copy 8 right pixels. *) MOVQ mm3, mm5 (* Copy 8 below pixels. *) PUNPCKHBW mm4, mm7 (* Unpack high right pxls to words. *) PUNPCKHBW mm5, mm7 (* Unpack high below pxls to words. *) PUNPCKLBW mm1, mm7 (* Unpack low right pxls to words. *) PUNPCKLBW mm3, mm7 (* Unpack low below pxls to words. *) PADDUSW mm4, mm5 (* Add right and below pixels. *) PADDUSW mm1, mm3 (* Add other right and below pixels. *) PADDUSW mm0, mm4 (* Now add 4st 4 pixels all together *) PADDUSW mm2, mm1 (* Same for next four. *) PSRLW mm0, 2 (* SHR MM0, 2. Divide by 4 *) PSRLW mm2, 2 (* SHR MM2, 2. Divide by 4 *) PACKUSWB mm2, mm0 (* Pack words in mm2 and mm0 to bytes *) MOVQ [EDI], mm2 (* Store 8 pixels on destination. *) ADD ESI, 8 (* Increase source pointer. *) ADD EDI, 8 (* Increase destination pointer. *) DEC ECX (* Decrease loop counter. *) JNZ @LOOP (* Jump until ECX = 0 *) EMMS (* Exit multimedia state. *) END;
(****************************************************************************) (* This one does a different kind of smudge ... rather fun :) *) (****************************************************************************) PROCEDURE CopyPageSmudge2(From, Too : DWORD); ASSEMBLER; ASM MOV EDI, [TOO] (* Get destination addres *) MOV ECX, 63360 (* Set loop count = 64000-2*320 *) MOV ESI, [FROM] (* Get source. *) ADD EDI, 320 (* Skip first line on destination. *) ADD ESI, 320 (* Skip first line on source. *) @LOOP: MOVZX EAX, BYTE PTR [ESI-320] (* Get pixel above. *) MOVZX EBX, BYTE PTR [ESI-1] (* Get pixel left. *) MOVZX EDX, BYTE PTR [ESI+1] (* Get pixel right. *) ADD EAX, EBX (* EAX := Above + left *) MOVZX EBX, BYTE PTR [ESI+320] (* Get pixel under. *) ADD EAX, EDX (* EAX +:= right. *) MOVZX EDX, BYTE PTR [ESI-321] (* Get pixel aboveleft. *) ADD EAX, EBX (* EAX +:= under. *) MOVZX EBX, BYTE PTR [ESI-319] (* Get pixel aboveright. *) ADD EDX, EBX (* EDX := Aboveleft+Aboveright. *) MOVZX EBX, BYTE PTR [ESI+319] (* Get pixel belowleft. *) ADD EDX, EBX (* EDX +:= belowleft. *) MOVZX EBX, BYTE PTR [ESI+321] (* Get pixel belowright. *) ADD EDX, EBX (* EDX +:= belowright. *) MOVZX EBX, BYTE PTR [ESI] (* Get pixel itself. *) LEA EBX, [EBX+2*EBX] (* Multiply pixel with 3 *) ADD EDX, EBX (* EDX +:= 3*pixel *) SHR EDX, 1 (* EDX /:= 2; *) ADD EAX, EDX (* Add all together. *) SHR EAX, 3 (* Divide by 8 *) MOV [EDI], AL (* And put on source. *) INC ESI (* Increase source pointer. *) INC EDI (* Increase destination pointer. *) DEC ECX (* Decrease loop counter. *) JNZ @LOOP (* Jump until 0 *) END;
(****************************************************************************) (* This one does a putpixel on a 256*256 screen ... (src for rotate). *) (****************************************************************************) PROCEDURE PutPixel255(Where : DWORD; X, Y, C : BYTE); ASSEMBLER; ASM XOR EAX, EAX (* Empty EAX *) MOV EDI, [WHERE] (* Get source addres *) MOV AL, [Y] (* Get column number. *) MOV BL, [C] (* Get color. *) MOV AH, [X] (* Get line number. *) MOV [EDI+EAX], BL (* Store color at correct place. *) END;
(****************************************************************************) (* This one grabs a pixel from a 256*256 screen. *) (****************************************************************************) FUNCTION GetPixel255(Where : DWORD; X, Y : BYTE) : BYTE; ASSEMBLER; ASM XOR EBX, EBX (* Empty EBX. *) MOV EDI, [WHERE] (* Get source addres *) MOV BH, [X] (* Get line. *) MOV BL, [Y] (* Get column. *) MOV AL, [EDI+EBX] (* Get pixel and return it. *) END;
(****************************************************************************) (* This one rotates a 256*256 source image to the screen, tiling it ... *) (****************************************************************************) PROCEDURE Rotate(From, Too : DWORD; (* Source(256) and Destination. *) Rot : DWORD; (* 0 < ROT < 4096 *) X, Y, (* pixelmappedtocenter/256*65535 *) SCALE : LONGINT); (* Sort of scale. *) VAR ANGLE : REAL; (* Temporary real variable. Yuck *) Ddx,Ddy,D2x,D2y : INTEGER; (* Delta's to move over source. *) i,j : INTEGER; (* Starting coordinates in the bitmap.*) BEGIN (* Calculate angle. ******************************************************) angle := rot * 2 * 3.14159236/ 2048;
(* Moving delta's. 8:8 fixed point ***************************************) Ddx:=trunc(((-Cos(angle)*256)) * SCALE) SHR 8; Ddy:=trunc(((Sin(Angle)*256)) * Scale) SHR 8; D2x:=trunc(((-Cos(angle+3.14159265/2) * 341))*SCALE) SHR 8; D2y:=trunc(((Sin(angle+3.14159265/2) * 341))*SCALE) SHR 8;
(* Starting coordinates in the source bitmap. *) i:=X-Ddx*(160)-D2x*(100); j:=y-Ddy*(160)-D2y*(100);
(* Do the shit :) *) ASM MOV ESI, [FROM] (* Get source addres. *) MOV EDI, [TOO] (* Get destination addres. *) MOV ECX, 200 (* The line count. *) @LineLoop: PUSH ECX (* Store the linecount on the stack. *) MOV BX, [I] (* Get starting coordinates for this line. *) MOV DX, [J] (* Store them in the BX and DX registers. *) MOV ECX, 320 (* Set the pixel count. *) XOR EAX, EAX (* Clear the EAX register. *) @PixelLoop: PUSH ECX (* Store the pixelcount on the stack. *) MOV AH, BH (* Get current linenr. *) MOV AL, DH (* Get current column. *) MOV CL, [ESI+EAX] (* Get source pixel. *) MOV [EDI], CL (* Store pixel on destination. *) INC EDI (* Increase destination pointer. *) ADD BX, [DDX] (* Update source positions for next pixel. *) ADD DX, [DDY] (* Update source positions for next pixel. *) POP ECX (* Get pixelcount from stack. *) DEC ECX (* Decrease pixelcount. *) JNZ @PixelLoop (* Jump until pixelcount is 0 *) MOV AX, [D2X] (* Get line update vars. *) MOV CX, [D2Y] (* idem dito. *) ADD [I], AX (* Add these to the starting coordinates of *) ADD [J], CX (* the beginning of the line = move to next *) POP ECX (* Get linecount. *) DEC ECX (* Decrease linecount. *) JNZ @LineLoop (* Jump until linecount = 0 *) END; (**) END;
(****************************************************************************) (* This one rotates a 256*256 source image to the screen and skips color 0 *) (****************************************************************************) PROCEDURE RotateT(From, Too : DWORD; (* Source(256) and Destination. *) Rot : DWORD; (* 0 < ROT < 4096 *) X, Y, (* pixelmappedtocenter/256*65535 *) SCALE : LONGINT); (* Sort of scale. *) VAR ANGLE : REAL; (* Temporary real variable. Yuck *) Ddx,Ddy,D2x,D2y : INTEGER; (* Delta's to move over source. *) i,j : INTEGER; (* Starting coordinates in the bitmap.*) BEGIN (* Calculate angle. ******************************************************) angle := rot * 2 * 3.14159236/ 2048;
(* Moving delta's. 8:8 fixed point ***************************************) Ddx:=trunc(((-Cos(angle)*256)) * SCALE) SHR 8; Ddy:=trunc(((Sin(Angle)*256)) * Scale) SHR 8; D2x:=trunc(((-Cos(angle+3.14159265/2) * 341))*SCALE) SHR 8; D2y:=trunc(((Sin(angle+3.14159265/2) * 341))*SCALE) SHR 8;
(* Starting coordinates in the source bitmap. *) i:=X-Ddx*(160)-D2x*(100); j:=y-Ddy*(160)-D2y*(100);
(* Do the shit :) *) ASM MOV ESI, [FROM] (* Get source addres. *) MOV EDI, [TOO] (* Get destination addres. *) MOV ECX, 200 (* The line count. *) @LineLoop: PUSH ECX (* Store the linecount on the stack. *) MOV BX, [I] (* Get starting coordinates for this line. *) MOV DX, [J] (* Store them in the BX and DX registers. *) MOV ECX, 320 (* Set the pixel count. *) XOR EAX, EAX (* Clear the EAX register. *) @PixelLoop: PUSH ECX (* Store the pixelcount on the stack. *) MOV AH, BH (* Get current linenr. *) MOV AL, DH (* Get current column. *) MOV CL, [ESI+EAX] (* Get source pixel. *) CMP CL, 0 (* Check if source pixel is 0 *) JZ @Skip (* If it is 0 then skip the plotting. *) MOV [EDI], CL (* Store pixel on destination. *) @Skip: INC EDI (* Increase destination pointer. *) ADD BX, [DDX] (* Update source positions for next pixel. *) ADD DX, [DDY] (* Update source positions for next pixel. *) POP ECX (* Get pixelcount from stack. *) DEC ECX (* Decrease pixelcount. *) JNZ @PixelLoop (* Jump until pixelcount is 0 *) MOV AX, [D2X] (* Get line update vars. *) MOV CX, [D2Y] (* idem dito. *) ADD [I], AX (* Add these to the starting coordinates of *) ADD [J], CX (* the beginning of the line = move to next *) POP ECX (* Get linecount. *) DEC ECX (* Decrease linecount. *) JNZ @LineLoop (* Jump until linecount = 0 *) END; (**) END;
(****************************************************************************) (* This one rotates a 256*256 source image to the screen and skips color 0 *) (* and warps the image. *) (****************************************************************************) PROCEDURE RotateTW(From, Too : DWORD; Rot : DWORD; X, Y, SCALE : LONGINT; WARPX, WARPY : WORD); VAR ANGLE : REAL; (* Yuck :) *) Ddx,Ddy,D2x,D2y : INTEGER; i,j : INTEGER; WARPDDY : INTEGER; BEGIN (* Sin and cos only 4 for every screen ... aint gonna waist a look- *) (* up table on that ! *) angle := rot * 2*3.14159236 / 2048;
(* Fixed Point Verplaatsingsvectoren geroteerd en gewogen(scale) *) Ddx:=trunc(((-Cos(angle)*256)) * SCALE) SHR 8; Ddy:=trunc(((Sin(Angle)*256)) * Scale) SHR 8; D2x:=trunc(((-Cos(angle+3.14159265/2) * 341))*SCALE) SHR 8; D2y:=trunc(((Sin(angle+3.14159265/2) * 341))*SCALE) SHR 8;
(* Starting coordinates in the source bitmap. *) i:=X-Ddx*(160)-D2x*(100); j:=y-Ddy*(160)-D2y*(100);
(* Do the shit :) *) ASM MOV ESI, [FROM] MOV EDI, [TOO] MOV ECX, 200 @LineLoop: PUSH ECX MOV BX, [I] MOV DX, [J] MOV ECX, 320 MOV AX, [DDY] MOV [WarpDDY], AX XOR EAX, EAX @PixelLoop: MOV AH, BH MOV AL, DH SHL EBX, 8 MOV BL, [ESI+EAX] CMP BL, 0 JZ @SKIP MOV [EDI], BL @SKIP: INC EDI SHR EBX, 8 MOV AX, [WarpDDY] ADD DX, AX ADD AX, [WarpY] MOV [WarpDDY], AX ADD BX, [DDX] DEC ECX JNZ @PixelLoop MOV AX, [D2X] MOV CX, [D2Y] ADD [I], AX ADD [J], CX POP ECX ADD AX, [WARPX] MOV [D2X], AX DEC ECX JNZ @LineLoop END; (**) END;
(****************************************************************************) (* This one rotates a 256*256 source image to the screen and skips color 0 *) (* and warps the image. (Slower but high precision warping.) *) (****************************************************************************) PROCEDURE RotateTW2(From, Too : DWORD; Rot : DWORD; X, Y, SCALE, WARPX, WARPY : LONGINT); VAR ANGLE : REAL; (* Yuck :) *) Ddx,Ddy,D2x,D2y : LONGINT; i,j : LONGINT; WARPDDY : LONGINT; BEGIN (* Sin and cos only 4 for every screen ... aint gonna waist a look- *) (* up table on that ! *) angle := rot * 2*3.14159236 / 2048;
(* Fixed Point Verplaatsingsvectoren geroteerd en gewogen(scale) *) Ddx:=trunc(((-Cos(angle)*65536)) * SCALE) SHR 8; Ddy:=trunc(((Sin(Angle)*65536)) * Scale) SHR 8; D2x:=trunc(((-Cos(angle+3.14159265/2) * 87296))*SCALE) SHR 8; D2y:=trunc(((Sin(angle+3.14159265/2) * 87296))*SCALE) SHR 8;
(* Starting coordinates in the source bitmap. *) i:=(X SHL 8)-(Ddx)*(160)-(D2x + 100 * WarpX)*(100); j:=(y SHL 8)-(Ddy + 160*WarpY)*(160)-(D2y)*(100);
(* Do the shit :) *) ASM MOV ESI, [FROM] MOV EDI, [TOO] MOV ECX, 200 @LineLoop: PUSH ECX MOV EBX, [I] MOV EDX, [J] MOV ECX, 320 MOV EAX, [DDY] MOV [WarpDDY], EAX XOR EAX, EAX @PixelLoop: PUSH ECX XOR EAX, EAX MOV ECX, EBX SHR ECX, 8 MOV AH, CH MOV ECX, EDX SHR ECX, 8 MOV AL, CH MOV CL, [ESI+EAX] CMP CL, 0 JZ @SKIP MOV [EDI], CL @SKIP: INC EDI MOV EAX, [WarpDDY] ADD EDX, EAX ADD EAX, [WarpY] MOV [WarpDDY], EAX ADD EBX, [DDX] POP ECX DEC ECX JNZ @PixelLoop MOV EAX, [D2X] MOV ECX, [D2Y] ADD [I], EAX ADD [J], ECX POP ECX ADD EAX, [WARPX] MOV [D2X], EAX DEC ECX JNZ @LineLoop END; (**) END;
(****************************************************************************) (* This one mixes two pages and stores the result. x86 version *) (****************************************************************************) PROCEDURE MixPages_x86(From1, From2, Too : DWORD); ASSEMBLER; ASM MOV ESI, [FROM1] MOV EBX, [FROM2] MOV EDI, [TOO] MOV ECX, 64000 @PixelLoop: MOVZX EAX, BYTE PTR [ESI] INC ESI MOVZX EDX, BYTE PTR [EBX] INC EBX ADD EAX, EDX SHR EAX, 1 MOV [EDI], AL INC EDI DEC ECX JNZ @PixelLoop END;
(****************************************************************************) (* This one mixes two pages and stores. mmx version *) (****************************************************************************) PROCEDURE MixPages_MMX(From1, From2, Too : DWORD); ASSEMBLER; ASM MOV ESI, [FROM1] MOV EBX, [FROM2] MOV EDI, [TOO] MOVQ mm2, QWORD PTR [SomeBitsOutMask] MOV ECX, 8192 @PixelLoop: MOVQ mm0, [ESI] ADD ESI, 8 MOVQ mm1, [EBX] PSRLQ mm0, 1 PSRLQ mm1, 1 PAND mm0, mm2 PAND mm1, mm2 ADD EBX, 8 PADDUSB mm0, mm1 MOVQ [EDI], mm0 ADD EDI, 8 DEC ECX JNZ @PixelLoop EMMS END;
(****************************************************************************) (* This one mixes pages with saturation, just (A+B) and trim on 255 *) (****************************************************************************) PROCEDURE MixPages2_x86(From1, From2, Too : DWORD); ASSEMBLER; ASM MOV ESI, [FROM1] MOV EBX, [FROM2] MOV EDI, [TOO] MOV ECX, 64000 @PixelLoop: MOVZX EAX, BYTE PTR [ESI] INC ESI MOVZX EDX, BYTE PTR [EBX] INC EBX ADD EAX, EDX CMP EAX, 255 JB @OK MOV AL, 255 @OK: MOV [EDI], AL INC EDI DEC ECX JNZ @PixelLoop END;
(****************************************************************************) (* This one does a saturated add of two pages, mmx version *) (****************************************************************************) PROCEDURE MixPages2_MMX(From1, From2, Too : DWORD); ASSEMBLER; ASM MOV ESI, [FROM1] MOV EBX, [FROM2] MOV EDI, [TOO] MOV ECX, 8000 @PixelLoop: MOVQ mm0, [ESI] ADD ESI, 8 MOVQ mm1, [EBX] ADD EBX, 8 PADDUSB mm0, mm1 MOVQ [EDI], mm0 ADD EDI, 8 DEC ECX JNZ @PixelLoop EMMS END;
(****************************************************************************) (* This one does an alphablended mix of two pages. *) (****************************************************************************) PROCEDURE MixPages3_x86(From1, From2, Too : DWORD; Amount : BYTE);ASSEMBLER; ASM MOV ESI, [FROM1] MOV EBX, [FROM2] MOV ECX, 64000 MOV EDI, [TOO] @LOOP: MOV AL, [ESI] MUL [amount] MOV DH, AH MOV AL, [EBX] MOV DL, [Amount] NOT DL MUL DL SHR AX, 8 ADD AL, DH MOV [EDI], AL INC ESI INC EBX INC EDI DEC ECX JNZ @LOOP END;
(****************************************************************************) (* This one does an alphablended mix of two pages. mmx version. *) (****************************************************************************) PROCEDURE MixPages3_mmx(FROM1, FROM2, TOO : DWORD; Amount : BYTE); ASSEMBLER; ASM MOV ESI, [FROM1] MOVZX DX, [Amount] MOV EBX, [FROM2] SHL EDX, 16 MOV EDI, [TOO] MOV ECX, 8000 MOVZX DX, [Amount] MOV AX, DX NOT AL SHL EAX, 16 MOV AX, DX NOT AL MOVD mm0, EDX MOVD mm1, EDX PSLLQ mm1, 32 POR mm0, mm1 MOVD mm1, EAX MOVD mm2, EAX PSLLQ mm2, 32 POR mm1, mm2 PSLLQ mm7, 64 @QuadPixelLoop: MOVQ mm2, [ESI] MOVQ mm3, [EBX] MOVQ mm4, mm2 MOVQ mm5, mm3 PUNPCKHBW mm2, mm7 PUNPCKLBW mm4, mm7 PMULLW mm2, mm0 PUNPCKHBW mm3, mm7 PMULLW mm4, mm0 PUNPCKLBW mm5, mm7 PMULLW mm3, mm1 ADD ESI, 8 PMULLW mm5, mm1 PADDUSW mm2, mm3 ADD EBX, 8 PADDUSW mm4, mm5 PSRLW mm2, 8 PSRLW mm4, 8 PACKUSWB mm4, mm2 MOVQ [EDI], mm4 ADD EDI, 8 DEC ECX JNZ @QuadPixelLoop EMMS END;
(****************************************************************************) (* This one does a bump-map. *) (****************************************************************************) PROCEDURE BumpMap(FROM, TOO, LIGHT : DWORD; LX, LY : WORD); ASSEMBLER; VAR X, Y : WORD; ASM MOV ESI, [FROM] MOV EDI, [TOO] MOV EDX, [LIGHT] MOV ECX, 63360 ADD ESI, 320 ADD EDI, 320 MOV [X], 0 MOV [Y], 0 @PixelLoop: MOVZX EAX, BYTE [ESI-320] MOV AH, BYTE [ESI+320] SUB AL, AH MOV BH, BYTE [ESI-1] MOV BL, BYTE [ESI+1] SUB BL, BH MOV AH, 0 MOV BH, 0 ADD AX, [LX] ADD BX, [LY] ADD AX, [X] ADD BX, [Y] MOV AH, BL INC [X] CMP [X], 320 JNZ @NO INC [Y] MOV [X], 0; @NO: MOV BL, [EDX+EAX] MOV [EDI], BL INC ESI INC EDI DEC ECX JNZ @PixelLoop END;
(****************************************************************************) (* This one does a bump-map. (no tiled lights) *) (****************************************************************************) PROCEDURE BumpMap2(FROM, TOO, LIGHT : DWORD; LX, LY : INTEGER); ASSEMBLER; VAR X, Y : WORD; ASM MOV ESI, [FROM] MOV EDI, [TOO] MOV ECX, 63360 ADD ESI, 320 ADD EDI, 320 MOV [X], 0 MOV [Y], 0 @PixelLoop: MOVZX EAX, BYTE [ESI-320] MOVZX DX, BYTE [ESI+320] SUB AX, DX MOVZX BX, BYTE [ESI-1] MOVZX DX, BYTE [ESI+1] SUB BX, DX ADD AX, [LX] ADD BX, [LY] ADD AX, [X] ADD BX, [Y] CMP AH, 0 JZ @XinRange MOV AL, 0 MOV BL, 0 @XinRange: CMP BH, 0 JZ @YinRange MOV AL, 0 MOV BL, 0 @YinRange: MOV AH, BL INC [X] MOV EDX, [LIGHT] CMP [X], 320 JNZ @NO INC [Y] MOV [X], 0; @NO: MOV BL, [EDX+EAX] MOV [EDI], BL INC ESI INC EDI DEC ECX JNZ @PixelLoop END;
(****************************************************************************) (* This one does a bump-map. (no tiled lights, no color 0) *) (****************************************************************************) PROCEDURE BumpMap2T(FROM, TOO, LIGHT : DWORD; LX, LY : INTEGER); ASSEMBLER; VAR X, Y : WORD; ASM MOV ESI, [FROM] MOV EDI, [TOO] MOV ECX, 63360 ADD ESI, 320 ADD EDI, 320 MOV [X], 0 MOV [Y], 0 @PixelLoop: MOV BL, BYTE PTR [ESI] CMP BL, 0 JZ @Skip MOVZX EAX, BYTE [ESI-320] MOVZX DX, BYTE [ESI+320] SUB AX, DX MOVZX BX, BYTE [ESI-1] MOVZX DX, BYTE [ESI+1] SUB BX, DX ADD AX, [LX] ADD BX, [LY] ADD AX, [X] ADD BX, [Y] CMP AH, 0 JZ @XinRange MOV AL, 0 MOV BL, 0 @XinRange: CMP BH, 0 JZ @YinRange MOV AL, 0 MOV BL, 0 @YinRange: MOV AH, BL MOV EDX, [LIGHT] MOV BL, [EDX+EAX] @Skip: INC [X] CMP [X], 320 JNZ @NO INC [Y] MOV [X], 0; @NO: MOV [EDI], BL INC ESI INC EDI DEC ECX JNZ @PixelLoop END;
(****************************************************************************) (* This one does a bump-map. (no tiled lights) *) (****************************************************************************) PROCEDURE BumpMap3(FROM, TOO, LIGHT : DWORD; LX, LY : INTEGER); ASSEMBLER; VAR X, Y : WORD; ASM MOV ESI, [FROM] MOV EDI, [TOO] MOV ECX, 63360 ADD ESI, 320 ADD EDI, 320 MOV [X], 0 MOV [Y], 0 @PixelLoop: MOVZX EAX, BYTE [ESI-320] MOVZX DX, BYTE [ESI+320] SUB AX, DX MOVZX EBX, BYTE [ESI-1] MOVZX DX, BYTE [ESI+1] SUB BX, DX ADD AX, [LX] ADD BX, [LY] ADD AX, [X] ADD BX, [Y] MOVZX DX, BYTE [ESI] NOT DL SHR DL, 1 ADD DL, 128 MUL DX SHR EAX, 8 MOV AH, DL XCHG EAX, EBX MOVZX DX, BYTE [ESI] NOT DL SHR DL, 1 ADD DL, 128 MUL DX SHR EAX, 8 MOV AH, DL XCHG EAX, EBX CMP AH, 0 JZ @XinRange MOV AL, 0 MOV BL, 0 @XinRange: CMP BH, 0 JZ @YinRange MOV AL, 0 MOV BL, 0 @YinRange: MOV AH, BL INC [X] MOV EDX, [LIGHT] CMP [X], 320 JNZ @NO INC [Y] MOV [X], 0; @NO: MOV BL, [EDX+EAX] MOV [EDI], BL INC ESI INC EDI DEC ECX JNZ @PixelLoop END;
(****************************************************************************) (* This one does a bump-map. (slope+heights+transparent) *) (****************************************************************************) PROCEDURE BumpMap3t(FROM, TOO, LIGHT : DWORD; LX, LY : INTEGER); ASSEMBLER; VAR X, Y : WORD; ASM MOV ESI, [FROM] MOV EDI, [TOO] MOV ECX, 63360 ADD ESI, 320 ADD EDI, 320 MOV [X], 0 MOV [Y], 0 @PixelLoop: MOV BL, [ESI] CMP BL, 0 JZ @Skip MOVZX EAX, BYTE [ESI-320] MOVZX DX, BYTE [ESI+320] SUB AX, DX MOVZX EBX, BYTE [ESI-1] MOVZX DX, BYTE [ESI+1] SUB BX, DX ADD AX, [LX] ADD BX, [LY] ADD AX, [X] ADD BX, [Y] MOVZX DX, BYTE [ESI] NOT DL SHR DL, 1 ADD DL, 128 MUL DX SHR EAX, 8 MOV AH, DL XCHG EAX, EBX MOVZX DX, BYTE [ESI] NOT DL SHR DL, 1 ADD DL, 128 MUL DX SHR EAX, 8 MOV AH, DL XCHG EAX, EBX CMP AH, 0 JZ @XinRange MOV AL, 0 MOV BL, 0 @XinRange: CMP BH, 0 JZ @YinRange MOV AL, 0 MOV BL, 0 @YinRange: MOV AH, BL MOV EDX, [LIGHT] MOV BL, [EDX+EAX] @Skip: INC [X] CMP [X], 320 JNZ @NO INC [Y] MOV [X], 0; @NO: MOV [EDI], BL INC ESI INC EDI DEC ECX JNZ @PixelLoop END;
(****************************************************************************) (* This one scales a 320*200 to 256*256 to use as source for rotate :) *) (****************************************************************************) PROCEDURE Scale320to256(FROM, TOO : DWORD); ASSEMBLER; VAR EEX, EFX : LONGINT; ASM MOV ESI, [FROM] MOV EDI, [TOO] MOV ECX, 256 MOV [EFX], 0 @LineLoop: PUSH ECX MOV [EEX], 0 MOV ECX, 256 @PixelLoop: MOV EAX, [EFX] MOV EBX, [EEX] SHR EAX, 8 SHR EBX, 8 MOV EDX, 320 mul EDX ADD EAX, EBX MOV DL, [ESI+EAX] MOV [EDI], DL INC EDI ADD [EEX], 320 DEC CL JNZ @PixelLoop ADD [EFX], 200 POP ECX DEC ECX JNZ @LineLoop END;
(****************************************************************************) (* This one scales a 256*256 to 320*200. *) (****************************************************************************) PROCEDURE Scale256to320(FROM, TOO : DWORD); VAR CX, CY : LONGINT; DX, DY : LONGINT; W1, W2 : LONGINT; BEGIN DX := (255 SHL 8) DIV 199; DY := (255 SHL 8) DIV 319; CX := 0; CY := 0; FOR W1 := 0 TO 199 DO BEGIN CY := 0; FOR W2 := 0 TO 319 DO BEGIN PutPixel(Too, W1, W2, GetPixel255(From, CX SHR 8, CY SHR 8)); CY +:= DY; END; CX +:= DX; END; END;
(****************************************************************************) (* This one applys two relocation maps to from. (from is 255*255 !) *) (****************************************************************************) PROCEDURE Relocate(From, Too, Distort1, Distort2, D1Ofs, D2Ofs : LONGINT); ASSEMBLER; ASM MOV ESI, [FROM] MOV EDI, [TOO] MOV EDX, [Distort1] MOV EBX, [Distort2] MOV ECX, 64000 @LOOP: PUSH ECX MOVZX EAX, BYTE PTR [EDX] ADD EAX, [D1Ofs] SHL EAX, 8 MOVZX ECX, BYTE PTR [EBX] SHL ECX, 1 ADD ECX, [D2Ofs] ADD EAX, ECX AND EAX, $FFFF MOV CL, [ESI+EAX] MOV [EDI], CL INC EDX INC EBX INC EDI POP ECX DEC ECX JNZ @Loop END;
(****************************************************************************) (* Same, but doesn't draw color 0 *) (****************************************************************************) PROCEDURE RelocateT(From, Too, Distort1, Distort2, D1Ofs, D2Ofs : LONGINT); ASSEMBLER; ASM MOV ESI, [FROM] MOV EDI, [TOO] MOV EDX, [Distort1] MOV EBX, [Distort2] MOV ECX, 64000 @LOOP: PUSH ECX MOVZX EAX, BYTE PTR [EDX] ADD EAX, [D1Ofs] SHL EAX, 8 MOVZX ECX, BYTE PTR [EBX] SHL ECX, 1 ADD ECX, [D2Ofs] ADD EAX, ECX AND EAX, $FFFF MOV CL, [ESI+EAX] CMP CL, 0 JZ @Skip MOV [EDI], CL @Skip: INC EDX INC EBX INC EDI POP ECX DEC ECX JNZ @Loop END;
(****************************************************************************) (* This one does a ripple. (X86 version) *) (****************************************************************************) PROCEDURE Ripple_x86(VAR Page1, Page2 : DWORD); ASSEMBLER; ASM MOV ECX, [Page1] MOV EDX, [Page2] MOV ESI, [ECX] MOV EDI, [EDX] MOV [ECX], EDI MOV [EDX], ESI ADD ESI, 320 ADD EDI, 320 MOV ECX, 63360 @LOOP: MOVZX EAX, BYTE [ESI-320] MOVZX EBX, BYTE [ESI-1] MOVZX EDX, BYTE [ESI+1] ADD EAX, EBX MOVZX EBX, BYTE [ESI+320] ADD EAX, EDX MOVZX EDX, BYTE [EDI] ADD EAX, EBX SUB EAX, 512 SUB EDX, 128 INC ESI SAR EAX, 1 SUB EAX, EDX MOV EBX, EAX SAR EAX, 5 SUB EBX, EAX MOV EAX, EBX ADD EAX, 128 CMP EAX, 0 JA @OK1 MOV EAX, 0 @OK1: CMP EAX, 255 JB @OK2 MOV EAX, 255 @OK2: MOV [EDI], AL INC EDI DEC ECX JNZ @Loop END;
(****************************************************************************) (* This one does a ripple. (mmx version) *) (****************************************************************************) PROCEDURE Ripple_mmx(VAR Page1, Page2 : DWORD); ASSEMBLER; ASM MOV ECX, [Page1] MOV EDX, [Page2] MOV ESI, [ECX] MOV EDI, [EDX] MOV [ECX], EDI MOV [EDX], ESI MOV ECX, 7920 (* Loop count. (7920*8=65536-640) *) ADD EDI, 320 (* Skip first line. *) ADD ESI, 320 (* Also on source. *) PSLLQ mm7, 64 (* Clear mm7 *) @LOOP: MOVQ mm0, QWORD PTR [ESI-320] (* Get 8 pixels above. *) MOVQ mm1, QWORD PTR [ESI-1] (* Get 8 pixels left. *) MOVQ mm2, mm0 (* Copy above pixels. *) MOVQ mm3, mm1 (* Copy left pixels. *) PUNPCKHBW mm0, mm7 (* Unpack 4 above pxls in mm0 to words*) PUNPCKHBW mm1, mm7 (* Unpack 4 left pxls in mm1 to words *) PUNPCKLBW mm2, mm7 (* Unpack low above pxls to words. *) PUNPCKLBW mm3, mm7 (* Unpack low left pxls to words. *) PADDUSW mm0, mm1 (* Add above and left pixels. *) PADDUSW mm2, mm3 (* Add 4 next above and left pixels. *) MOVQ mm4, QWORD PTR [ESI+1] (* Get 8 right pixels. *) MOVQ mm5, QWORD PTR [ESI+320] (* Get 8 below pixels. *) MOVQ mm1, mm4 (* Copy 8 right pixels. *) MOVQ mm3, mm5 (* Copy 8 below pixels. *) PUNPCKHBW mm4, mm7 (* Unpack high right pxls to words. *) PUNPCKHBW mm5, mm7 (* Unpack high below pxls to words. *) PUNPCKLBW mm1, mm7 (* Unpack low right pxls to words. *) PUNPCKLBW mm3, mm7 (* Unpack low below pxls to words. *) PADDUSW mm4, mm5 (* Add right and below pixels. *) PADDUSW mm1, mm3 (* Add other right and below pixels. *) PADDUSW mm0, mm4 (* Now add 4st 4 pixels all together *) PADDUSW mm2, mm1 (* Same for next four. *) PSUBW mm0, [MASK512W] PSUBW mm2, [MASK512W] MOVQ mm4, QWORD PTR [EDI] MOVQ mm1, mm4 PUNPCKHBW mm4, mm7 PUNPCKLBW mm1, mm7 PSUBW mm4, [MASK128W] PSUBW mm1, [MASK128W] PSRAW mm0, 1 PSRAW mm2, 1 PSUBW mm0, mm4 PSUBW mm2, mm1 MOVQ mm3, mm0 MOVQ mm4, mm2 PSRAW mm3, 5 PSRAW mm4, 5 PSUBW mm0, mm3 PSUBW mm2, mm4 PADDW mm0, [MASK128W] PADDW mm2, [MASK128W] PACKUSWB mm2, mm0 (* Pack words in mm2 and mm0 to bytes *) MOVQ [EDI], mm2 (* Store 8 pixels on destination. *) ADD ESI, 8 (* Increase source pointer. *) ADD EDI, 8 (* Increase destination pointer. *) DEC ECX (* Decrease loop counter. *) JNZ @LOOP (* Jump until ECX = 0 *) EMMS (* Exit multimedia state. *) END;
(****************************************************************************) (* Displacement effect. *) (****************************************************************************) PROCEDURE DisPlace(From, Too, Disp : DWORD); ASSEMBLER; ASM MOV EDI, [Too] MOV ESI, [Disp] ADD EDI, 320 MOV EDX, 1 @LineLoop: XOR ECX, ECX @PixelLoop: PUSH EDX PUSH ECX MOVZX EBX, BYTE [ESI-320] MOVZX EAX, BYTE [ESI+320] SUB EBX, EAX ADD EDX, EBX MOVZX EBX, BYTE [ESI-1] MOVZX EAX, BYTE [ESI+1] SUB EBX, EAX ADD ECX, EBX CMP ECX, 0 JA @OK1 MOV ECX, 0 @OK1: CMP ECX, 319 JB @OK2 MOV ECX, 319 @OK2: CMP EDX, 0 JA @OK3 MOV EDX, 0 @OK3: CMP EDX, 199 JB @OK4 MOV EDX, 199 @OK4: LEA EDX, [EDX+4*EDX] MOV EBX, 0 SHL EDX, 6 ADD EDX, ECX MOV EBX, [FROM] MOV AL, [EBX+EDX] MOV BYTE [EDI], AL INC EDI INC ESI POP ECX POP EDX INC ECX CMP ECX, 320 JNZ @PixelLoop INC EDX CMP EDX, 195 JNZ @LineLoop END;
(****************************************************************************) (* This one does a fire effect. *) (****************************************************************************) PROCEDURE DoFire(From, Too, Flame : DWORD); ASSEMBLER; ASM MOV EDI, [TOO] MOV ECX, 63360 MOV ESI, [FROM] MOV EDX, [Flame] @LOOP: MOVZX EAX, BYTE PTR [ESI] MOVZX EBX, BYTE PTR [ESI+319] ADD EAX, EBX MOVZX EBX, BYTE PTR [ESI+320] SHL EBX, 2 ADD EAX, EBX MOVZX EBX, BYTE PTR [ESI+321] ADD EAX, EBX MOVZX EBX, BYTE PTR [ESI+640] ADD EAX, EBX SHR EAX, 3 MOVZX EBX, BYTE PTR [EDX] SHR EBX, 3 SUB EAX, EBX JNS @Skip MOV AL, 0 @Skip: MOV [EDI], AL INC ESI INC EDI INC EDX DEC ECX JNZ @LOOP END;
(****************************************************************************) (* Initialise two distortion maps for tunnel effect. *) (****************************************************************************) PROCEDURE InitTunnel(Distort1, Distort2 : DWORD); VAR W1, W2, W3, W4, W5 : LONGINT; R1, R2, R3 : REAL; BEGIN FOR W1:=-100 TO 99 DO FOR W2:=-160 TO 159 DO BEGIN IF W1<>0 THEN W3:=W1 ELSE W3:=1; IF W2<>0 THEN W4:=W2 ELSE W4:=1; R1:=Trunc(Exp(Ln(262144*(SQRT(W1*W1+W2*W2)+0.001))*0.1)*256); W5:=trunc(R1+(32*Sin(R1*1.284/64))); PutPixel(Distort1, W1+100, W2+160, W5 AND $FF); END; FOR W1:=-100 TO 99 DO FOR W2:=-160 TO 159 DO BEGIN IF W1<>0 THEN R2:=W1 ELSE R2:=0.0001; IF W2<>0 THEN R3:=W2 ELSE R3:=0.0001; R1:=ArcTan(R3/R2)*(256/6.284); W3:=Trunc(R1); PutPixel(Distort2, W1+100, W2+160, W3 AND $FF); END; END;
(****************************************************************************) (* Initialise two distortion maps for tunnel effect. *) (****************************************************************************) PROCEDURE InitTunnel2(Distort1, Distort2 : DWORD); VAR W1, W2, W3, W4, W5 : LONGINT; R1, R2, R3 : REAL; BEGIN FOR W1:=-100 TO 99 DO FOR W2:=-160 TO 159 DO BEGIN IF W1<>0 THEN W3:=W1 ELSE W3:=1; IF W2<>0 THEN W4:=W2 ELSE W4:=1; R1:=Trunc(Exp(Ln(262144*(SQRT(W1*W1+W2*W2)+0.001))*0.1)*256); W5:=trunc(R1+(32*Sin(R1*1.284/64))); W5:=TRUNC(R1); PutPixel(Distort1, W1+100, W2+160, W5 AND $FF); END; FOR W1:=-100 TO 99 DO FOR W2:=-160 TO 159 DO BEGIN IF W1<>0 THEN R2:=W1 ELSE R2:=0.0001; IF W2<>0 THEN R3:=W2 ELSE R3:=0.0001; R1:=ArcTan(R3/R2)*(256/6.284) + ArcTan(SQRT(W1*W1+W2*W2))*2000; W3:=Trunc(R1); PutPixel(Distort2, W1+100, W2+160, W3 AND $FF); END; END;
(****************************************************************************) (* Initialise two distortion maps for tunnel effect. *) (****************************************************************************) PROCEDURE InitTunnelFast(Distort1, Distort2 : DWORD); VAR W1, W2, W3, W4, W5 : LONGINT; R1, R2, R3 : REAL; BEGIN FOR W1:=-100 TO 99 DO FOR W2:=-160 TO 159 DO BEGIN IF W1<>0 THEN W3:=W1 ELSE W3:=1; IF W2<>0 THEN W4:=W2 ELSE W4:=1; R1:=TRUNC(SQRT(((W3*W3)+(W4*W4)))); R1:=Trunc(Exp((Ln(Ln(256*R1))*0.41))*256); W5:=Trunc(r1+(64*Cos(R1*1.284/64))); PutPixel(Distort1, W1+100, W2+160, W5 AND $FF); END; FOR W1:=-100 TO 99 DO FOR W2:=-160 TO 159 DO BEGIN IF W1<>0 THEN R2:=W1 ELSE R2:=0.0001; IF W2<>0 THEN R3:=W2 ELSE R3:=0.0001; R1:=ArcTan(R3/R2)*(256/6.284); W3:=Trunc(R1); PutPixel(Distort2, W1+100, W2+160, W3 AND $FF); END; END;
(****************************************************************************) (* Initialise two distortion maps for flashke effect. *) (****************************************************************************) PROCEDURE InitFlashke(Distort1, Distort2 : DWORD); VAR W1, W2, W3, W4, W5 : LONGINT; R1, R2, R3 : REAL; BEGIN FOR W1:=-100 TO 99 DO FOR W2:=-160 TO 159 DO BEGIN IF W1<>0 THEN W3:=W1 ELSE W3:=1; IF W2<>0 THEN W4:=W2 ELSE W4:=1; R1:=TRUNC(SQRT(((W3*W3)+(W4*W4)))); R1:=Trunc(Exp(Ln(256*R1)*0.21)*256); W5:=Trunc(R1+(64*Cos(R1*1.284/32))); PutPixel(Distort1, W1+100, W2+160, W5 AND $FF); END; FOR W1:=-100 TO 99 DO FOR W2:=-160 TO 159 DO BEGIN IF W1<>0 THEN R2:=W1 ELSE R2:=0.0001; IF W2<>0 THEN R3:=W2 ELSE R3:=0.0001; R1:=ArcTan(R3/R2)*(256/6.284) + SQRT(R2*R2 + R3*R3); W3:=Trunc(R1); PutPixel(Distort2, W1+100, W2+160, W3 AND $FF); END; END;
(****************************************************************************) (* Initialise two distortion maps for flashke effect. *) (****************************************************************************) PROCEDURE InitSpiral(Distort1, Distort2 : DWORD); VAR W1, W2, W3, W4, W5 : LONGINT; R1, R2, R3 : REAL; BEGIN FOR W1:=-100 TO 99 DO FOR W2:=-160 TO 159 DO BEGIN IF W1<>0 THEN W3:=W1 ELSE W3:=1; IF W2<>0 THEN W4:=W2 ELSE W4:=1; R1:=TRUNC(SQRT(((W3*W3)+(W4*W4)))); R1:=Trunc((exp(ln( ABS(Sin(R1/256))*128 )*0.2))*256); W5:=TRUNC(r1/(sin(R1/256)/cos(r1/256))); PutPixel(Distort1, W1+100, W2+160, W5 AND $FF); END; FOR W1:=-100 TO 99 DO FOR W2:=-160 TO 159 DO BEGIN IF W1<>0 THEN R2:=W1 ELSE R2:=0.0001; IF W2<>0 THEN R3:=W2 ELSE R3:=0.0001; R1:=(ArcTan(R3/R2)*(256/6.284)*4) + SIN(SQRT((SQR(R2)+SQR(R3))/256))*64 + COS(SQRT((SQR(R2)+SQR(R3))/256))*64; W3:=Trunc(R1); PutPixel(Distort2, W1+100, W2+160, W3 AND $FF); END; END;
(****************************************************************************) (* Init's the standard light for the bumpmapper. *) (****************************************************************************) PROCEDURE InitBump(Light : DWORD); VAR W1, W2 : LONGINT; FUNCTION CL(X:LONGINT):LONGINT;BEGIN IF X < 0 THEN CL:=0 ELSE CL := X END; BEGIN FOR W1 := 0 TO 255 DO FOR W2 := 0 TO 255 DO PutPixel255(Light, W1, W2, CL(255-TRUNC(SQRT(SQR(W1-128)+SQR(W2-128))/191*370))); END; (****************************************************************************) (* This one init's a lightmap with a smaller light. *) (****************************************************************************) PROCEDURE InitBumpSmall(Light : DWORD); VAR W1, W2 : LONGINT; FUNCTION CL(X:LONGINT):LONGINT;BEGIN IF X < 0 THEN CL:=0 ELSE CL := X END; BEGIN FOR W1 := 0 TO 255 DO FOR W2 := 0 TO 255 DO PutPixel255(Light, W1, W2, CL(255-TRUNC(SQRT(SQR(W1-128)+SQR(W2-128))/191*740))); END;
(****************************************************************************) (* This one loads a raw image from disk onto a fake screen. Only 256*256*8b *) (****************************************************************************) PROCEDURE LoadRAW(Where : DWORD; Name : STRING); TYPE Square255 = ARRAY[0..255,0..255] OF BYTE; VAR F : FILE; P : ^Square255; BEGIN ASSIGN(F, Name); {$i-} RESET(F, 1); {$i+} P := PTR(Where); IF IORESULT = 0 THEN BEGIN BlockRead(F, P^, 65536); END; CLOSE(F); END;
(****************************************************************************) (* This one allocate memory for a new fake screen. Returns offset *) (****************************************************************************) FUNCTION NewPage : DWORD; VAR Temp : POINTER; BEGIN getmem(temp, 65536); NewPage := OFS(Temp^); (* Returns new page offset *) END;
(****************************************************************************) (* This one allocates the memory allocated to the given offset. *) (****************************************************************************) PROCEDURE DisposePage(PageOffset : DWORD); VAR Temp : Pointer; BEGIN Temp := PTR(PAgeOffset); Freemem(Temp, 65536); END;
(****************************************************************************) (* This one detects if mmx is available. *) (****************************************************************************) FUNCTION MMXsupported : BOOLEAN;ASSEMBLER; ASM (* First check if the CPUID instruction is supported. *******************) PUSHFD (* PUSH Extended flags *) POP EAX (* Pop'em into EAX *) MOV EBX, EAX (* Copy into EBX *) XOR EAX, $200000 (* Change the 21st byte *) PUSH EAX (* Push this new altered value *) POPFD (* Pop'em into the EFLAGS register. *) PUSHFD (* Push the flags again. *) POP EAX (* Pop'em into EAX again. *) CMP EAX, EBX (* See if we could change the 21st bit. *) JZ @NoMMX (* nopez we could'nt .. CPUID NOT SUPPORTED *) (* Now check for mmx. ***************************************************) MOV EAX, 1 (* Call subfunction 1. *) CPUID (* Execute CPUID *) AND ECX, $00800000 (* Mask out mmx bit. *) JZ @NOMMX (* It's a zero .. no mmx. *) MOV AL, 1 (* Yups ... we got mmx. *) @NOMMX: END; (****************************************************************************)
BEGIN Write ('þ Mute''s educational VGA engine : '); IF (MMXSupported = TRUE) OR NOT(ParamSTR(1) = 'NOMMX') THEN BEGIN WriteLn ('using MMX technology !'); ClearPage := ClearPage_mmx; CopyPage := CopyPage_mmx; CopyPageSmudge := CopyPageSmudge_mmx; MixPages := MixPages_mmx; MixPages2 := MixPages2_mmx; MixPages3 := MixPages3_mmx; Ripple := Ripple_mmx; END ELSE BEGIN WriteLn ('using X86 technology !'); ClearPage := ClearPage_x86; CopyPage := CopyPage_x86; CopyPageSmudge := CopyPageSmudge_x86; MixPages := MixPages_x86; MixPages2 := MixPages2_x86; MixPages3 := MixPages3_x86; Ripple := Ripple_x86; END; END.
|