Home | History | Annotate | Download | only in ldlinux
      1 #include <syslinux/video.h>
      2 #include <com32.h>
      3 #include <stdio.h>
      4 #include <bios.h>
      5 #include <graphics.h>
      6 
      7 static uint8_t TextAttribute;	/* Text attribute for message file */
      8 extern uint8_t DisplayMask;	/* Display modes mask */
      9 
     10 /* Routine to interpret next print char */
     11 static void (*NextCharJump)(uint8_t);
     12 
     13 void msg_initvars(void);
     14 static void msg_setfg(uint8_t data);
     15 static void msg_putchar(uint8_t ch);
     16 
     17 /*
     18  *
     19  * get_msg_file: Load a text file and write its contents to the screen,
     20  *               interpreting color codes.
     21  *
     22  * Returns 0 on success, -1 on failure.
     23  */
     24 int get_msg_file(char *filename)
     25 {
     26 	FILE *f;
     27 	char ch;
     28 
     29 	f = fopen(filename, "r");
     30 	if (!f)
     31 		return -1;
     32 
     33 	TextAttribute = 0x7;	/* Default grey on white */
     34 	DisplayMask = 0x7;	/* Display text in all modes */
     35 	msg_initvars();
     36 
     37 	/*
     38 	 * Read the text file a byte at a time and interpret that
     39 	 * byte.
     40 	 */
     41 	while ((ch = getc(f)) != EOF) {
     42 		/* DOS EOF? */
     43 		if (ch == 0x1A)
     44 			break;
     45 
     46 		NextCharJump(ch);	/* Do what shall be done */
     47 	}
     48 
     49 	DisplayMask = 0x07;
     50 
     51 	fclose(f);
     52 	return 0;
     53 }
     54 
     55 static inline int display_mask_vga(void)
     56 {
     57 	uint8_t mask = UsingVGA & 0x1;
     58 	return (DisplayMask & ++mask);
     59 }
     60 
     61 static void msg_setbg(uint8_t data)
     62 {
     63 	if (unhexchar(&data) == 0) {
     64 		data <<= 4;
     65 		if (display_mask_vga())
     66 			TextAttribute = data;
     67 
     68 		NextCharJump = msg_setfg;
     69 	} else {
     70 		TextAttribute = 0x7;	/* Default attribute */
     71 		NextCharJump = msg_putchar;
     72 	}
     73 }
     74 
     75 static void msg_setfg(uint8_t data)
     76 {
     77 	if (unhexchar(&data) == 0) {
     78 		if (display_mask_vga()) {
     79 			/* setbg set foreground to 0 */
     80 			TextAttribute |= data;
     81 		}
     82 	} else
     83 		TextAttribute = 0x7;	/* Default attribute */
     84 
     85 	NextCharJump = msg_putchar;
     86 }
     87 
     88 static inline void msg_ctrl_o(void)
     89 {
     90 	NextCharJump = msg_setbg;
     91 }
     92 
     93 /* Convert ANSI colors to PC display attributes */
     94 static int convert_to_pcdisplay[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
     95 
     96 static void set_fgbg(void)
     97 {
     98 	uint8_t bg, fg;
     99 
    100 	fg = convert_to_pcdisplay[(TextAttribute & 0x7)];
    101 	bg = convert_to_pcdisplay[((TextAttribute >> 4) & 0x7)];
    102 
    103 	printf("\033[");
    104 	if (TextAttribute & 0x8)
    105 		printf("1;"); /* Foreground bright */
    106 
    107 	printf("3%dm\033[", fg);
    108 
    109 	if (TextAttribute & 0x80)
    110 		printf("5;"); /* Foreground blink */
    111 
    112 	printf("4%dm", bg);
    113 }
    114 
    115 static void msg_formfeed(void)
    116 {
    117 	set_fgbg();
    118 	printf("\033[2J\033[H\033[0m");
    119 }
    120 
    121 static void msg_novga(void)
    122 {
    123 	syslinux_force_text_mode();
    124 	msg_initvars();
    125 }
    126 
    127 static void msg_viewimage(void)
    128 {
    129 	FILE *f;
    130 
    131 	*VGAFilePtr = '\0';	/* Zero-terminate filename */
    132 
    133 	mangle_name(VGAFileMBuf, VGAFileBuf);
    134 	f = fopen(VGAFileMBuf, "r");
    135 	if (!f) {
    136 		/* Not there */
    137 		NextCharJump = msg_putchar;
    138 		return;
    139 	}
    140 
    141 	vgadisplayfile(f);
    142 	fclose(f);
    143 	msg_initvars();
    144 }
    145 
    146 /*
    147  * Getting VGA filename
    148  */
    149 static void msg_filename(uint8_t data)
    150 {
    151 	/* <LF> = end of filename */
    152 	if (data == 0x0A) {
    153 		msg_viewimage();
    154 		return;
    155 	}
    156 
    157 	/* Ignore space/control char */
    158 	if (data > ' ') {
    159 		if ((char *)VGAFilePtr < (VGAFileBuf + sizeof(VGAFileBuf)))
    160 			*VGAFilePtr++ = data;
    161 	}
    162 }
    163 
    164 static void msg_vga(void)
    165 {
    166 	NextCharJump = msg_filename;
    167 	VGAFilePtr = (uint16_t *)VGAFileBuf;
    168 }
    169 
    170 static void msg_normal(uint8_t data)
    171 {
    172 	/* 0x1 = text mode, 0x2 = graphics mode */
    173 	if (!display_mask_vga() || !(DisplayCon & 0x01)) {
    174 		/* Write to serial port */
    175 		if (DisplayMask & 0x4)
    176 			write_serial(data);
    177 
    178 		return;		/* Not screen */
    179 	}
    180 
    181 	set_fgbg();
    182 	printf("%c\033[0m", data);
    183 }
    184 
    185 static void msg_modectl(uint8_t data)
    186 {
    187 	data &= 0x07;
    188 	DisplayMask = data;
    189 	NextCharJump = msg_putchar;
    190 }
    191 
    192 static void msg_putchar(uint8_t ch)
    193 {
    194 	/* 10h to 17h are mode controls */
    195 	if (ch >= 0x10 && ch < 0x18) {
    196 		msg_modectl(ch);
    197 		return;
    198 	}
    199 
    200 	switch (ch) {
    201 	case 0x0F:		/* ^O = color code follows */
    202 		msg_ctrl_o();
    203 		break;
    204 	case 0x0D:		/* Ignore <CR> */
    205 		break;
    206 	case 0x0C:		/* <FF> = clear screen */
    207 		msg_formfeed();
    208 		break;
    209 	case 0x19:		/* <EM> = return to text mode */
    210 		msg_novga();
    211 		break;
    212 	case 0x18:		/* <CAN> = VGA filename follows */
    213 		msg_vga();
    214 		break;
    215 	default:
    216 		msg_normal(ch);
    217 		break;
    218 	}
    219 }
    220 
    221 /*
    222  * Subroutine to initialize variables, also needed after loading
    223  * graphics file.
    224  */
    225 void msg_initvars(void)
    226 {
    227 	/* Initialize state machine */
    228 	NextCharJump = msg_putchar;
    229 }
    230