backported fixes from 256boss
[bootcensus] / src / contty.c
index 6601ce8..9fdf1c7 100644 (file)
@@ -40,18 +40,20 @@ along with this program.  If not, see <https://www.gnu.org/licenses/>.
 #define CRTC_REG_CURLOC_L      0x0f
 
 #define VMEM_CHAR(c, attr) \
-       ((uint16_t)(c) | ((uint16_t)(attr) << 8))
+       (((uint16_t)(c) & 0xff) | ((uint16_t)(attr) << 8))
 
 static void scroll(void);
 static void crtc_cursor(int x, int y);
 static void crtc_setstart(int y);
 static inline unsigned char crtc_read(int reg);
 static inline void crtc_write(int reg, unsigned char val);
-static inline void crtc_write_bits(int reg, unsigned char val, unsigned char mask);
 
 extern int cursor_x, cursor_y;
 static unsigned char txattr = 0x07;
 static int start_line;
+static unsigned char cy0, cy1;
+static int curvis;
+static int scr_on = 1;
 
 int con_init(void)
 {
@@ -60,26 +62,39 @@ int con_init(void)
 #endif
 
 #ifdef CON_TEXTMODE
+       cy0 = crtc_read(CRTC_REG_CURSTART);
+       curvis = cy0 & 0x20 ? 1 : 0;
+       cy0 &= 0x1f;
+       cy1 = crtc_read(CRTC_REG_CUREND) & 0x1f;
+
        con_show_cursor(1);
        crtc_setstart(0);
        crtc_cursor(cursor_x, cursor_y);
-       /*
-       printf("curloc: %x %x\n", (unsigned int)crtc_read(CRTC_REG_CURLOC_H),
-                       (unsigned int)crtc_read(CRTC_REG_CURLOC_L));
-       printf("curstart: %x\n", (unsigned int)crtc_read(CRTC_REG_CURSTART));
-       printf("curend: %x\n", (unsigned int)crtc_read(CRTC_REG_CUREND));
-       */
+       scr_on = 1;
 #endif
 
        return 0;
 }
 
+void con_scr_enable(void)
+{
+       scr_on = 1;
+}
+
+void con_scr_disable(void)
+{
+       scr_on = 0;
+}
+
 void con_show_cursor(int show)
 {
 #ifdef CON_TEXTMODE
-       unsigned char val = show ? 0 : 0x20;
-
-       crtc_write_bits(CRTC_REG_CURSTART, val, 0x20);
+       unsigned char val = cy0 & 0x1f;
+       if(!show) {
+               val |= 0x20;
+       }
+       crtc_write(CRTC_REG_CURSTART, val);
+       curvis = show;
 #endif
 }
 
@@ -92,6 +107,23 @@ void con_cursor(int x, int y)
 #endif
 }
 
+void con_curattr(int shape, int blink)
+{
+#ifdef CON_TEXTMODE
+       unsigned char start;
+       cy0 = (shape == CON_CURSOR_LINE) ? 0xd : 0;
+       cy1 = 0xe;
+
+       start = cy0;
+       if(curvis) {
+               start |= 0x20;
+       }
+
+       crtc_write(CRTC_REG_CURSTART, start);
+       crtc_write(CRTC_REG_CUREND, cy0);
+#endif
+}
+
 void con_fgcolor(int c)
 {
        txattr = (txattr & 0xf0) | c;
@@ -102,10 +134,20 @@ void con_bgcolor(int c)
        txattr = (txattr & 0x0f) | (c << 4);
 }
 
+void con_setattr(unsigned char attr)
+{
+       txattr = attr;
+}
+
+unsigned char con_getattr(void)
+{
+       return txattr;
+}
+
 void con_clear(void)
 {
 #ifdef CON_TEXTMODE
-       memset(TEXT_ADDR, 0, NCOLS * NROWS * 2);
+       memset16(TEXT_ADDR, VMEM_CHAR(' ', txattr), NCOLS * NROWS);
 
        start_line = 0;
        crtc_setstart(0);
@@ -126,33 +168,39 @@ static inline void linefeed(void)
 void con_putchar(int c)
 {
 #ifdef CON_TEXTMODE
-       uint16_t *ptr;
-
-       switch(c) {
-       case '\n':
-               linefeed();
-       case '\r':
-               cursor_x = 0;
-               crtc_cursor(cursor_x, cursor_y);
-               break;
-
-       case '\t':
-               cursor_x = (cursor_x & 0x7) + 8;
-               if(cursor_x >= NCOLS) {
-                       linefeed();
-                       cursor_x = 0;
-               }
-               crtc_cursor(cursor_x, cursor_y);
-               break;
-
-       default:
-               con_putchar_scr(cursor_x, cursor_y, c);
-
-               if(++cursor_x >= NCOLS) {
+       if(scr_on) {
+               switch(c) {
+               case '\n':
                        linefeed();
+               case '\r':
                        cursor_x = 0;
+                       crtc_cursor(cursor_x, cursor_y);
+                       break;
+
+               case '\t':
+                       cursor_x = (cursor_x & 0x7) + 8;
+                       if(cursor_x >= NCOLS) {
+                               linefeed();
+                               cursor_x = 0;
+                       }
+                       crtc_cursor(cursor_x, cursor_y);
+                       break;
+
+               case '\b':
+                       if(cursor_x > 0) cursor_x--;
+                       con_putchar_scr(cursor_x, cursor_y, ' ');
+                       crtc_cursor(cursor_x, cursor_y);
+                       break;
+
+               default:
+                       con_putchar_scr(cursor_x, cursor_y, c);
+
+                       if(++cursor_x >= NCOLS) {
+                               linefeed();
+                               cursor_x = 0;
+                       }
+                       crtc_cursor(cursor_x, cursor_y);
                }
-               crtc_cursor(cursor_x, cursor_y);
        }
 #endif
 
@@ -163,12 +211,15 @@ void con_putchar(int c)
 
 void con_putchar_scr(int x, int y, int c)
 {
+#ifdef CON_TEXTMODE
        uint16_t *ptr = (uint16_t*)TEXT_ADDR;
        ptr[(y + start_line) * NCOLS + x] = VMEM_CHAR(c, txattr);
+#endif
 }
 
-void con_printf(int x, int y, const char *fmt, ...)
+int con_printf(int x, int y, const char *fmt, ...)
 {
+#ifdef CON_TEXTMODE
        va_list ap;
        char buf[81];
        char *ptr = buf;
@@ -180,6 +231,10 @@ void con_printf(int x, int y, const char *fmt, ...)
        while(*ptr && x < 80) {
                con_putchar_scr(x++, y, *ptr++);
        }
+       return ptr - buf;
+#else
+       return 0;
+#endif
 }
 
 static void scroll(void)
@@ -229,12 +284,3 @@ static inline void crtc_write(int reg, unsigned char val)
        outb(reg, CRTC_ADDR);
        outb(val, CRTC_DATA);
 }
-
-static inline void crtc_write_bits(int reg, unsigned char val, unsigned char mask)
-{
-       unsigned char prev;
-       outb(reg, CRTC_ADDR);
-       prev = inb(CRTC_DATA);
-       val = (prev & ~mask) | (val & mask);
-       outb(val, CRTC_DATA);
-}