--- /dev/null
+;-----------------------------------------------------------\r
+;\r
+; MXTL.ASM - Put tile\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+WARN PRO\r
+NOWARN RES\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxPutTile\r
+PUBLIC mxTransPutTile\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
+;-----------------------------------------------------------\r
+;\r
+; Copies a "mode-x" tile from memory to screen.\r
+;\r
+; Input:\r
+; Image = pointer to tile\r
+; X, Y = coordinates of destination\r
+; Width = width of image in pixels (Width and 3 = 0)\r
+; Height = height of image in pixels\r
+; Output:\r
+; none\r
+; Note:\r
+; no clipping is performed on tiles!\r
+;\r
+mxPutTile PROC FAR\r
+ ARG Height:WORD, \\r
+ Width:WORD, \\r
+ Y:WORD, \\r
+ X:WORD, \\r
+ Image:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si, es, di\r
+\r
+ mov ax, [Y] ; Get pixel address\r
+ mul [mx_BytesPerLine]\r
+ mov di, [X]\r
+ .shr di, 2\r
+ add di, ax\r
+ mov es, [mx_VideoSegment]\r
+\r
+ lds si, [Image] ; Get tile address\r
+ .shr [Width], 2 ; Number of bytes per plane\r
+ mov cl, BYTE PTR [X]\r
+ and cl, 3\r
+ mov ah, 11h ; AH = plane mask\r
+ shl ah, cl ; Align mask to first plane\r
+\r
+ mov [Y], 4 ; Number of planes\r
+ mov bx, [mx_BytesPerLine]\r
+ sub bx, [Width] ; Extra bytes per line\r
+@@Loop:\r
+ mov al, 02h\r
+ mov dx, TS\r
+ out dx, ax ; Set write plane\r
+ mov [X], di ; Save video offset\r
+ mov dx, [Height]\r
+@@Loop2:\r
+ mov cx, [Width] ; Number of bytes to move\r
+\r
+ shr cx, 1 ; Move line\r
+ rep movsw\r
+ rcl cx, 1\r
+ rep movsb\r
+\r
+ add di, bx ; Move video offset to next line\r
+ dec dx ; Done all lines?\r
+ jnz @@Loop2 ; No, continue\r
+ mov di, [X] ; Restore video offset\r
+ rol ah, 1 ; Next plane\r
+ adc di, 0 ; Bump video offset if needed\r
+ dec [Y] ; Any plane left?\r
+ jnz @@Loop ; Yes, keep looping\r
+\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxPutTile ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Copies a "mode-x" tile from memory to screen.\r
+; Skips over color 0.\r
+;\r
+; Input:\r
+; Image = pointer to tile\r
+; X, Y = coordinates of destination\r
+; Width = width of image in pixels (Width and 3 = 0)\r
+; Height = height of image in pixels\r
+; Output:\r
+; none\r
+; Note:\r
+; no clipping is performed on tiles!\r
+;\r
+mxTransPutTile PROC FAR\r
+ ARG Height:WORD, \\r
+ Width:WORD, \\r
+ Y:WORD, \\r
+ X:WORD, \\r
+ Image:DWORD = ARG_SIZE\r
+ ASSUME ds:NOTHING\r
+ .enter 0\r
+ .push ds, si, es, di\r
+\r
+ mov ax, [Y] ; Get pixel address\r
+ mul [mx_BytesPerLine]\r
+ mov di, [X]\r
+ .shr di, 2\r
+ add di, ax\r
+ mov es, [mx_VideoSegment]\r
+\r
+ lds si, [Image] ; Get tile address\r
+ .shr [Width], 2 ; Number of bytes per plane\r
+ mov cl, BYTE PTR [X]\r
+ and cl, 3\r
+ mov ah, 11h ; AH = plane mask\r
+ shl ah, cl ; Align mask to first plane\r
+\r
+ mov [Y], 4 ; Number of planes\r
+ mov bx, [mx_BytesPerLine]\r
+ sub bx, [Width] ; Extra bytes per line\r
+@@Loop:\r
+ mov al, 02h\r
+ mov dx, TS\r
+ out dx, ax ; Set write plane\r
+ mov [X], di ; Save video offset\r
+ mov dx, [Height]\r
+@@Loop2:\r
+ mov cx, [Width] ; Number of bytes to move\r
+\r
+; Move one line\r
+ jcxz @@MoveLineDone\r
+@@MoveLineLoop:\r
+ mov al, ds:[si]\r
+ test al, al\r
+ jz @@MoveLineNext\r
+ mov es:[di], al\r
+@@MoveLineNext:\r
+ inc si\r
+ inc di\r
+ dec cx\r
+ jnz @@MoveLineLoop\r
+@@MoveLineDone:\r
+\r
+ add di, bx ; Move video offset to next line\r
+ dec dx ; Done all lines?\r
+ jnz @@Loop2 ; No, continue\r
+ mov di, [X] ; Restore video offset\r
+ rol ah, 1 ; Next plane\r
+ adc di, 0 ; Bump video offset if needed\r
+ dec [Y] ; Any plane left?\r
+ jnz @@Loop ; Yes, keep looping\r
+\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxTransPutTile ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r