hos/kernel/video/video.cpp

266 lines
5.3 KiB
C++

// video.c
// 08/13/03 Josh Holtrop
// Modified: 03/08/04
#include "hos_defines.h"
#include "video.h"
#include "video/stdfont.h"
#include "mm/vmm.h"
ModeInfoBlock video_mode;
dword videoMode = 0; //what video mode # we are in, 0 for console mode
word *vid_ptr16 = (word *)0xF0000000;
byte *vid_ptr24 = (byte *)0xF0000000;
dword *vid_ptr32 = (dword *)0xF0000000;
void (*video_psetp)(int, dword) = video_psetpnull; //function pointer to set a pixel
//Initialized the video mode information block video_mode and allocated double-buffer memory for graphics display
void video_init()
{
videoMode = *(word *)BOOT_VIDEO_MODE;
if (!videoMode) //we are in console mode
return;
video_mode = *(ModeInfoBlock *) BOOT_VIDEO_MODE_INFO_BLOCK;
switch(video_mode.BitsPerPixel)
{
case 16:
video_psetp = &video_psetp16;
break;
case 24:
video_psetp = &video_psetp24;
break;
case 32:
video_psetp = &video_psetp32;
}
unsigned int vidPages = video_mode.XResolution * video_mode.YResolution * (video_mode.BitsPerPixel >> 3);
if (vidPages % 4096)
vidPages = (vidPages >> 12) + 1;
else
vidPages = (vidPages >> 12);
vmm_mapn(0xF0000000, video_mode.PhysBasePtr, vidPages);
}
//Renders a character using stdfont[] as a bitmask
void video_renderChar(int x, int y, int character, int font, dword color, int drawBack, dword backColor)
{
int charWidth = stdfont_getFontWidth(font);
if (!charWidth)
return;
int charHeight = stdfont_getFontHeight(font);
int charpos = (character & 0xFF) * charHeight;
byte *charBMP = (byte *)stdfont_getBitmap(font);
int row;
int col;
for (row = 0; row < charHeight; row++)
{
for (col = 0; col < charWidth; col++)
{
if ((charBMP[charpos + row] << col) & 0x80)
video_pset(x + col, y + row, color);
else if (drawBack)
video_pset(x + col, y + row, backColor);
}
}
}
//Draws a horizontal line
void video_horiz(int y, int x1, int x2, dword color)
{
if (x1 > x2)
{
int tmp = x2;
x2 = x1;
x1 = tmp; //x2 >= x1 now
}
if (x2 < 0)
return;
if (x1 >= video_mode.XResolution)
return;
if (x1 < 0)
x1 = 0;
if (x2 >= video_mode.XResolution)
x2 = video_mode.XResolution - 1;
int pixel = y * video_mode.XResolution + x1;
for (; x1 <= x2; x1++)
{
video_psetp(pixel++, color);
}
}
//Draws a single pixel
void video_pset(int x, int y, dword color)
{
if ((x < 0) || (x >= video_mode.XResolution) || (y < 0) || (y >= video_mode.YResolution))
return;
video_psetp(y * video_mode.XResolution + x, color);
}
//Draws a pixel at the specified pixel position
//This function is needed because external modules do not have access to the function pointer video_psetp
void video_pseti(int pixel, dword color)
{
video_psetp(pixel, color);
}
//Draws a vertical line
void video_vert(int x, int y1, int y2, dword color)
{
if (y1 > y2)
{
int tmp = y2;
y2 = y1;
y1 = tmp; //y2 >= y1 now
}
if (y2 < 0)
return;
if (y1 >= video_mode.YResolution)
return;
if (y1 < 0)
y1 = 0;
if (y2 >= video_mode.YResolution)
y2 = video_mode.YResolution - 1;
int pixel = y1 * video_mode.XResolution + x;
for (; y1 <= y2; y1++)
{
video_psetp(pixel, color);
pixel += video_mode.XResolution;
}
}
//Draws a rectangle
void video_rect(int x1, int y1, int x2, int y2, dword color)
{
video_horiz(y1, x1, x2, color);
video_horiz(y2, x1, x2, color);
video_vert(x1, y1, y2, color);
video_vert(x2, y1, y2, color);
}
//Draws a filled rectangle
void video_rectf(int x1, int y1, int x2, int y2, dword color)
{
if (y2 < y1)
{
int tmp = y2;
y2 = y1;
y1 = tmp;
}
for (; y1 <= y2; y1++)
video_horiz(y1, x1, x2, color);
}
//Draws a pixel at the specified pixel position
void video_psetp16(int pixel, dword color)
{
vid_ptr16[pixel] = ((color&0xFF)>>3) | ((((color>>8)&0xFF)>>2)<<5) | ((((color>>16)&0xFF)>>3)<<11);
}
//Draws a pixel at the specified pixel position
void video_psetp24(int pixel, dword color)
{
vid_ptr24[pixel*3] = color & 0xFF;
vid_ptr24[pixel*3+1] = (color>>8) & 0xFF;
vid_ptr24[pixel*3+2] = (color>>16) & 0xFF;
}
//Draws a pixel at the specified pixel position
void video_psetp32(int pixel, dword color)
{
vid_ptr32[pixel] = color;
}
//Dummy function to not draw anything if there is no graphical mode enabled
void video_psetpnull(int pixel, dword color) {}
int video_getWidth()
{
return video_mode.XResolution;
}
int video_getHeight()
{
return video_mode.YResolution;
}
byte video_getBitsPerPixel()
{
return video_mode.BitsPerPixel;
}
dword video_getPhysBasePtr()
{
return video_mode.PhysBasePtr;
}
dword video_Mode()
{
return videoMode;
}
void video_line(int x0, int y0, int x1, int y1, dword color)
{
int dy = y1 - y0;
int dx = x1 - x0;
int stepx, stepy;
if (dy < 0)
{
dy = -dy;
stepy = -1;
}
else
{
stepy = 1;
}
if (dx < 0)
{
dx = -dx;
stepx = -1;
}
else
{
stepx = 1;
}
dy <<= 1; // dy is now 2*dy
dx <<= 1; // dx is now 2*dx
video_pset(x0, y0, color);
if (dx > dy)
{
int fraction = dy - (dx >> 1); // same as 2*dy - dx
while (x0 != x1)
{
if (fraction >= 0)
{
y0 += stepy;
fraction -= dx; // same as fraction -= 2*dx
}
x0 += stepx;
fraction += dy; // same as fraction -= 2*dy
video_pset(x0, y0, color);
}
}
else
{
int fraction = dx - (dy >> 1);
while (y0 != y1)
{
if (fraction >= 0)
{
x0 += stepx;
fraction -= dy;
}
y0 += stepy;
fraction += dx;
video_pset(x0, y0, color);
}
}
}