diff options
Diffstat (limited to 'com32/elflink/ldlinux/msg.c')
-rw-r--r-- | com32/elflink/ldlinux/msg.c | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/com32/elflink/ldlinux/msg.c b/com32/elflink/ldlinux/msg.c new file mode 100644 index 0000000..1a97b3c --- /dev/null +++ b/com32/elflink/ldlinux/msg.c @@ -0,0 +1,229 @@ +#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; +} |