Do color upconversion when copying lcscreen -> screen
[lsnes.git] / generic / framebuffer.cpp
blob6d99473f5fa43bd8dee9b31458149b88c8aac760
1 #include "framebuffer.hpp"
2 #include "lua.hpp"
3 #include "command.hpp"
4 #include "window.hpp"
5 #include "misc.hpp"
6 #include "render.hpp"
8 lcscreen framebuffer;
9 lcscreen screen_nosignal;
10 lcscreen screen_corrupt;
11 extern uint32_t fontdata[];
13 namespace
15 struct render_list_entry
17 uint32_t codepoint;
18 uint32_t x;
19 uint32_t y;
20 uint32_t scale;
23 struct render_list_entry rl_nosignal[] = {
24 {'N', 4, 168, 7},
25 {'O', 60, 168, 7},
26 {'S', 172, 168, 7},
27 {'I', 228, 168, 7},
28 {'G', 284, 168, 7},
29 {'N', 340, 168, 7},
30 {'A', 396, 168, 7},
31 {'L', 452, 168, 7},
32 {0, 0, 0, 0}
35 struct render_list_entry rl_corrupt[] = {
36 {'S', 88, 56, 7},
37 {'Y', 144, 56, 7},
38 {'S', 200, 56, 7},
39 {'T', 256, 56, 7},
40 {'E', 312, 56, 7},
41 {'M', 368, 56, 7},
42 {'S', 116, 168, 7},
43 {'T', 172, 168, 7},
44 {'A', 224, 168, 7},
45 {'T', 280, 168, 7},
46 {'E', 336, 168, 7},
47 {'C', 60, 280, 7},
48 {'O', 116, 280, 7},
49 {'R', 172, 280, 7},
50 {'R', 228, 280, 7},
51 {'U', 284, 280, 7},
52 {'P', 340, 280, 7},
53 {'T', 396, 280, 7},
54 {0, 0, 0, 0}
57 void draw_special_screen(uint32_t* target, struct render_list_entry* rlist)
59 while(rlist->scale) {
60 int32_t x;
61 int32_t y;
62 auto g = find_glyph(rlist->codepoint, 0, 0, 0, x, y);
63 for(uint32_t j = 0; j < 16; j++) {
64 for(uint32_t i = 0; i < 8; i++) {
65 uint32_t slice = g.second + j / 4;
66 uint32_t bit = 31 - ((j % 4) * 8 + i);
67 uint32_t value = (fontdata[slice] >> bit) & 1;
68 if(value) {
69 uint32_t basex = rlist->x + rlist->scale * i;
70 uint32_t basey = rlist->y + rlist->scale * j;
71 for(uint32_t j2 = 0; j2 < rlist->scale; j2++)
72 for(uint32_t i2 = 0; i2 < rlist->scale; i2++)
73 target[(basey + j2) * 512 + (basex + i2)] = 0x7FFFF;
77 rlist++;
81 void draw_nosignal(uint32_t* target)
83 for(unsigned i = 0; i < 512 * 448; i++)
84 target[i] = 0x7FC00;
85 draw_special_screen(target, rl_nosignal);
88 void draw_corrupt(uint32_t* target)
90 for(unsigned i = 0; i < 512 * 448; i++)
91 target[i] = 0x7FC00;
92 draw_special_screen(target, rl_corrupt);
95 function_ptr_command<arg_filename> take_screenshot("take-screenshot", "Takes a screenshot",
96 "Syntax: take-screenshot <file>\nSaves screenshot to PNG file <file>\n",
97 [](arg_filename file) throw(std::bad_alloc, std::runtime_error) {
98 framebuffer.save_png(file);
99 messages << "Saved PNG screenshot" << std::endl;
103 screen main_screen;
106 void init_special_screens() throw(std::bad_alloc)
108 uint32_t buf[512*448];
109 draw_nosignal(buf);
110 screen_nosignal = lcscreen(buf, 512, 448);
111 draw_corrupt(buf);
112 screen_corrupt = lcscreen(buf, 512, 448);
115 void redraw_framebuffer()
117 uint32_t hscl, vscl;
118 auto g = get_scale_factors(framebuffer.width, framebuffer.height);
119 hscl = g.first;
120 vscl = g.second;
121 render_queue rq;
122 struct lua_render_context lrc;
123 lrc.left_gap = 0;
124 lrc.right_gap = 0;
125 lrc.bottom_gap = 0;
126 lrc.top_gap = 0;
127 lrc.queue = &rq;
128 lrc.width = framebuffer.width * hscl;
129 lrc.height = framebuffer.height * vscl;
130 lua_callback_do_paint(&lrc);
131 main_screen.reallocate(framebuffer.width * hscl + lrc.left_gap + lrc.right_gap, framebuffer.height * vscl +
132 lrc.top_gap + lrc.bottom_gap, lrc.left_gap, lrc.top_gap);
133 main_screen.copy_from(framebuffer, hscl, vscl);
134 //We would want divide by 2, but we'll do it ourselves in order to do mouse.
135 window::set_window_compensation(lrc.left_gap, lrc.top_gap, 1, 1);
136 rq.run(main_screen);
137 window::notify_screen_update();
140 std::pair<uint32_t, uint32_t> get_scale_factors(uint32_t width, uint32_t height)
142 uint32_t v = 1;
143 uint32_t h = 1;
144 if(width < 512)
145 h = 2;
146 if(height < 400)
147 v = 2;
148 return std::make_pair(h, v);