--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXPI.ASM - Put image\r
+; Copyright (c) 1993,1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxPutImage\r
+\r
+EXTRN subClipImage : NEAR\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_VideoSegment : WORD\r
+EXTRN mx_BytesPerLine : WORD\r
+\r
+mxTable LABEL WORD ; Raster ops\r
+ DW subMove\r
+ DW subAnd\r
+ DW subOr\r
+ DW subXor\r
+ DW subTrans\r
+ DW subAdd\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Move functions.\r
+; Note: loops unrolled and optimized for CX even, no check for CX = 0.\r
+;\r
+subMove PROC NEAR\r
+ shr cx, 1 ; Make CX even\r
+ jc @@Odd ; Special case if odd byte\r
+@@Loop: movsb\r
+ add si, 3\r
+ movsb\r
+ add si, 3\r
+ dec cx\r
+ jnz @@Loop\r
+@@Exit: ret\r
+@@Odd: movsb\r
+ add si, 3\r
+ jcxz @@Exit\r
+ jmp @@Loop\r
+subMove ENDP\r
+;\r
+subAnd PROC NEAR\r
+ shr cx, 1\r
+ jc @@Odd\r
+@@Loop: mov al, ds:[si]\r
+ mov ah, ds:[si+4]\r
+ and es:[di], ax\r
+ inc di\r
+ inc di\r
+ add si, 8\r
+ dec cx\r
+ jnz @@Loop\r
+@@Exit: ret\r
+@@Odd: lodsb\r
+ and es:[di], al\r
+ inc di\r
+ add si, 3\r
+ jcxz @@Exit\r
+ jmp @@Loop\r
+subAnd ENDP\r
+;\r
+subOr PROC NEAR\r
+ shr cx, 1\r
+ jc @@Odd\r
+@@Loop: mov al, ds:[si]\r
+ mov ah, ds:[si+4]\r
+ or es:[di], ax\r
+ inc di\r
+ inc di\r
+ add si, 8\r
+ dec cx\r
+ jnz @@Loop\r
+@@Exit: ret\r
+@@Odd: lodsb\r
+ or es:[di], al\r
+ inc di\r
+ add si, 3\r
+ jcxz @@Exit\r
+ jmp @@Loop\r
+subOr ENDP\r
+;\r
+subXor PROC NEAR\r
+ shr cx, 1\r
+ jc @@Odd\r
+@@Loop: mov al, ds:[si]\r
+ mov ah, ds:[si+4]\r
+ xor es:[di], ax\r
+ inc di\r
+ inc di\r
+ add si, 8\r
+ dec cx\r
+ jnz @@Loop\r
+@@Exit: ret\r
+@@Odd: lodsb\r
+ xor es:[di], al\r
+ inc di\r
+ add si, 3\r
+ jcxz @@Exit\r
+ jmp @@Loop\r
+subXor ENDP\r
+;\r
+subTrans PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ cmp al, ah\r
+ je @@Skip\r
+ mov es:[di], al\r
+@@Skip: inc di\r
+ add si, 4\r
+ dec cx\r
+ jnz @@Loop\r
+@@Exit: ret\r
+subTrans ENDP\r
+;\r
+subAdd PROC NEAR\r
+@@Loop: mov al, ds:[si]\r
+ add es:[di], al\r
+ inc di\r
+ add si, 4\r
+ dec cx\r
+ jnz @@Loop\r
+ ret\r
+subAdd ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies a "raw" image from memory to screen.\r
+;\r
+; Input:\r
+; Image = pointer to image\r
+; X, Y = coordinates of destination\r
+; Width = width of image in pixels\r
+; Height = height of image in pixels\r
+; Op = raster op (OP_xxx)\r
+; Output:\r
+; none\r
+;\r
+mxPutImage PROC FAR\r
+ ARG Op:WORD, \\r
+ Height:WORD, \\r
+ Width:WORD, \\r
+ Y:WORD, \\r
+ X:WORD, \\r
+ Image:DWORD = ARG_SIZE\r
+ LOCAL PlaneWidth:WORD:4, \\r
+ PixelOffset:WORD, \\r
+ MoveFunction:WORD, \\r
+ Count:BYTE, \\r
+ ReadPlane:BYTE, \\r
+ OpInfo:BYTE, \\r
+ WritePlane:BYTE = AUTO_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+\r
+; Clip image\r
+ mov bx, [X]\r
+ mov ax, [Y]\r
+ mov cx, [Width]\r
+ mov dx, [Height]\r
+ call subClipImage\r
+ jc @@Exit ; Full clipped\r
+ mov [Height], dx\r
+ add WORD PTR Image[0], si ; Skip clipped pixels\r
+\r
+; Get pixel address\r
+ mul [mx_BytesPerLine]\r
+ mov di, bx\r
+ shr di, 1\r
+ shr di, 1\r
+ add di, ax\r
+ mov [PixelOffset], di\r
+ mov es, [mx_VideoSegment] ; ES:DI points to pixel\r
+ and bl, 03h\r
+ mov [ReadPlane], bl\r
+\r
+; Compute extra bytes and width count for each plane\r
+ mov bx, cx\r
+ shr bx, 1\r
+ shr bx, 1 ; Width for each plane\r
+ and cl, 03h\r
+ mov al, 00001000b\r
+ shr al, cl\r
+ mov si, 3 SHL 1\r
+@@PatchLoop:\r
+ mov PlaneWidth[si], bx\r
+ shr al, 1\r
+ adc bx, 0\r
+ dec si\r
+ dec si\r
+ jge @@PatchLoop\r
+\r
+; Setup planes for output to VGA registers\r
+ mov cl, [ReadPlane]\r
+ mov al, 00010001b\r
+ shl al, cl\r
+ mov [WritePlane], al\r
+\r
+; Install move function\r
+ mov bx, [Op]\r
+ mov [OpInfo], bh ; Remember additional info if needed\r
+ xor bh, bh\r
+ cmp bl, OP_ADD\r
+ jbe @@SetMoveFunction\r
+ xor bl, bl\r
+@@SetMoveFunction:\r
+ shl bx, 1\r
+ mov ax, mxTable[bx]\r
+ mov [MoveFunction], ax\r
+\r
+; Put image\r
+ cld\r
+ mov [Count], 4 ; Four planes\r
+ lea bx, PlaneWidth ; SS:[BX] = width in bytes for plane\r
+ mov ds, WORD PTR Image[2]\r
+@@PlaneLoop:\r
+ cmp WORD PTR ss:[bx], 0 ; Exit if nothing more to do\r
+ je @@Exit ; (also, never try to move zero bytes!)\r
+ mov si, WORD PTR Image[0]\r
+ mov ah, [WritePlane]\r
+ and ah, 0Fh\r
+ mov al, 02h\r
+ mov dx, TS\r
+ out dx, ax ; Select write plane\r
+ mov ah, [ReadPlane]\r
+ and ah, 03h\r
+ mov al, 04h\r
+ mov dx, GDC\r
+ out dx, ax ; Select read plane\r
+ mov dx, [Height]\r
+ mov di, [PixelOffset]\r
+@@Loop:\r
+ push si\r
+ push di\r
+ mov cx, WORD PTR ss:[bx] ; Number of bytes to move\r
+ mov ah, [OpInfo] ; Transparent color for subTrans\r
+ call [MoveFunction]\r
+ pop di\r
+ pop si\r
+ add si, [Width] ; Go to next image line\r
+ add di, [mx_BytesPerLine] ; Go to next screen row\r
+ dec dx\r
+ jnz @@Loop ; Repeat for all lines\r
+ inc bx\r
+ inc bx ; Select width for next plane\r
+ inc [ReadPlane]\r
+ rol [WritePlane], 1\r
+ adc [PixelOffset], 0\r
+ inc WORD PTR Image[0]\r
+ dec [Count]\r
+ jnz @@PlaneLoop ; Repeat for all planes\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxPutImage ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r