Skip to content
Snippets Groups Projects
Select Git revision
  • master
  • developement_1 protected
  • Version_1.2.4
  • Version_1.2.3
  • Version_1.2.2
  • Version_1.2.1
  • Version_1.2.0
  • Version_1.0.1
  • Version_1.0.0
  • Version_0.1.0
  • Version_0.0.6
  • Version_0.0.5
  • Version_0.0.4
  • Version_0.0.3
  • Version_0.0.2
  • Version_0.0.1
16 results

shader.cpp

  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    screen.c 14.93 KiB
    /*
     * =====================================================================================
     *
     *       Filename:  screen.c
     *
     *    Description:  
     *
     *        Version:  1.0
     *        Created:  24.08.2011 16:44:29
     *       Revision:  none
     *       Compiler:  gcc
     *
     *         Author:  Georg Wassen (gw) (wassen@lfbs.rwth-aachen.de), 
     *        Company:  Lehrstuhl für Betriebssysteme (Chair for Operating Systems)
     *                  RWTH Aachen University
     *
     * Copyright (c) 2011, Georg Wassen, RWTH Aachen University
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions are met:
     *    * Redistributions of source code must retain the above copyright
     *      notice, this list of conditions and the following disclaimer.
     *    * Redistributions in binary form must reproduce the above copyright
     *      notice, this list of conditions and the following disclaimer in the
     *      documentation and/or other materials provided with the distribution.
     *    * Neither the name of the University nor the names of its contributors
     *      may be used to endorse or promote products derived from this
     *      software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
     * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     * =====================================================================================
     */
    #include "system.h"
    #include "cpu.h"
    
    #ifndef EARLY
    #include "sync.h"
    #endif
    
    /*
     * This file is used in 32-Bit Boot Code (REAL MODE) called from startXX.asm and boot32.c
     * as well as in the final kernel (main.c etc.) for 32- and 64-bit mode.
     */
    
    /* These define our textpointer, our background and foreground
    *  colors (attributes), and x and y cursor coordinates */
    static uint16_t *textmemptr;
    static uint8_t attrib = ATTRIB(COLOR_FG_WHITE, COLOR_BG_BLACK); //0x0F;
    static uint8_t attrib_status = 0x1F;
    static uint8_t csr_x = 0, csr_y = 0;
    static uint8_t screen_h = 25;              /* screen height (currently constant, but may be set according to multiboot info) */
    static uint8_t screen_w = 80;              /* screen width  (currently constant, but may be set according to multiboot info) */
    
    #if !defined(EARLY) && SCROLLBACK_BUF_SIZE
    static char* buf_scrollback = NULL;
    static unsigned buf_x = 0, buf_y = 0;
    #endif
    
    #ifndef EARLY
    extern volatile unsigned cpu_online;
    #endif
    
    /* Scrolls the screen */
    static void scroll(void)
    {
        uint16_t blank, temp;
    
        /* A blank is defined as a space... we need to give it
        *  backcolor too */
        blank = 0x20 | (ATTRIB(COLOR_FG_WHITE, COLOR_BG_BLACK) << 8); // (attrib << 8);
    
        /* Row screen_h ( = 25) is the end, this means we need to scroll up */
        if(csr_y >= screen_h)
        {
            /* Move the current text chunk that makes up the screen
            *  back in the buffer by a line */
            temp = csr_y - screen_h + 1;         /* skip first line (used as status monitor) */
            memcpy ((uint16_t*)textmemptr + screen_w, (uint16_t*)textmemptr + (temp+1) * screen_w, (screen_h - temp ) * screen_w * 2);
    
            /* Finally, we set the chunk of memory that occupies
            *  the last line of text to our 'blank' character */
            memsetw (textmemptr + (screen_h - temp) * screen_w, blank, screen_w);
            csr_y = screen_h - 1;
        }
    }
    
    /* Updates the hardware cursor: the little blinking line
    *  on the screen under the last character pressed! */
    static void move_csr(void)
    {
        unsigned temp;
    
        /* The equation for finding the index in a linear
        *  chunk of memory can be represented by:
        *  Index = [(y * width) + x] */
        temp = csr_y * screen_w + csr_x;
    
        /* This sends a command to indicies 14 and 15 in the
        *  CRT Control Register of the VGA controller. These
        *  are the high and low bytes of the index that show
        *  where the hardware cursor is to be 'blinking'. To
        *  learn more, you should look up some VGA specific
        *  programming documents. A great start to graphics:
        *  http://www.brackeen.com/home/vga */
        outportb(0x3D4, 14);
        outportb(0x3D5, temp >> 8);
        outportb(0x3D4, 15);
        outportb(0x3D5, temp);
    }
    
    /* Clears the screen */
    void cls()
    {
        uint16_t blank;
        int i;
    
        /* Again, we need the 'short' that will be used to
        *  represent a space with color */
        blank = 0x20 | (attrib << 8);
    
        /* set background color of status line */
        for (i=0; i < screen_w; i++)
            *((uint8_t*)(textmemptr + i)+1) = attrib_status;
    
        /* Sets the entire screen to spaces in our current
        *  color */
        /* skip first line (used as status monitor) */
        for(i = 1; i < screen_h; i++)
            memsetw (textmemptr + i * screen_w, blank, screen_w);
    
        /* Update out virtual cursor, and then move the
        *  hardware cursor */
        csr_x = 0;
        csr_y = 0;
    #   if !defined(EARLY) && SCROLLBACK_BUF_SIZE
        buf_x = 0;
        buf_y++;
        if (buf_y > SCROLLBACK_BUF_SIZE) {
            buf_y = 0;
            printf("Scrollback overflow!\n");
        }
    #   endif
        move_csr();
    }
    
    void locate(int abs_x, int rel_y)
    {
        csr_x = abs_x;
        csr_y += rel_y;
    #   if !defined(EARLY) && SCROLLBACK_BUF_SIZE
        buf_x = csr_x;
        buf_y += rel_y;
    #   endif
    }
    
    /* Puts a single character on the screen */
    void putch(char c)
    {
        unsigned short *where;
        unsigned att = attrib << 8;
    
        /* Handle a backspace, by moving the cursor back one space */
        if(c == 0x08)       //   '\b'
        {
            if(csr_x != 0) csr_x--;
    #       if !defined(EARLY) && SCROLLBACK_BUF_SIZE
            buf_x = csr_x;
    #       endif
        }
        /* Handles a tab by incrementing the cursor's x, but only
        *  to a point that will make it divisible by 8 */
        else if(c == 0x09)  //   '\t'
        {
            csr_x = (csr_x + 8) & ~(8 - 1);
    #       if !defined(EARLY) && SCROLLBACK_BUF_SIZE
            buf_x = csr_x;
    #       endif
        }
        /* Handles a 'Carriage Return', which simply brings the
        *  cursor back to the margin */
        else if(c == '\r')
        {
            csr_x = 0;
    #       if !defined(EARLY) && SCROLLBACK_BUF_SIZE
            buf_x = csr_x;
    #       endif
        }
        /* We handle our newlines the way DOS and the BIOS do: we
        *  treat it as if a 'CR' was also there, so we bring the
        *  cursor to the margin and we increment the 'y' value */
        else if(c == '\n')
        {
            csr_x = 0;
            csr_y++;
    #       if !defined(EARLY) && SCROLLBACK_BUF_SIZE
            buf_x = csr_x;
            buf_y++;
            if (buf_y > SCROLLBACK_BUF_SIZE) {
                buf_y = 0;
                printf("Scrollback overflow!\n");
            }
    #       endif
        }
        /* Any character greater than and including a space, is a
        *  printable character. The equation for finding the index
        *  in a linear chunk of memory can be represented by:
        *  Index = [(y * width) + x] */
        else if(c >= ' ')
        {
            where = textmemptr + (csr_y * screen_w + csr_x);
            *where = c | att;	/* Character AND attributes: color */
            csr_x++;
    #       if !defined(EARLY) && SCROLLBACK_BUF_SIZE
                if (buf_scrollback != NULL) {
                    buf_scrollback[buf_y*80+buf_x] = c;
                }
                buf_x = csr_x;
    #       endif
        }
    
        /* If the cursor has reached the edge of the screen's width, we
        *  insert a new line in there */
        if(csr_x >= screen_w)
        {
            csr_x = 0;
            csr_y++;
    #       if !defined(EARLY) && SCROLLBACK_BUF_SIZE
            buf_x = csr_x;
            buf_y++;
    #       endif
        }
    
        /* Scroll the screen if needed, and finally move the cursor */
        scroll();
        move_csr();
    }
    
    /*
     * This functions puts the character c at the position x in the first line (the status monitor)
     * The cursor (for putch, puts, printf, et. al.) is NOT moved.
     * Scrolling does not touch the status monitor line.
     */
    void status_putch(int x, int c)
    {
        *((uint16_t*)textmemptr + x) = c | (attrib_status << 8);
    }
    
    /* Uses the above routine to output a string... */
    void puts(char *text)
    {
        int i;
    
        for (i = 0; i < strlen((const char*)text); i++)
        {
            putch(text[i]);
        }
    }
    
    /* Sets the forecolor and backcolor that we will use */
    void settextcolor(unsigned char forecolor, unsigned char backcolor)
    {
        /* Top 4 bits are the background, bottom 4 bits
        *  are the foreground color */
        //attrib = (backcolor << 4) | (forecolor & 0x0F);
        attrib = ATTRIB(forecolor, backcolor);
    }
    unsigned char gettextattrib()
    {
        return attrib;
    }
    void settextattrib(unsigned char a)
    {
        attrib = a;
    }
    
    /* Sets our text-mode VGA pointer, then clears the screen for us */
    void init_video(void)
    {
        textmemptr = (unsigned short *)0xB8000;
        cls();
        csr_y = 1;      /* skip first line (used as status monitor) */
    }
    
    #if !defined(EARLY) && SCROLLBACK_BUF_SIZE
    #include "mm.h"
    #include "keyboard.h"
    void init_video_scrollback(void)
    {
        printf("scrollback buffer initialized\n");
        buf_scrollback = heap_alloc(SCROLLBACK_BUF_SIZE / PAGE_SIZE, 0);
        memset(buf_scrollback, ' ', SCROLLBACK_BUF_SIZE);
        buf_y = 0;
    }
    void video_scrollback(void)
    {
        unsigned s= 9 + cpu_online;
        char msg[] = "SCROLLBACK (exit with ESC) ";
        char *m = &msg[0];
        unsigned offset_y = 0;
        unsigned x, y;
        uint8_t key;
        unsigned do_exit = 0;
    
        while (*m != 0) status_putch(s++, *m++);
    
        while (!do_exit) {
            if (offset_y > SCROLLBACK_BUF_SIZE) offset_y = SCROLLBACK_BUF_SIZE;
            for (y=0; y<23; y++) {
                for (x=0; x<80; x++) {
                    textmemptr[(y+1)*80+x] = 0x0F00 | buf_scrollback[(y+offset_y)*80+x];
                }
            }
    
            key = wait_for_key();
            switch(key) {
                case KEY_ESC  : do_exit = 1; break;
                case KEY_UP   : if (offset_y > 0) offset_y--; break;
                case KEY_DOWN : offset_y++; break;
                case KEY_PGDOWN : offset_y+=20; break;
                case KEY_HOME : offset_y = 0; break;
                case KEY_END : offset_y = buf_y; //break;
                case KEY_PGUP   : if (offset_y > 20) offset_y-=20; else offset_y = 0; break;
            }
        }
    
    }
    #endif
    
    ////////////////////////////////////////////////////////////////////////////////
    // the following is from the multiboot specification
    // http://www.gnu.org/software/grub/manual/multiboot/multiboot.html#multiboot_002eh
    ////////////////////////////////////////////////////////////////////////////////
    
    /* Convert the integer D to a string and save the string in BUF. If
       BASE is equal to 'd', interpret that D is decimal, and if BASE is
       equal to 'x', interpret that D is hexadecimal. */
    void itoa (char *buf, int base, long d)
    {
      char *p = buf;
      char *p1, *p2;
      unsigned long ud = *((unsigned long*)&d);
      int divisor = 10;
    
      if (base == 'p') base = 'x';
    
      /* If %d is specified and D is minus, put `-' in the head. */
      if (base == 'd' && d < 0)
        {
          *p++ = '-';
          buf++;
          ud = -d;
        }
      else if (base == 'x')
        divisor = 16;
    
      /* Divide UD by DIVISOR until UD == 0. */
      do
        {
          int remainder = ud % divisor;
    
          *p++ = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10;
        }
      while (ud /= divisor);
    
      /* Terminate BUF. */
      *p = 0;
    
      /* Reverse BUF. */
      p1 = buf;
      p2 = p - 1;
      while (p1 < p2)
        {
          char tmp = *p1;
          *p1 = *p2;
          *p2 = tmp;
          p1++;
          p2--;
        }
    }
    
    
     /* Format a string and print it on the screen, just like the libc
       function printf. */
    #ifndef EARLY
    mutex_t mutex_printf = MUTEX_INITIALIZER;
    #endif
    
    /*
     * TODO : does not work on xaxis with 32 bit
     *          (Qemu32 works...)
     *
     *          WHY ?!?
     *
     *          could be the __builtin_va_list that does not work --without-builtins...
     *
     */
    
    static void vprintf(const char *format, __builtin_va_list ap)
    {
      int c;
      char buf[20];
      unsigned long value;
      char bi_prefix[] = {' ', 'k', 'M', 'G', 'T'};
    
      while ((c = *format++) != 0)
        {
          if (c != '%')
            putch (c);
          else
            {
              char *p;
              int len = 0;
              unsigned hash = 0;
              char prefix = ' ';
              unsigned bi_pref_idx = 0;
    
              c = *format++;
              if (len == 0 && c == '#') {
                  hash = 1;
                  c = *format++;
              }
              if (len == 0 && c == '0') {
                  prefix = '0';
                  c = *format++;
              }
              while (c >= '0' && c <= '9') {
                  len *= 10;
                  len += (c-'0');
                  c = *format++;
              }
              switch (c)
                {
                case 'd':
                case 'i':
                  value = __builtin_va_arg(ap, long);
                  goto weiter;
                case 'u':
                case 'x':
                case 'p':
                  value = __builtin_va_arg(ap, unsigned long);
                  if (c == 'u' && hash) {
                      while (value >= 1024 && (value%1024) == 0) {
                          value >>= 10;
                          bi_pref_idx++;
                      }
                      if (!len) len=6;
                  }
                weiter:
                  if ((c == 'x' || c == 'p') && hash) {
                      buf[0] = '0';
                      buf[1] = 'x';
                      itoa (buf+2, c, value);
                  } else {
                      itoa (buf, c, value);
                  }
                  if (c == 'u' && hash) {
                      unsigned l = strlen(buf);
                      buf[l++] = ' ';
                      buf[l++] = bi_prefix[bi_pref_idx];
                      buf[l++] = 0;
                      bi_pref_idx = 0;
                  }
                  p = buf;
                  goto string;
                  break;
    
                  /*
                case 'c':
                  value = __builtin_va_arg(ap, char);
                  putch(value);
                  break;
                  */
    
                case 's':
                  p = __builtin_va_arg(ap, char*);
                  if (! p)
                    p = "(null)";
    
                string:
                  len -= strlen(p);
                  while (len > 0) {
                      putch(prefix);
                      len--;
                  }
                  while (*p)
                    putch (*p++);
                  break;
    
                default:
                  value = __builtin_va_arg(ap, long);
                  putch (value);
                  break;
                }
            }
        }
    }
    
    void printf_nomutex(const char *format, ...)
    {
      __builtin_va_list ap;
      __builtin_va_start(ap, format);
      vprintf(format, ap);
      __builtin_va_end(ap);
    }
    
    void printf (const char *format, ...)
    {
      __builtin_va_list ap;
      __builtin_va_start(ap, format);
    
    # ifndef EARLY
      mutex_lock(&mutex_printf);
    # endif
    
      vprintf(format, ap);
    
    
    # ifndef EARLY
      mutex_unlock(&mutex_printf);
    # endif
      __builtin_va_end(ap);
    }