blob: 1a97b3c02e9610f5efd46495fb439e03c801f888 [file] [log] [blame]
Greg Hartman76d05dc2016-11-23 15:51:27 -08001#include <syslinux/video.h>
2#include <com32.h>
3#include <stdio.h>
4#include <bios.h>
5#include <graphics.h>
6
7static uint8_t TextAttribute; /* Text attribute for message file */
8extern uint8_t DisplayMask; /* Display modes mask */
9
10/* Routine to interpret next print char */
11static void (*NextCharJump)(uint8_t);
12
13void msg_initvars(void);
14static void msg_setfg(uint8_t data);
15static 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 */
24int 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
55static inline int display_mask_vga(void)
56{
57 uint8_t mask = UsingVGA & 0x1;
58 return (DisplayMask & ++mask);
59}
60
61static 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
75static 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
88static inline void msg_ctrl_o(void)
89{
90 NextCharJump = msg_setbg;
91}
92
93/* Convert ANSI colors to PC display attributes */
94static int convert_to_pcdisplay[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
95
96static 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
115static void msg_formfeed(void)
116{
117 set_fgbg();
118 printf("\033[2J\033[H\033[0m");
119}
120
121static void msg_novga(void)
122{
123 syslinux_force_text_mode();
124 msg_initvars();
125}
126
127static 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 */
149static 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
164static void msg_vga(void)
165{
166 NextCharJump = msg_filename;
167 VGAFilePtr = (uint16_t *)VGAFileBuf;
168}
169
170static 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
185static void msg_modectl(uint8_t data)
186{
187 data &= 0x07;
188 DisplayMask = data;
189 NextCharJump = msg_putchar;
190}
191
192static 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 */
225void msg_initvars(void)
226{
227 /* Initialize state machine */
228 NextCharJump = msg_putchar;
229}