--- /dev/null
+;-----------------------------------------------------------------------\r
+; MODULE XTEXT\r
+;\r
+; Point functions all MODE X 256 Color resolutions\r
+;\r
+; Compile with Tasm.\r
+; C callable.\r
+;\r
+;\r
+; ****** XLIB - Mode X graphics library ****************\r
+; ****** ****************\r
+; ****** Written By Themie Gouthas ****************\r
+;\r
+; egg@dstos3.dsto.gov.au\r
+; teg@bart.dsto.gov.au\r
+;-----------------------------------------------------------------------\r
+\r
+\r
+include xlib.inc\r
+include xtext.inc\r
+\r
+.data\r
+\r
+_FontDriverActive db 0\r
+\r
+\r
+_CharHeight db 0\r
+_CharWidth db 0\r
+_FontPtr dw 2 dup (0)\r
+_FirstChar db 0\r
+\r
+_UserFontPtr dw 2 dup (0)\r
+_UserChHeight db 0\r
+_UserChWidth db 0\r
+_UserFirstCh db 0\r
+\r
+\r
+F8x8Ptr dw 2 dup (0)\r
+F8x14Ptr dw 2 dup (0)\r
+\r
+; This is a look up table for the mirror image of a byte eg\r
+; a byte with the value 11001010 has a corresponding byte in the table\r
+; 01010011. This is necessary as the VGA rom font bits are the reverse\r
+; order of what we need for the Mode X. If you know a better-faster way\r
+; TELL ME!\r
+\r
+MirrorTable label byte\r
+ db 0,128, 64,192, 32,160, 96,224, 16,144, 80,208, 48,176,112,240\r
+ db 8,136, 72,200, 40,168,104,232, 24,152, 88,216, 56,184,120,248\r
+ db 4,132, 68,196, 36,164,100,228, 20,148, 84,212, 52,180,116,244\r
+ db 12,140, 76,204, 44,172,108,236, 28,156, 92,220, 60,188,124,252\r
+ db 2,130, 66,194, 34,162, 98,226, 18,146, 82,210, 50,178,114,242\r
+ db 10,138, 74,202, 42,170,106,234, 26,154, 90,218, 58,186,122,250\r
+ db 6,134, 70,198, 38,166,102,230, 22,150, 86,214, 54,182,118,246\r
+ db 14,142, 78,206, 46,174,110,238, 30,158, 94,222, 62,190,126,254\r
+ db 1,129, 65,193, 33,161, 97,225, 17,145, 81,209, 49,177,113,241\r
+ db 9,137, 73,201, 41,169,105,233, 25,153, 89,217, 57,185,121,249\r
+ db 5,133, 69,197, 37,165,101,229, 21,149, 85,213, 53,181,117,245\r
+ db 13,141, 77,205, 45,173,109,237, 29,157, 93,221, 61,189,125,253\r
+ db 3,131, 67,195, 35,163, 99,227, 19,147, 83,211, 51,179,115,243\r
+ db 11,139, 75,203, 43,171,107,235, 27,155, 91,219, 59,187,123,251\r
+ db 7,135, 71,199, 39,167,103,231, 23,151, 87,215, 55,183,119,247\r
+ db 15,143, 79,207, 47,175,111,239, 31,159, 95,223, 63,191,127,255\r
+\r
+MirrorTableOffs dw ?\r
+.code\r
+\r
+;----------------------------------------------------------------------\r
+; x_text_init - Initializes the Mode X text driver and sets the\r
+; default font (VGA ROM 8x8)\r
+;\r
+; C caller:\r
+;\r
+; x_text_init()\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_text_init proc\r
+ push bp\r
+\r
+ mov [_FontDriverActive],TRUE\r
+ mov ax,1130h ; AH = BIOS generator function\r
+ ; AL = BIOS get font pointer subfunction\r
+ push ax ; Save Video interrupt function parameters\r
+ mov bh,3 ; Select 8x8 VGA ROM font\r
+ int 10h ; Call BIOS video interrupt\r
+ mov word ptr [F8x8Ptr],bp ; Save 8x8 Font address in FontPtr table\r
+ mov word ptr [F8x8Ptr+2],es\r
+\r
+ mov word ptr [_FontPtr],bp ; Default font = 8x8 ROM font\r
+ mov word ptr [_FontPtr+2],es\r
+\r
+ pop ax ; Recall Video interrupt function parameters\r
+ mov bh,2 ; Select 8x14 VGA ROM font\r
+ int 10h ; Call BIOS video interrupt\r
+ mov word ptr [F8x14Ptr],bp ; Save 8x14 Font address in FontPtr table\r
+ mov word ptr [F8x14Ptr+2],es\r
+\r
+\r
+ mov al,8\r
+ mov [_CharHeight],al ; Set the font character heights\r
+ mov [_CharWidth] ,al ; Set the font character widths\r
+\r
+ mov dx,offset MirrorTable ; Initialize mirror table offset\r
+ mov [MirrorTableOffs],dx\r
+\r
+ pop bp\r
+ ret\r
+_x_text_init endp\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; x_set_font - Mode X Set current font for text drawing\r
+;\r
+; C caller:\r
+;\r
+; x_set_font(int FontID)\r
+;\r
+; PARAMETERS FontID 0 = VGA ROM 8x8\r
+; 1 = VGA ROM 8x14\r
+; 2 = User defined bitmapped font\r
+;\r
+;\r
+; WARNING: A user font must be registered before setting FontID 2\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+\r
+_x_set_font proc\r
+ ARG FontID:word\r
+ push bp\r
+ mov bp,sp\r
+\r
+ xor dx,dx ; Clear DX - Mirror table offset (0 for non ROM fonts)\r
+ mov cx,FontID\r
+ cmp cx,2\r
+\r
+ jne @@not_userfont ; Do we have a user font\r
+ mov ax,[_UserFontPtr] ; Yes - Activate it\r
+ mov [_FontPtr],ax\r
+\r
+ mov ax,[_UserFontPtr+2]\r
+ mov [_FontPtr+2],ax\r
+\r
+ mov al,[_UserChHeight]\r
+ mov [_CharHeight],al ; Set the font character heights\r
+\r
+ mov al,[_UserChWidth]\r
+ mov [_CharWidth],al ; Set the font character heights\r
+\r
+ mov al,[_UserFirstCh]\r
+ mov [_FirstChar],al\r
+ jmp short @@done\r
+\r
+@@not_userfont: ; We have a ROM font\r
+\r
+ mov dx,offset MirrorTable\r
+ mov [_CharWidth],8 ; Set the font character widths\r
+ mov [_FirstChar],0 ; Character sets start at ascii 0\r
+ cmp cx,1 ; Do we have an 8x14 ROM font\r
+ jne @@not_8x14font ; No, we have 8x8 - jump\r
+\r
+ mov ax,[F8x14Ptr] ; Yes Activate it\r
+ mov [_FontPtr],ax\r
+\r
+ mov ax,[F8x14Ptr+2]\r
+ mov [_FontPtr+2],ax\r
+\r
+ mov [_CharHeight],14 ; Set the font character heights\r
+ jmp short @@done\r
+\r
+@@not_8x14font:\r
+ mov ax,[F8x8Ptr] ; Activate the 8x8 ROM Font\r
+ mov [_FontPtr],ax\r
+\r
+ mov ax,[F8x8Ptr+2]\r
+ mov [_FontPtr+2],ax\r
+\r
+ mov [_CharHeight],8 ; Set the font character heights\r
+\r
+@@done:\r
+ mov [MirrorTableOffs],dx\r
+\r
+ pop bp\r
+ ret\r
+_x_set_font endp\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; x_register_userfont - Mode X register user font\r
+;\r
+; C caller:\r
+;\r
+; x_register_userfont(void far *user_font)\r
+;\r
+;\r
+; NOTES registering a user font deregisters the previous user font\r
+; User fonts may be at most 8 pixels wide\r
+;\r
+;\r
+; USER FONT STRUCTURE\r
+;\r
+; Word: ascii code of first char in font\r
+; Byte: Height of chars in font\r
+; Byte: Width of chars in font\r
+; n*h*Byte: the font data where n = number of chars and h = height\r
+; of chars\r
+;\r
+; WARNING: The onus is on the program to ensure that all characters\r
+; drawn whilst this font is active, are within the range of\r
+; characters defined.\r
+;\r
+;\r
+; UPDATE: Variable width fonts are now available (up to 8 pixels max)\r
+; If the Width byte in the font header is 0 then it is assumed that\r
+; the font is variable width. For variable width fonts each characters\r
+; data is followed by one byte representing the characters pixel width.\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_register_userfont proc\r
+ ARG FontToRegister:dword\r
+ push bp\r
+ mov bp,sp\r
+ push si\r
+\r
+ mov ax,word ptr [FontToRegister]\r
+ mov bx,word ptr [FontToRegister+2]\r
+ add ax,4\r
+ mov [_UserFontPtr],ax\r
+ mov [_UserFontPtr+2],bx\r
+\r
+ push ds\r
+ lds si,[FontToRegister]\r
+ lodsw\r
+ mov bx,ax\r
+ lodsw\r
+ pop ds\r
+\r
+ mov [_UserChHeight],al\r
+ mov [_UserChWidth],ah\r
+ mov [_UserFirstCh],bl\r
+ pop si\r
+ pop bp\r
+ ret\r
+_x_register_userfont endp\r
+\r
+\r
+_x_get_char_width proc\r
+ ARG Chr:byte\r
+ push bp\r
+ mov bp,sp\r
+\r
+ xor ah,ah\r
+ mov al,[_CharWidth]\r
+ or al,al\r
+ jz @@NotFixed\r
+ pop bp\r
+ ret\r
+\r
+@@NotFixed:\r
+ push si\r
+ mov al,[_CharHeight]\r
+ mov bx,ax\r
+ inc al\r
+ mov dl,[Chr] ; User fonts may have incomplete charsets\r
+ sub dl,[_FirstChar] ; this compensates for fonts not starting at\r
+ ; ascii value 0\r
+ mul dl ; Mult AX by character to draw giving offset\r
+ ; of first character byte in font table\r
+ add ax,bx\r
+ les si,dword ptr [_FontPtr]\r
+ add si,ax\r
+ xor ah,ah\r
+ mov al,es:[si]\r
+ pop si\r
+ pop bp\r
+ ret\r
+_x_get_char_width endp\r
+\r
+\r
+;----------------------------------------------------------------------\r
+; x_char_put - Mode X Draw a text character at the specified location\r
+;\r
+;\r
+; C caller:\r
+;\r
+; x_char_put(char ch, int x, int y, unsigned ScrnOffs, unsigned Color)\r
+;\r
+; PARAMETERS ch char to draw\r
+; x,y screen coords at which to draw ch\r
+; ScrnOffs Starting offset of page on whih to draw\r
+; Color Color of the text\r
+;\r
+; NOTES: Uses the current font settings. See SetFont, InitTextDriver,\r
+; RegisterUserFont\r
+;\r
+; WARNING: InitTextDriver must be called before using this function\r
+;\r
+;\r
+; Written by Themie Gouthas\r
+;----------------------------------------------------------------------\r
+_x_char_put proc\r
+ ARG Chr:byte,X:word,Y:word,ScrnOffs:word,Color:word\r
+ LOCAL ScreenInc:word,Hold:word=LocalStk\r
+ push bp\r
+ mov bp,sp\r
+ sub sp,LocalStk\r
+ push si\r
+ push di\r
+ push ds\r
+\r
+ cld\r
+ mov ax,[_ScrnLogicalByteWidth] ; AX = Virtual screen width\r
+ mov bx,ax ; copy Virt screen width and decrement\r
+ sub bx,3 ; by the max number of bytes (whole or part)\r
+ ; that a character row may occupy on the screen\r
+ mov [ScreenInc],bx ; Save it to the local stack var. SceenInc\r
+ mul [Y] ; Find the starting dest. screen address of\r
+ mov di,[X] ; the character to draw\r
+ mov cx,di\r
+ shr di,2\r
+ add di,ax\r
+ add di,[ScrnOffs] ; Dont forget to compensate for page\r
+\r
+ mov ax,SCREEN_SEG ; ES:DI -> first screen dest. byte of char\r
+ mov es,ax\r
+\r
+ and cx,3 ; CH = 0, CL = Plane of first pixel\r
+\r
+ mov bx,[MirrorTableOffs] ; set BX to offset of mirror table for XLAT\r
+ mov al,[_CharHeight] ; AL = Character height, AH = 0\r
+ xor ah,ah\r
+ mov ch,al ; CH = Character height\r
+\r
+ cmp [_CharWidth],0\r
+ jne @@NoWidthByte\r
+ inc al\r
+@@NoWidthByte:\r
+\r
+ mov dl,[Chr] ; User fonts may have incomplete charsets\r
+ sub dl,[_FirstChar] ; this compensates for fonts not starting at\r
+ ; ascii value 0\r
+ mul dl ; Mult AX by character to draw giving offset\r
+ ; of first character byte in font table\r
+\r
+ lds si,dword ptr [_FontPtr] ; DS:SI -> beggining of required font\r
+ add si,ax ; DS:SI -> first byte of req. char\r
+\r
+ mov dx,SC_INDEX ; Prepare for VGA out's\r
+\r
+@@MainLoop:\r
+\r
+ lodsb ; load character byte into AL\r
+ or al,al\r
+ jz @@NoCharPixels ; Dont bother if no pixels to draw\r
+\r
+ or bx,bx ; if BX=0 -> User font, so no need to mirror data\r
+ jz @@DontMirror\r
+ push ds\r
+ mov dx,@data ; Set DS to the Mirror lookup table's segment\r
+ mov ds,dx ; - BX should already contain the offset addr of table\r
+ xlatb ; AL is now replaced by the corresponding table entry\r
+ pop ds ; Restore previous data segment\r
+ mov dx,SC_INDEX ; Restore DX\r
+\r
+@@DontMirror:\r
+ xor ah,ah ; shift the byte for the dest plane and save it\r
+ shl ax,cl\r
+ mov [Hold],ax\r
+\r
+ mov ah,al ; output high nibble of first byte of shifted char\r
+ and ah,0fh ; 4 pixels at a time !\r
+ jnz @@p1 ; if nibble has pixels, draw them\r
+ inc di ; otherwise go to next nibble\r
+ jmp @@SecondNibble\r
+\r
+@@p1:\r
+ mov al,MAP_MASK\r
+ out dx,ax\r
+ mov al,byte ptr [Color]\r
+ stosb\r
+\r
+@@SecondNibble:\r
+ ; output low nibble of first byte of shifted char\r
+ mov ax,[Hold]\r
+ shl ax,4\r
+ and ah,0fh\r
+ jnz @@p2\r
+ inc di\r
+ jmp @@ThirdNibble\r
+\r
+@@p2:\r
+ mov al,MAP_MASK\r
+ out dx,ax\r
+ mov al,byte ptr [Color]\r
+ stosb\r
+\r
+@@ThirdNibble:\r
+ mov ax,[Hold] ; output high nibble of last byte of shifted char\r
+ and ah,0fh\r
+ jnz @@p3\r
+ inc di\r
+ jmp short @@NextCharRow\r
+\r
+@@p3:\r
+ mov al,MAP_MASK ; completing the drawing of one character row\r
+ out dx,ax\r
+ mov al,byte ptr [Color]\r
+ stosb\r
+\r
+@@NextCharRow:\r
+ add di,[ScreenInc] ; Now move to the next screen row and do the same\r
+ dec ch ; any remaining character bytes\r
+ jnz @@MainLoop\r
+\r
+@@done:\r
+ pop es\r
+ mov ah,0\r
+ mov al,es:[_CharWidth] ; return the character width (for string fuctions\r
+ or al,al\r
+ jnz @@FixedSpacing ; using this character drawing function).\r
+ lodsb\r
+@@FixedSpacing:\r
+\r
+ mov bx,es\r
+ mov ds,bx\r
+\r
+ pop di\r
+ pop si\r
+ mov sp,bp\r
+ pop bp\r
+ ret\r
+\r
+@@NoCharPixels:\r
+ add di,3\r
+ add di,[ScreenInc] ; Now move to the next screen row and do the same\r
+ dec ch ; any remaining character bytes\r
+ jnz @@MainLoop\r
+ jmp short @@done\r
+\r
+_x_char_put endp\r
+\r
+\r
+end\r
+\r