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 */
get_msg_file(char * filename)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
display_mask_vga(void)55 static inline int display_mask_vga(void)
56 {
57 uint8_t mask = UsingVGA & 0x1;
58 return (DisplayMask & ++mask);
59 }
60
msg_setbg(uint8_t data)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
msg_setfg(uint8_t data)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
msg_ctrl_o(void)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
set_fgbg(void)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
msg_formfeed(void)115 static void msg_formfeed(void)
116 {
117 set_fgbg();
118 printf("\033[2J\033[H\033[0m");
119 }
120
msg_novga(void)121 static void msg_novga(void)
122 {
123 syslinux_force_text_mode();
124 msg_initvars();
125 }
126
msg_viewimage(void)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 */
msg_filename(uint8_t data)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
msg_vga(void)164 static void msg_vga(void)
165 {
166 NextCharJump = msg_filename;
167 VGAFilePtr = (uint16_t *)VGAFileBuf;
168 }
169
msg_normal(uint8_t data)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
msg_modectl(uint8_t data)185 static void msg_modectl(uint8_t data)
186 {
187 data &= 0x07;
188 DisplayMask = data;
189 NextCharJump = msg_putchar;
190 }
191
msg_putchar(uint8_t ch)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 */
msg_initvars(void)225 void msg_initvars(void)
226 {
227 /* Initialize state machine */
228 NextCharJump = msg_putchar;
229 }
230