/*
    exDOS - Experimental 32 Bit protected mode scripted operating system
    (C) 2005 Jason Hunt
    
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

    Contact: nulluser@gmail.com

    File: video.c
*/

#include "types.h"
#include "video.h"
#include "system.h"

byte *vga = (byte *) 0xb8000;           // Base address of video

volatile byte x_pos = 0;                // Cursor position
volatile byte y_pos = 3;

volatile byte vga_text_attr = 0x07;     // Current text attribites

volatile byte vga_move_cursor = 1;      // True of the cursor should be moved

#define text_x_size 80
#define text_y_size 25

extern volatile dword debug_count;
extern volatile word key_intr_count;


/* Return the current cursor */
void vga_get_cursor(byte *x, byte *y)
{
    *x = x_pos;
    *y = y_pos;
}
/* end of vga_get_cursor */


/* Set the current cursor pos */
void vga_set_cursor(byte x, byte y)
{
    x_pos = x;
    y_pos = y;
}
/* end of vga_set_cursor */


/* Update the hardware cursor */
void vga_update_cursor(void)
{
    // Calculate offset
    word offset = (y_pos << 6) + (y_pos << 4) + x_pos;

    out_byte(0x03d4, 0x0f);             // Setup for low byte latch
    out_byte(0x03d5, offset & 0xff);    // Latch the low byte
    
    out_byte(0x03d4, 0x0e);             // Setup for high byte latch
    out_byte(0x03d5, offset >> 8);      // Latch the high byte
}
/* End of video_update_cursor */



/* Write a char to the display, update manage cursor pos */
void vga_put_char(byte c)
{
    if (c < 0x20 && c != 0x0a) return;   // do not display non-pritables
    
    if (c == 0x0a)          // End of line?
    {
        x_pos = 0;
        y_pos++;
    }
    else                    // Normal char
    {
        // Get offset into video
        word offset = (x_pos << 1) + (y_pos << 7) + (y_pos << 5);
    
        vga[offset++] = c;                      // Set char
        vga[offset] = vga_text_attr;                // Set attrib
        x_pos++;                                // Move cursor
    }    
                
    if (x_pos == 80)    // End of line
    {
        x_pos = 0;
        y_pos ++;
    }    

    if (y_pos == 25) // Scroll display
    {
        y_pos = 24;

        if (vga_move_cursor)
            vga_screen_up();  
    }   
    
    if (vga_move_cursor)        // Update the cursor pos, if needed
        vga_update_cursor();
}
/* End of put_char */


/* Display a string. */
void vga_put_str(char * s)
{
    while (*s) vga_put_char(*s++);
}
/* End of display string */



/* Display 4 bits as hex */
void vga_put_hex_nibble(byte n)
{
    n &= 0x0f;      // Mask off any unused data

    if (n > 9)
        vga_put_char(n + 'A' - 10);
    else     
        vga_put_char(n + '0');
}     
/* End of put_hex_nibble */


/* Display a byte as hex */
void vga_put_hex(byte n)
{
    vga_put_hex_nibble(n >> 4);
    vga_put_hex_nibble(n);
}
/* End of put_hex */


/* Display a byte as hex */
void vga_put_hex_16(word n)
{
    vga_put_hex(n >> 8);
    vga_put_hex(n);
}
/* End of put_hex */

/* Display a byte as hex */
void vga_put_hex_32(dword n)
{
    vga_put_hex_16(n >> 16);
    vga_put_hex_16(n);
}
/* End of put_hex */


/* Draw status bar on top */
void vga_draw_status( void )
{
    unsigned char old_x = x_pos;
    unsigned char old_y = y_pos;
    unsigned char old_attr = vga_text_attr;
    unsigned char old_move_cursor = vga_move_cursor;
    
    byte i;
    
    vga_text_attr = 0x1f;
    
    vga_move_cursor = 0;
    
    x_pos = 0;
    y_pos = 0;

    for (i = 0; i < 80; i++) vga_put_char(' ');

    x_pos = 0;
    y_pos = 0;
     
    vga_put_str("exDOS Version " KVERSION " -- 2005 Jason Hunt");
     
    x_pos = 70;
    vga_put_hex_32(debug_count);

    x_pos = 60;
    vga_put_hex_32(key_intr_count);

           
    vga_move_cursor = old_move_cursor;   
    x_pos = old_x;
    y_pos = old_y;
    vga_text_attr = old_attr;
}
/* End of draw status bar */


/* Sets text attribute */
void vga_set_attr(byte attr)
{
    vga_text_attr = attr;
}
/* End of vga_set_attr */


/* Gets text attribute */
byte vga_get_attr(void)
{
    return(vga_text_attr);
}
/* End of vga_get_attr */



/* Enables cursor movement on write */
void vga_enable_cursor_move( void )
{
    vga_move_cursor = 1;
}
/* End of vga_enable_cursor_move */


/* Disables cursor movement on write */
void vga_disable_cursor_move( void )
{
    vga_move_cursor = 0;
}
/* End of vga_enable_cursor_move */


/* Returns the address of the frame buffer */
byte * vga_get_buffer_addr( void )
{
    return(vga);
}
/* Vga_get_buffer_addr */













