#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;
}