summaryrefslogtreecommitdiff
path: root/src/screen.c
blob: 6f682ae9b65248575e6316a75b45cb14e5634012 (plain)
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
#include <lib.h>
#include <screen.h>
#include <bochs.h>
#include <stddef.h>
#include <stdint.h>

#define SCREEN_WIDTH	       1024
#define SCREEN_HEIGHT          768
#define SCREEN_BIT_DEPTH       32

struct rgb {
	uint8_t r;
	uint8_t g;
	uint8_t b;
};

struct hsv {
	uint16_t h;
	uint16_t s;
	uint16_t v;
};

static uint32_t *buffer = NULL;
static uint32_t width, height;
static uint8_t bit_depth;

static uint16_t angle;

static void set_pixel(struct rgb color, uint16_t x, uint16_t y) {
	uint32_t offset = y * width + x;
	buffer[offset] = (color.b << 0) | (color.g << 8) | (color.r << 16);
}

static float fmod(float f, float m) {
	return f - (int)(f / m) * m;
}

static float fabs(float f) {
	return f > 0 ? f : -f;
}

static struct rgb htor(struct hsv hsv) {
	struct rgb rgb;
	float s = hsv.s / 100.0;
	float v = hsv.v / 100.0;
	float c = s * v;
	float x = c * (1-fabs(fmod(hsv.h/60.0, 2) - 1));
	float m = v - c;
	float r,g,b;

	if (hsv.h < 60) {
		r = c; g = x; b = 0;
	} else if (hsv.h >= 60 && hsv.h < 120) {
		r = x; g = c; b = 0;
	} else if (hsv.h >= 120 && hsv.h < 180) {
		r = 0; g = c; b = x;
	} else if (hsv.h >= 180 && hsv.h < 240) {
		r = 0; g = x; b = c;
	} else if (hsv.h >= 240 && hsv.h < 300) {
		r = x; g = 0; b = c;
	} else {
		r = c; g = 0; b = x;
	}

	rgb.r = (r + m) * 255;
	rgb.g = (g + m) * 255;
	rgb.b = (b + m) * 255;

	return rgb;
}

static struct rgb get_color(uint16_t a, uint16_t x, uint16_t y) {
	struct hsv hsv = {
		.h = a,
		.s = x * 100.0 / width,
		.v = y * 100.0 / height,
	};
	return htor(hsv);
}

void screen_init(void) {
	angle = 0;
	width = SCREEN_WIDTH;
	height = SCREEN_HEIGHT;
	bit_depth = SCREEN_BIT_DEPTH;
	buffer = bochs_init(width, height, bit_depth);
}

void screen_redraw(void) {
	for (uint16_t y = 0; y < height; y++) {
		for (uint16_t x = 0; x < width; x++) {
			struct rgb color = get_color(angle, x, height - y);
			set_pixel(color, x, y);
		}
	}
	angle++;
	angle %= 360;
}