+;-----------------------------------------------------------\r
+;\r
+; MXOT.ASM - Text functions\r
+; Copyright (c) 1994 by Alessandro Scotti\r
+;\r
+;-----------------------------------------------------------\r
+;WARN PRO\r
+;NOWARN RES ; We use the reserved name 'WIDTH'\r
+INCLUDE MODEX.DEF\r
+\r
+PUBLIC mxOutChar\r
+PUBLIC mxOutText\r
+PUBLIC mxSetFont\r
+PUBLIC mxSetTextColor\r
+PUBLIC mxGetTextStep\r
+PUBLIC mxSetTextStep\r
+\r
+MAX_WIDTH EQU 16 ; Must be <= 16\r
+MAX_HEIGHT EQU 32\r
+\r
+MX_TEXT SEGMENT USE16 PARA PUBLIC 'CODE'\r
+ ASSUME cs:MX_TEXT, ds:NOTHING, es:NOTHING\r
+\r
+EXTRN mx_CodeSegment : WORD\r
+EXTRN mxPutImage : FAR\r
+\r
+; Default 8x8 font\r
+fnt_Default LABEL BYTE\r
+ INCLUDE DEFAULT.FNT\r
+\r
+; Table of system fonts\r
+tbl_SystemFont LABEL WORD\r
+ DW fnt_Default, 8, 8\r
+\r
+MX_MAXSYSFONT EQU ($-OFFSET tbl_SystemFont) SHR 2\r
+\r
+mx_FontPtr DW OFFSET fnt_Default, SEG MX_TEXT\r
+mx_FontWidth DW 8 ; Font width in pixels\r
+mx_FontHeight DW 8 ; Font height in pixels\r
+mx_FontCharSize DW 8 ; Size in bytes of a font character\r
+mx_FontColor DW 00FFh ; Color: foreground + background*256\r
+mx_FontOp DW OP_MOVE ; Raster op\r
+mx_DeltaX DW 8 ; Horizontal step\r
+mx_DeltaY DW 0 ; Vertical step\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the current font.\r
+;\r
+; Input:\r
+; Font = pointer to font data\r
+; Width = width of font character in pixels\r
+; Height = height of font character in pixels\r
+; Output:\r
+; AX = 0 on success, else invalid parameters\r
+;\r
+; Note: when the high word of Font (i.e. the segment) is zero, the low\r
+; word is used to select one of the system fonts.\r
+;\r
+mxSetFont PROC FAR\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,0\r
+ push ds\r
+ .enter 0\r
+ .push ds\r
+\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, WORD PTR Font[2] ; Get font segment\r
+ test ax, ax ; Null segment?\r
+ jnz @@UserFont ; No, install user font\r
+\r
+; Install system font\r
+ mov ax, WORD PTR Font[0] ; Get font number\r
+ cmp ax, MX_MAXSYSFONT ; Check range\r
+ jb @@SystemFont\r
+ xor ax, ax ; Out of range, use default font\r
+@@SystemFont:\r
+ shl ax, 1\r
+ shl ax, 1\r
+ mov bx, ax\r
+ mov ax, tbl_SystemFont[bx] ; Get font offset\r
+ mov WORD PTR mx_FontPtr[0], ax\r
+ mov WORD PTR mx_FontPtr[2], cs\r
+ mov al, BYTE PTR tbl_SystemFont[bx+2]\r
+ xor ah, ah\r
+ mov [mx_FontWidth], ax\r
+ mov [mx_DeltaX], ax\r
+ mov dl, BYTE PTR tbl_SystemFont[bx+3]\r
+ xor dh, dh\r
+ mov [mx_FontHeight], dx\r
+ mul dx\r
+ mov [mx_FontCharSize], ax\r
+ mov [mx_DeltaX], ax\r
+ xor ax, ax\r
+ mov [mx_DeltaY], ax\r
+ jmp @@Exit\r
+\r
+; Install user font\r
+@@UserFont:\r
+ mov ax, -1 ; Assume an error\r
+ mov bx, [bp+8]\r
+ cmp bx, MAX_WIDTH\r
+ ja @@Exit ; Invalid character width\r
+ mov dx, [bp+4]\r
+ cmp dx, MAX_HEIGHT\r
+ ja @@Exit ; Invalid character height\r
+ mov [mx_FontWidth], bx\r
+ mov [mx_FontHeight], dx\r
+ mov ax, bx\r
+ add ax, 7\r
+ shr ax, 1\r
+ shr ax, 1\r
+ shr ax, 1\r
+ mul dx\r
+ mov [mx_FontCharSize], ax\r
+ mov ax, WORD PTR Font[0]\r
+ mov WORD PTR mx_FontPtr[0], ax\r
+ mov ax, WORD PTR Font[2]\r
+ mov WORD PTR mx_FontPtr[2], ax\r
+ xor ax, ax\r
+\r
+@@Exit:\r
+ .pop ds\r
+ ASSUME ds:NOTHING\r
+ ;.leave ARG_SIZE\r
+mxSetFont ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the text color and raster op.\r
+;\r
+; Input:\r
+; Color = text color (foreground + background*256)\r
+; Op = raster op\r
+; Output:\r
+; none\r
+;\r
+mxSetTextColor PROC FAR\r
+ ARG Op:WORD, \\r
+ Color:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds\r
+\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, [Color]\r
+ mov [mx_FontColor], ax\r
+ mov ax, [Op]\r
+ mov [mx_FontOp], ax\r
+\r
+ xor ax, ax\r
+ .pop ds\r
+ ASSUME ds:NOTHING\r
+ .leave ARG_SIZE\r
+mxSetTextColor ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Writes a character using the current font and attributes.\r
+;\r
+; Input:\r
+; X, Y = video coordinates\r
+; C = character to print\r
+; Output:\r
+; none\r
+;\r
+mxOutChar PROC FAR\r
+ ARG C:BYTE:2, \\r
+ Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ LOCAL Image:BYTE:MAX_WIDTH*MAX_HEIGHT, \\r
+ Count:WORD = AUTO_SIZE\r
+ .enter AUTO_SIZE\r
+ .push ds, si, es, di\r
+ ASSUME ds:NOTHING\r
+\r
+; Gets the pointer to font data for the selected character\r
+ lds si, DWORD PTR [mx_FontPtr]\r
+ mov al, [C]\r
+ xor ah, ah\r
+ mul [mx_FontCharSize] ; Offset into font\r
+ add si, ax ; DS:SI -> font data for character\r
+\r
+; Converts font data into a 256-color linear image\r
+ mov ax, ss\r
+ mov es, ax\r
+ lea di, [Image]\r
+ mov dx, [mx_FontColor]\r
+ mov ax, [mx_FontHeight]\r
+ mov [Count], ax\r
+@@HeightLoop:\r
+ mov cx, [mx_FontWidth]\r
+ mov bh, ds:[si]\r
+ inc si ; Get a byte from font data\r
+ cmp cx, 8\r
+ jbe @@WidthLoop ; Ok for width <= 8\r
+ mov bl, ds:[si] ; Get another byte\r
+ inc si\r
+@@WidthLoop:\r
+ mov al, dl ; Assume foreground color\r
+ shl bx, 1 ; Is font bit set?\r
+ jc @@1 ; Yes, foreground is just great\r
+ mov al, dh ; Get background color\r
+@@1:\r
+ mov es:[di], al ; Put pixel into image\r
+ inc di\r
+ dec cx\r
+ jnz @@WidthLoop\r
+ dec [Count]\r
+ jnz @@HeightLoop\r
+\r
+; Now pass image to mx_PutImage\r
+ lea ax, [Image]\r
+ push es\r
+ push ax ; Pointer to image\r
+ push [X]\r
+ push [Y] ; Image coordinates\r
+ push [mx_FontWidth]\r
+ push [mx_FontHeight] ; Image size\r
+ push [mx_FontOp] ; Raster op\r
+ call mxPutImage ; Write character\r
+\r
+ xor ax, ax\r
+ .pop ds, si, es, di\r
+ .leave ARG_SIZE\r
+mxOutChar ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Writes a string at the coordinates specified.\r
+;\r
+; Input:\r
+; X, Y = text coordinates\r
+; S = pointer to ASCIIZ string\r
+; Output:\r
+; none\r
+;\r
+mxOutText PROC FAR\r
+ ARG S:DWORD, \\r
+ Y:WORD, \\r
+ X:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+ ASSUME ds:NOTHING\r
+\r
+ lds si, [S]\r
+@@Loop:\r
+ mov al, ds:[si]\r
+ test al, al ; End of string?\r
+ jz @@Exit ; Yes, exit\r
+ inc si\r
+ push [X] ; Display character\r
+ push [Y]\r
+ push ax\r
+ call mxOutChar\r
+ mov ax, [mx_DeltaX]\r
+ add [X], ax ; Bump X coordinate\r
+ mov ax, [mx_DeltaY]\r
+ add [Y], ax ; Bump Y coordinate\r
+ dec [Count]\r
+ jnz @@Loop\r
+\r
+@@Exit:\r
+ xor ax, ax\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+ ret\r
+mxOutText ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Sets the distance between characters.\r
+;\r
+; Input:\r
+; DeltaX = horizontal distance in pixels\r
+; DeltaY = vertical distance in pixels\r
+; Output:\r
+; none\r
+;\r
+; Note: this function may be used to set the text direction.\r
+;\r
+mxSetTextStep PROC FAR\r
+ ARG DeltaY:WORD, \\r
+ DeltaX:WORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds\r
+\r
+ mov ds, [mx_CodeSegment]\r
+ ASSUME ds:MX_TEXT\r
+\r
+ mov ax, [DeltaX]\r
+ mov [mx_DeltaX], ax\r
+ mov ax, [DeltaY]\r
+ mov [mx_DeltaY], ax\r
+\r
+ .pop ds\r
+ .leave ARG_SIZE\r
+mxSetTextStep ENDP\r
+\r
+;-----------------------------------------------------------\r
+;\r
+; Gets the current distance between characters.\r
+;\r
+; Input:\r
+; DeltaX = pointer to horizontal distance in pixels (integer)\r
+; DeltaY = pointer to vertical distance in pixels (integer)\r
+; Output:\r
+; none\r
+;\r
+mxGetTextStep PROC FAR\r
+ ARG DeltaY:DWORD, \\r
+ DeltaX:DWORD = ARG_SIZE\r
+ .enter 0\r
+ .push ds, si\r
+ ASSUME ds:NOTHING\r
+\r
+ mov ax, [mx_DeltaX]\r
+ lds si, [DeltaX]\r
+ mov ds:[si], ax\r
+ mov ax, [mx_DeltaY]\r
+ lds si, [DeltaY]\r
+ mov ds:[si], ax\r
+\r
+ .pop ds, si\r
+ .leave ARG_SIZE\r
+mxGetTextStep ENDP\r
+\r
+MX_TEXT ENDS\r
+END\r