285 lines
7.4 KiB
C
285 lines
7.4 KiB
C
#include <stdarg.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <system.h>
|
|
#include <conio.h>
|
|
|
|
byte default_background, default_foreground;
|
|
|
|
char hex[] = "0123456789ABCDEF";
|
|
const static char base_chars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
|
|
int abs(int x)
|
|
{
|
|
return (x>0) ? (x) : (x*-1);
|
|
}
|
|
|
|
void graphics_init()
|
|
{
|
|
// Detect if color/monochrome screen
|
|
char c = (*(volatile unsigned short*)0x410)&0x30;
|
|
if (c==0x30) TextVideoRam = (byte *)0xb0000;
|
|
else TextVideoRam = (byte *)0xb8000;
|
|
|
|
// Reset cursor, use 80x25 text video mode
|
|
current_mode_width = 80;
|
|
current_mode_height = 25;
|
|
cursor_x = cursor_y = 0;
|
|
|
|
}
|
|
|
|
|
|
// Change cursor position
|
|
void text_mode_cursor(int x, int y)
|
|
{
|
|
unsigned temp = y*current_mode_width + x;
|
|
|
|
outportb (0x3D4, 14);
|
|
outportb (0x3D5, temp >> 8);
|
|
outportb (0x3D4, 15);
|
|
outportb (0x3D5, temp);
|
|
}
|
|
|
|
// Set the default colors; max is 0x0F
|
|
void set_default_colors(byte back, byte fore)
|
|
{
|
|
if (back < 0x10) default_background = back;
|
|
if (fore < 0x10) default_foreground = fore;
|
|
}
|
|
|
|
|
|
// Clear screen, and set font to default font
|
|
void clrscr()
|
|
{
|
|
byte font = default_foreground | (default_background<<4);
|
|
int i = 0;
|
|
for (i = 0; i < current_mode_width*current_mode_height; i++)
|
|
{ TextVideoRam[2*i] = 0;
|
|
TextVideoRam[2*i+1] = font;
|
|
}
|
|
cursor_x = 0; cursor_y = 0;
|
|
}
|
|
|
|
void scroll(int n)
|
|
{
|
|
memcpy(TextVideoRam,
|
|
TextVideoRam+(current_mode_width*n*2),
|
|
2*current_mode_width*(current_mode_height - n));
|
|
|
|
byte blank = default_foreground | (default_background<<4);
|
|
|
|
int i;
|
|
for (i = current_mode_width*(current_mode_height-n);
|
|
i < current_mode_width*current_mode_height; i++){
|
|
TextVideoRam[2*i] = 0;
|
|
TextVideoRam[2*i+1] = blank;
|
|
}
|
|
}
|
|
|
|
|
|
void prev_line()
|
|
{
|
|
cursor_x = 79;
|
|
if (--cursor_y < 0) {
|
|
cursor_y = 0; cursor_x=0;
|
|
}
|
|
}
|
|
|
|
void next_line()
|
|
{
|
|
cursor_x = 0;
|
|
if (++cursor_y >=25) {
|
|
cursor_y = 24; scroll(1);
|
|
}
|
|
}
|
|
|
|
|
|
// Put character on screen in specified position; can use different font colors
|
|
void putc_pos_font(int x, int y, char c, byte back, byte fore)
|
|
{
|
|
TextVideoRam[2*(y*current_mode_width+x)] = c;
|
|
TextVideoRam[2*(y*current_mode_width+x)+1] = fore|(back<<4);
|
|
}
|
|
// Put character on screen in specified position; use default font colors
|
|
void putc_pos(int x, int y, char c)
|
|
{
|
|
TextVideoRam[2*(y*current_mode_width+x)] = c;
|
|
}
|
|
// Put character on screen in the current cursor position; different font colors
|
|
void putc_font(char c, byte back, byte fore)
|
|
{
|
|
if (cursor_x >= current_mode_width) next_line();
|
|
|
|
if (c == '\n') {next_line(); return;};
|
|
TextVideoRam[2*(cursor_y*current_mode_width+cursor_x)] = c;
|
|
TextVideoRam[2*(cursor_y*current_mode_width+cursor_x)+1] = fore|(back<<4);
|
|
cursor_x++;
|
|
}
|
|
// Put character on screen in the current cursor position; default font colors
|
|
void putc(char c)
|
|
{
|
|
if (cursor_x >= current_mode_width) next_line();
|
|
|
|
if (c == '\n') {next_line(); return;};
|
|
if (c == '\r') {cursor_x = 0; return; };
|
|
TextVideoRam[2*(cursor_y*current_mode_width+cursor_x)] = c;
|
|
cursor_x++;
|
|
}
|
|
|
|
// Unsigned INT to ASCII
|
|
void uitoa (unsigned int value, char *string, int radix)
|
|
{
|
|
if (radix == 1 || radix>36) return;
|
|
|
|
// Calculate how much space needed for number
|
|
int len, temp = abs(value);
|
|
for (len = 0; temp > 0; len++) temp/=radix;
|
|
if (len == 0) len = 1;
|
|
|
|
string[len] = 0;
|
|
for (len--; len >=0; len-- ) {
|
|
string[len] = base_chars[value%radix];
|
|
value/=radix;
|
|
}
|
|
}
|
|
|
|
// Signed INT to ASCII
|
|
void itoa (int value, char *string, unsigned int radix)
|
|
{
|
|
if (radix < 2 || radix>36) return;
|
|
|
|
// Calculate how much space needed for number
|
|
int len, temp = abs(value);
|
|
for (len = 0; temp > 0; len++) temp/=radix;
|
|
if (len == 0) len = 1;
|
|
|
|
//Add a space for '-'
|
|
if (value<0) {
|
|
len++; string[0] = '-';
|
|
value = abs(value);
|
|
}
|
|
|
|
string[len] = 0;
|
|
for (len--; len >0; len-- ) {
|
|
string[len] = base_chars[value%radix];
|
|
value/=radix;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Put string on screen in specified position; can use different font colors
|
|
void puts_pos_font(int x, int y, const char *str, byte back, byte fore)
|
|
{
|
|
int i;
|
|
for (i = 0; str[i] != 0; i++)
|
|
putc_pos_font(x+i, y, str[i], back, fore);
|
|
|
|
}
|
|
|
|
// Put string on screen in specified position; use default font colors
|
|
void puts_pos(int x, int y, const char *str)
|
|
{
|
|
int i;
|
|
for (i = 0; str[i] != 0; i++)
|
|
putc_pos(x+i, y, str[i]);
|
|
}
|
|
void puts(const char *str)
|
|
{
|
|
int i;
|
|
for (i = 0; str[i] != 0; i++)
|
|
putc(str[i]);
|
|
}
|
|
|
|
void puts_font(const char *str, byte back, byte fore)
|
|
{
|
|
int i;
|
|
for (i = 0; str[i] != 0; i++)
|
|
putc_font(str[i], back, fore);
|
|
}
|
|
|
|
void put_hex(unsigned int alpha)
|
|
{
|
|
char nr[9];
|
|
int i;
|
|
for (i = 7; i >= 0; i--) {
|
|
nr[i] = hex[alpha%16];
|
|
alpha /= 16;
|
|
}
|
|
nr[8] = 0;
|
|
puts(nr);
|
|
}
|
|
void put_hex_pos(int x, int y, unsigned int alpha)
|
|
{
|
|
char nr[9];
|
|
int i;
|
|
for (i = 7; i >= 0; i--) {
|
|
nr[i] = hex[alpha%16];
|
|
alpha /= 16;
|
|
}
|
|
nr[8] = 0;
|
|
puts_pos(x,y,nr);
|
|
}
|
|
|
|
void put_bin (int x, int y, byte xz)
|
|
{
|
|
int i;
|
|
char arr[9] = {0,0,0,0,0,0,0,0,0};
|
|
for(i=7; i>=0; i--) {
|
|
arr[i] = (xz%2) + '0'; xz/=2;
|
|
}
|
|
puts_pos (x, y, arr);
|
|
}
|
|
|
|
|
|
int printf(const char* str, ...)
|
|
{
|
|
if (!str) return 0;
|
|
|
|
va_list args;
|
|
va_start (args, str);
|
|
size_t i, len = strlen(str);
|
|
for (i = 0; i < len; i++)
|
|
switch (str[i]) {
|
|
case '%':
|
|
switch (str[i+1]) {
|
|
// Character
|
|
case 'c': {char c = va_arg (args, char);
|
|
putc(c); i++; break;}
|
|
// String
|
|
case 's': {int* c = (int*) va_arg (args, char*);
|
|
puts((const char*)c); i++; break;}
|
|
// Integers
|
|
case 'd':
|
|
case 'i': {int c = va_arg(args, int);
|
|
char temp[32];
|
|
itoa(c, temp, 10);
|
|
puts(temp);
|
|
i++; break;}
|
|
// Integers - hex
|
|
case 'X':
|
|
case 'x': {int c = va_arg(args, int);
|
|
char temp[32];
|
|
uitoa(c, temp, 16);
|
|
puts(temp);
|
|
i++; break;}
|
|
|
|
// Integers - unsigned
|
|
case 'u': { int c = va_arg(args, unsigned int);
|
|
char temp[32];
|
|
uitoa(c, temp, 10);
|
|
puts(temp);
|
|
i++; break;
|
|
}
|
|
|
|
default: va_end(args); return 1;
|
|
};
|
|
break;
|
|
default: putc(str[i]); break;
|
|
}
|
|
|
|
va_end(args);
|
|
return i;
|
|
}
|
|
|