| #include <syslinux/video.h> |
| #include <com32.h> |
| #include <stdio.h> |
| #include <bios.h> |
| #include <graphics.h> |
| |
| static uint8_t TextAttribute; /* Text attribute for message file */ |
| extern uint8_t DisplayMask; /* Display modes mask */ |
| |
| /* Routine to interpret next print char */ |
| static void (*NextCharJump)(uint8_t); |
| |
| void msg_initvars(void); |
| static void msg_setfg(uint8_t data); |
| static void msg_putchar(uint8_t ch); |
| |
| /* |
| * |
| * get_msg_file: Load a text file and write its contents to the screen, |
| * interpreting color codes. |
| * |
| * Returns 0 on success, -1 on failure. |
| */ |
| int get_msg_file(char *filename) |
| { |
| FILE *f; |
| char ch; |
| |
| f = fopen(filename, "r"); |
| if (!f) |
| return -1; |
| |
| TextAttribute = 0x7; /* Default grey on white */ |
| DisplayMask = 0x7; /* Display text in all modes */ |
| msg_initvars(); |
| |
| /* |
| * Read the text file a byte at a time and interpret that |
| * byte. |
| */ |
| while ((ch = getc(f)) != EOF) { |
| /* DOS EOF? */ |
| if (ch == 0x1A) |
| break; |
| |
| NextCharJump(ch); /* Do what shall be done */ |
| } |
| |
| DisplayMask = 0x07; |
| |
| fclose(f); |
| return 0; |
| } |
| |
| static inline int display_mask_vga(void) |
| { |
| uint8_t mask = UsingVGA & 0x1; |
| return (DisplayMask & ++mask); |
| } |
| |
| static void msg_setbg(uint8_t data) |
| { |
| if (unhexchar(&data) == 0) { |
| data <<= 4; |
| if (display_mask_vga()) |
| TextAttribute = data; |
| |
| NextCharJump = msg_setfg; |
| } else { |
| TextAttribute = 0x7; /* Default attribute */ |
| NextCharJump = msg_putchar; |
| } |
| } |
| |
| static void msg_setfg(uint8_t data) |
| { |
| if (unhexchar(&data) == 0) { |
| if (display_mask_vga()) { |
| /* setbg set foreground to 0 */ |
| TextAttribute |= data; |
| } |
| } else |
| TextAttribute = 0x7; /* Default attribute */ |
| |
| NextCharJump = msg_putchar; |
| } |
| |
| static inline void msg_ctrl_o(void) |
| { |
| NextCharJump = msg_setbg; |
| } |
| |
| /* Convert ANSI colors to PC display attributes */ |
| static int convert_to_pcdisplay[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; |
| |
| static void set_fgbg(void) |
| { |
| uint8_t bg, fg; |
| |
| fg = convert_to_pcdisplay[(TextAttribute & 0x7)]; |
| bg = convert_to_pcdisplay[((TextAttribute >> 4) & 0x7)]; |
| |
| printf("\033["); |
| if (TextAttribute & 0x8) |
| printf("1;"); /* Foreground bright */ |
| |
| printf("3%dm\033[", fg); |
| |
| if (TextAttribute & 0x80) |
| printf("5;"); /* Foreground blink */ |
| |
| printf("4%dm", bg); |
| } |
| |
| static void msg_formfeed(void) |
| { |
| set_fgbg(); |
| printf("\033[2J\033[H\033[0m"); |
| } |
| |
| static void msg_novga(void) |
| { |
| syslinux_force_text_mode(); |
| msg_initvars(); |
| } |
| |
| static void msg_viewimage(void) |
| { |
| FILE *f; |
| |
| *VGAFilePtr = '\0'; /* Zero-terminate filename */ |
| |
| mangle_name(VGAFileMBuf, VGAFileBuf); |
| f = fopen(VGAFileMBuf, "r"); |
| if (!f) { |
| /* Not there */ |
| NextCharJump = msg_putchar; |
| return; |
| } |
| |
| vgadisplayfile(f); |
| fclose(f); |
| msg_initvars(); |
| } |
| |
| /* |
| * Getting VGA filename |
| */ |
| static void msg_filename(uint8_t data) |
| { |
| /* <LF> = end of filename */ |
| if (data == 0x0A) { |
| msg_viewimage(); |
| return; |
| } |
| |
| /* Ignore space/control char */ |
| if (data > ' ') { |
| if ((char *)VGAFilePtr < (VGAFileBuf + sizeof(VGAFileBuf))) |
| *VGAFilePtr++ = data; |
| } |
| } |
| |
| static void msg_vga(void) |
| { |
| NextCharJump = msg_filename; |
| VGAFilePtr = (uint16_t *)VGAFileBuf; |
| } |
| |
| static void msg_normal(uint8_t data) |
| { |
| /* 0x1 = text mode, 0x2 = graphics mode */ |
| if (!display_mask_vga() || !(DisplayCon & 0x01)) { |
| /* Write to serial port */ |
| if (DisplayMask & 0x4) |
| write_serial(data); |
| |
| return; /* Not screen */ |
| } |
| |
| set_fgbg(); |
| printf("%c\033[0m", data); |
| } |
| |
| static void msg_modectl(uint8_t data) |
| { |
| data &= 0x07; |
| DisplayMask = data; |
| NextCharJump = msg_putchar; |
| } |
| |
| static void msg_putchar(uint8_t ch) |
| { |
| /* 10h to 17h are mode controls */ |
| if (ch >= 0x10 && ch < 0x18) { |
| msg_modectl(ch); |
| return; |
| } |
| |
| switch (ch) { |
| case 0x0F: /* ^O = color code follows */ |
| msg_ctrl_o(); |
| break; |
| case 0x0D: /* Ignore <CR> */ |
| break; |
| case 0x0C: /* <FF> = clear screen */ |
| msg_formfeed(); |
| break; |
| case 0x19: /* <EM> = return to text mode */ |
| msg_novga(); |
| break; |
| case 0x18: /* <CAN> = VGA filename follows */ |
| msg_vga(); |
| break; |
| default: |
| msg_normal(ch); |
| break; |
| } |
| } |
| |
| /* |
| * Subroutine to initialize variables, also needed after loading |
| * graphics file. |
| */ |
| void msg_initvars(void) |
| { |
| /* Initialize state machine */ |
| NextCharJump = msg_putchar; |
| } |