230 lines
4.1 KiB
C
230 lines
4.1 KiB
C
#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;
|
|
}
|