about summary refs log tree commit diff stats
path: root/tools/iso/kernel.soso/gfx.c
blob: 15e0ae697b57978c4b76071658d61f502c2fb9b3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include "gfx.h"
#include "vmm.h"
#include "serial.h"
#include "framebuffer.h"
#include "debugprint.h"

static uint32 gWidth = 0;
static uint32 gHeight = 0;
static uint32 gBytesPerPixel = 0;
static uint32 gPitch = 0;
static uint32* gPixels = NULL;

extern char _binary_font_psf_start;
extern char _binary_font_psf_end;

uint16 *gUnicode = NULL;

static int gLineCount = 10;
static int gColumnCount = 10;
static uint16 gCurrentLine = 0;
static uint16 gCurrentColumn = 0;

#define LINE_HEIGHT 16

void Gfx_Initialize(uint32* pixels, uint32 width, uint32 height, uint32 bytesPerPixel, uint32 pitch) {
    char* p_address = (char*)pixels;
    char* v_address = (char*)GFX_MEMORY;

    //Usually physical and virtual are the same here but of course they don't have to

    gPixels = (uint32*)v_address;
    gWidth = width;
    gHeight = height;
    gBytesPerPixel = bytesPerPixel;
    gPitch = pitch;

    gLineCount = gHeight / LINE_HEIGHT;
    gColumnCount = gWidth / 8;


    BOOL success = addPageToPd(gKernelPageDirectory, v_address, p_address, 0);

    if (success) {
        for (int y = 0; y < gHeight; ++y) {
            for (int x = 0; x < gWidth; ++x) {
                gPixels[x + y * gWidth] = 0xFFFFFFFF;
            }
        }
    }
    else {
        Debug_PrintF("Gfx initialization failed!\n");
    }

    initializeFrameBuffer((uint8*)p_address, (uint8*)v_address);
}

#define PSF_FONT_MAGIC 0x864ab572

typedef struct {
    uint32 magic;         /* magic bytes to identify PSF */
    uint32 version;       /* zero */
    uint32 headersize;    /* offset of bitmaps in file, 32 */
    uint32 flags;         /* 0 if there's no unicode table */
    uint32 numglyph;      /* number of glyphs */
    uint32 bytesperglyph; /* size of each glyph */
    uint32 height;        /* height in pixels */
    uint32 width;         /* width in pixels */
} PSF_font;

//From Osdev PC Screen Font (The font used here is free to use)
void Gfx_PutCharAt(
    /* note that this is int, not char as it's a unicode character */
    unsigned short int c,
    /* cursor position on screen, in characters not in pixels */
    int cx, int cy,
    /* foreground and background colors, say 0xFFFFFF and 0x000000 */
    uint32 fg, uint32 bg) {
    /* cast the address to PSF header struct */
    PSF_font *font = (PSF_font*)&_binary_font_psf_start;
    /* we need to know how many bytes encode one row */
    int bytesperline=(font->width+7)/8;
    /* unicode translation */
    if(gUnicode != NULL) {
        c = gUnicode[c];
    }
    /* get the glyph for the character. If there's no
       glyph for a given character, we'll display the first glyph. */
    unsigned char *glyph =
     (unsigned char*)&_binary_font_psf_start +
     font->headersize +
     (c>0&&c<font->numglyph?c:0)*font->bytesperglyph;
    /* calculate the upper left corner on screen where we want to display.
       we only do this once, and adjust the offset later. This is faster. */
    int offs =
        (cy * font->height * gPitch) +
        (cx * (font->width+1) * 4);
    /* finally display pixels according to the bitmap */
    int x,y, line,mask;
    for(y=0;y<font->height;y++){
        /* save the starting position of the line */
        line=offs;
        mask=1<<(font->width-1);
        /* display a row */
        for(x=0;x<font->width;x++) {
            if (c == 0) {
                *((uint32*)((uint8*)gPixels + line)) = bg;
            }
            else {
                *((uint32*)((uint8*)gPixels + line)) = ((int)*glyph) & (mask) ? fg : bg;
            }

            /* adjust to the next pixel */
            mask >>= 1;
            line += 4;
        }
        /* adjust to the next line */
        glyph += bytesperline;
        offs  += gPitch;
    }
}

void Gfx_FlushFromTty(Tty* tty) {
    for (uint32 r = 0; r < tty->lineCount; ++r) {
        for (uint32 c = 0; c < tty->columnCount; ++c) {
            uint8* ttyPos = tty->buffer + (r * tty->columnCount + c) * 2;

            uint8 chr = ttyPos[0];
            uint8 color = ttyPos[1];

            Gfx_PutCharAt(chr, c, r, 0, 0xFFFFFFFF);
        }
    }

    //Screen_MoveCursor(tty->currentLine, tty->currentColumn);
}

uint8* Gfx_GetVideoMemory() {
    return (uint8*)gPixels;
}

uint16 Gfx_GetWidth() {
    return gWidth;
}

uint16 Gfx_GetHeight() {
    return gHeight;
}

uint16 Gfx_GetBytesPerPixel() {
    return gBytesPerPixel;
}

void Gfx_Fill(uint32 color) {
    for (uint32 y = 0; y < gHeight; ++y) {
        for (uint32 x = 0; x < gWidth; ++x) {
            gPixels[x + y * gWidth] = color;
        }
    }
}