diff options
Diffstat (limited to 'src/ppu.c')
-rw-r--r-- | src/ppu.c | 82 |
1 files changed, 50 insertions, 32 deletions
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | #include <linux/fb.h> | 5 | #include <linux/fb.h> |
6 | #include <sys/ioctl.h> | 6 | #include <sys/ioctl.h> |
7 | #include <sys/kd.h> | 7 | // #include <sys/kd.h> |
8 | #include <sys/mman.h> | 8 | #include <sys/mman.h> |
9 | 9 | ||
10 | #include "ppu.h" | 10 | #include "ppu.h" |
@@ -24,8 +24,9 @@ | |||
24 | 24 | ||
25 | static size_t screen_width = 0; | 25 | static size_t screen_width = 0; |
26 | static size_t screen_height = 0; | 26 | static size_t screen_height = 0; |
27 | static size_t bpp = 0; | ||
27 | 28 | ||
28 | static u32 *framebuffer = 0; | 29 | static u8 *framebuffer = 0; |
29 | 30 | ||
30 | static u32 palette[16]; | 31 | static u32 palette[16]; |
31 | static u8 *pixels_fg; | 32 | static u8 *pixels_fg; |
@@ -42,6 +43,14 @@ static u8 blending[5][16] = { | |||
42 | {2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2}, | 43 | {2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2}, |
43 | {1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0}}; | 44 | {1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0}}; |
44 | 45 | ||
46 | u16 | ||
47 | rgb565(u32 rgba) { | ||
48 | u16 r = rgba >> 16 & 0xFF; | ||
49 | u16 g = rgba >> 8 & 0xFF; | ||
50 | u16 b = rgba >> 0 & 0xFF; | ||
51 | return (r << 8) | (g << 3) | (b >> 3); | ||
52 | } | ||
53 | |||
45 | void | 54 | void |
46 | ppu_pixel(u8 *layer, u16 x, u16 y, u8 color) { | 55 | ppu_pixel(u8 *layer, u16 x, u16 y, u8 color) { |
47 | if(x < screen_width && y < screen_height) { | 56 | if(x < screen_width && y < screen_height) { |
@@ -101,39 +110,39 @@ set_tty(bool graphics) { | |||
101 | exit(EXIT_FAILURE); | 110 | exit(EXIT_FAILURE); |
102 | } | 111 | } |
103 | 112 | ||
104 | if (graphics) { | 113 | // if (graphics) { |
105 | if (ioctl(tty, KDSETMODE, KD_GRAPHICS)) { | 114 | // if (ioctl(tty, KDSETMODE, KD_GRAPHICS)) { |
106 | fprintf(stderr,"error: setting graphics mode failed\n"); | 115 | // fprintf(stderr,"error: setting graphics mode failed\n"); |
107 | exit(EXIT_FAILURE); | 116 | // exit(EXIT_FAILURE); |
108 | } | 117 | // } |
109 | struct termios t; | 118 | // struct termios t; |
110 | if (tcgetattr(STDIN_FILENO, &t)) { | 119 | // if (tcgetattr(STDIN_FILENO, &t)) { |
111 | fprintf(stderr, "error: couldn't disable terminal echo\n"); | 120 | // fprintf(stderr, "error: couldn't disable terminal echo\n"); |
112 | exit(EXIT_FAILURE); | 121 | // exit(EXIT_FAILURE); |
113 | } | 122 | // } |
114 | prev_t = t; | 123 | // prev_t = t; |
115 | t.c_lflag &= ~((tcflag_t) ECHO); | 124 | // t.c_lflag &= ~((tcflag_t) ECHO); |
116 | if (tcsetattr(STDIN_FILENO, TCSANOW, &t)) { | 125 | // if (tcsetattr(STDIN_FILENO, TCSANOW, &t)) { |
117 | fprintf(stderr, "error: couldn't disable terminal echo\n"); | 126 | // fprintf(stderr, "error: couldn't disable terminal echo\n"); |
118 | exit(EXIT_FAILURE); | 127 | // exit(EXIT_FAILURE); |
119 | } | 128 | // } |
120 | } else { | 129 | // } else { |
121 | if (ioctl(tty, KDSETMODE, KD_TEXT)) { | 130 | // if (ioctl(tty, KDSETMODE, KD_TEXT)) { |
122 | fprintf(stderr,"error: setting text mode failed\n"); | 131 | // fprintf(stderr,"error: setting text mode failed\n"); |
123 | exit(EXIT_FAILURE); | 132 | // exit(EXIT_FAILURE); |
124 | } | 133 | // } |
125 | if (tcsetattr(STDIN_FILENO, TCSANOW, &prev_t)) { | 134 | // if (tcsetattr(STDIN_FILENO, TCSANOW, &prev_t)) { |
126 | fprintf(stderr, "error: couldn't restore terminal attributes\n"); | 135 | // fprintf(stderr, "error: couldn't restore terminal attributes\n"); |
127 | exit(EXIT_FAILURE); | 136 | // exit(EXIT_FAILURE); |
128 | } | 137 | // } |
129 | } | 138 | // } |
130 | close(tty); | 139 | close(tty); |
131 | } | 140 | } |
132 | 141 | ||
133 | int | 142 | int |
134 | ppu_init(void) { | 143 | ppu_init(void) { |
135 | // Open frambuffer and get the size. | 144 | // Open frambuffer and get the size. |
136 | int fb = open("/dev/fb0", O_RDWR); | 145 | int fb = open("/dev/graphics/fb0", O_RDWR); |
137 | if (fb <= 0) { | 146 | if (fb <= 0) { |
138 | fprintf(stderr, "error: couldn't open the framebuffer\n"); | 147 | fprintf(stderr, "error: couldn't open the framebuffer\n"); |
139 | exit(EXIT_FAILURE); | 148 | exit(EXIT_FAILURE); |
@@ -147,7 +156,8 @@ ppu_init(void) { | |||
147 | // Mmap the framebuffer to a buffer object. | 156 | // Mmap the framebuffer to a buffer object. |
148 | screen_width = info.xres; | 157 | screen_width = info.xres; |
149 | screen_height = info.yres; | 158 | screen_height = info.yres; |
150 | size_t len = 4 * screen_width * screen_height; | 159 | bpp = info.bits_per_pixel / 8; |
160 | size_t len = bpp * screen_width * screen_height; | ||
151 | framebuffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0); | 161 | framebuffer = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0); |
152 | if (framebuffer == MAP_FAILED) { | 162 | if (framebuffer == MAP_FAILED) { |
153 | fprintf(stderr, "error: couldn't mmap the framebuffer\n"); | 163 | fprintf(stderr, "error: couldn't mmap the framebuffer\n"); |
@@ -164,7 +174,7 @@ ppu_init(void) { | |||
164 | } | 174 | } |
165 | 175 | ||
166 | // Prepare TTY for graphics mode. | 176 | // Prepare TTY for graphics mode. |
167 | set_tty(true); | 177 | // set_tty(true); |
168 | 178 | ||
169 | // Initialize default palette. | 179 | // Initialize default palette. |
170 | palette[0] = 0x444444; | 180 | palette[0] = 0x444444; |
@@ -177,6 +187,9 @@ ppu_init(void) { | |||
177 | memset(pixels_bg, 0, screen_width * screen_height); | 187 | memset(pixels_bg, 0, screen_width * screen_height); |
178 | memset(dirty_lines, 1, screen_height); | 188 | memset(dirty_lines, 1, screen_height); |
179 | 189 | ||
190 | // Clear framebuffer. | ||
191 | memset(framebuffer, 0xFF, len); | ||
192 | |||
180 | // Make sure we perform an initial screen drawing. | 193 | // Make sure we perform an initial screen drawing. |
181 | reqdraw = 1; | 194 | reqdraw = 1; |
182 | redraw_screen(); | 195 | redraw_screen(); |
@@ -189,11 +202,16 @@ blit_framebuffer(void) { | |||
189 | if (reqdraw == 0) { | 202 | if (reqdraw == 0) { |
190 | return; | 203 | return; |
191 | } | 204 | } |
205 | // TODO: add some parameter to account for zoom? for example we may want to | ||
206 | // have an internal resolution smaller than the screen! | ||
192 | for (size_t j = 0; j < screen_height; j++) { | 207 | for (size_t j = 0; j < screen_height; j++) { |
193 | if (dirty_lines[j] != 0) { | 208 | if (dirty_lines[j] != 0) { |
194 | for (size_t i = 0; i < screen_width; i++) { | 209 | for (size_t i = 0; i < screen_width; i++) { |
195 | size_t idx = i + j * screen_width; | 210 | size_t idx = i + j * screen_width; |
196 | framebuffer[idx] = palette[pixels_fg[idx] << 2 | pixels_bg[idx]]; | 211 | u16 *p = framebuffer; |
212 | p[idx] = rgb565(palette[pixels_fg[idx] << 2 | pixels_bg[idx]]); | ||
213 | // FIXME: can we generalize this to use bpp instead of having | ||
214 | // a version for 32/16 bit color? | ||
197 | } | 215 | } |
198 | } | 216 | } |
199 | dirty_lines[j] = 0; | 217 | dirty_lines[j] = 0; |