Cleanup some symbols
[lsnes.git] / src / core / framebuffer.cpp
blobe0518fc475cfa214434e801f69918773d11cba62
1 #include "core/command.hpp"
2 #include "core/dispatch.hpp"
3 #include "core/emustatus.hpp"
4 #include "core/framebuffer.hpp"
5 #include "core/instance.hpp"
6 #include "core/memorywatch.hpp"
7 #include "core/messages.hpp"
8 #include "core/moviedata.hpp"
9 #include "core/rom.hpp"
10 #include "core/settings.hpp"
11 #include "core/subtitles.hpp"
12 #include "fonts/wrapper.hpp"
13 #include "library/framebuffer.hpp"
14 #include "library/framebuffer-pixfmt-lrgb.hpp"
15 #include "library/minmax.hpp"
16 #include "library/triplebuffer.hpp"
17 #include "lua/lua.hpp"
19 namespace
21 struct render_list_entry
23 uint32_t codepoint;
24 uint32_t x;
25 uint32_t y;
26 uint32_t scale;
29 const struct render_list_entry rl_corrupt[] = {
30 {'S', 88, 56, 7},
31 {'Y', 144, 56, 7},
32 {'S', 200, 56, 7},
33 {'T', 256, 56, 7},
34 {'E', 312, 56, 7},
35 {'M', 368, 56, 7},
36 {'S', 116, 168, 7},
37 {'T', 172, 168, 7},
38 {'A', 224, 168, 7},
39 {'T', 280, 168, 7},
40 {'E', 336, 168, 7},
41 {'C', 60, 280, 7},
42 {'O', 116, 280, 7},
43 {'R', 172, 280, 7},
44 {'R', 228, 280, 7},
45 {'U', 284, 280, 7},
46 {'P', 340, 280, 7},
47 {'T', 396, 280, 7},
48 {0, 0, 0, 0}
51 void draw_special_screen(uint32_t* target, const struct render_list_entry* rlist)
53 while(rlist->scale) {
54 auto g = main_font.get_glyph(rlist->codepoint);
55 for(uint32_t j = 0; j < 16; j++) {
56 for(uint32_t i = 0; i < (g.wide ? 16 : 8); i++) {
57 uint32_t slice = g.data[j / (g.wide ? 2 : 4)];
58 uint32_t bit = 31 - ((j % (g.wide ? 2 : 4)) * (g.wide ? 16 : 8) + i);
59 uint32_t value = (slice >> bit) & 1;
60 if(value) {
61 uint32_t basex = rlist->x + rlist->scale * i;
62 uint32_t basey = rlist->y + rlist->scale * j;
63 for(uint32_t j2 = 0; j2 < rlist->scale; j2++)
64 for(uint32_t i2 = 0; i2 < rlist->scale; i2++)
65 target[(basey + j2) * 512 + (basex + i2)] = 0x7FFFF;
69 rlist++;
73 void draw_corrupt(uint32_t* target)
75 for(unsigned i = 0; i < 512 * 448; i++)
76 target[i] = 0x7FC00;
77 draw_special_screen(target, rl_corrupt);
80 command::fnptr<command::arg_filename> CMD_take_screenshot(lsnes_cmds, "take-screenshot", "Takes a screenshot",
81 "Syntax: take-screenshot <file>\nSaves screenshot to PNG file <file>\n",
82 [](command::arg_filename file) throw(std::bad_alloc, std::runtime_error) {
83 CORE().fbuf->take_screenshot(file);
84 messages << "Saved PNG screenshot" << std::endl;
85 });
87 settingvar::supervariable<settingvar::model_int<0, 8191>> SET_dtb(lsnes_setgrp, "top-border",
88 "UI‣Top padding", 0);
89 settingvar::supervariable<settingvar::model_int<0, 8191>> SET_dbb(lsnes_setgrp, "bottom-border",
90 "UI‣Bottom padding", 0);
91 settingvar::supervariable<settingvar::model_int<0, 8191>> SET_dlb(lsnes_setgrp, "left-border",
92 "UI‣Left padding", 0);
93 settingvar::supervariable<settingvar::model_int<0, 8191>> SET_drb(lsnes_setgrp, "right-border",
94 "UI‣Right padding", 0);
97 framebuffer::raw emu_framebuffer::screen_corrupt;
99 emu_framebuffer::emu_framebuffer(subtitle_commentary& _subtitles, settingvar::group& _settings, memwatch_set& _mwatch,
100 keyboard::keyboard& _keyboard, emulator_dispatch& _dispatch, lua_state& _lua2, loaded_rom& _rom,
101 status_updater& _supdater)
102 : buffering(buffer1, buffer2, buffer3), subtitles(_subtitles), settings(_settings), mwatch(_mwatch),
103 keyboard(_keyboard), edispatch(_dispatch), lua2(_lua2), rom(_rom), supdater(_supdater)
105 last_redraw_no_lua = false;
108 void emu_framebuffer::take_screenshot(const std::string& file) throw(std::bad_alloc, std::runtime_error)
110 render_info& ri = buffering.get_read();
111 ri.fbuf.save_png(file);
112 buffering.put_read();
116 void emu_framebuffer::init_special_screens() throw(std::bad_alloc)
118 std::vector<uint32_t> buf;
119 buf.resize(512*448);
121 framebuffer::info inf;
122 inf.type = &framebuffer::pixfmt_lrgb;
123 inf.mem = reinterpret_cast<char*>(&buf[0]);
124 inf.physwidth = 512;
125 inf.physheight = 448;
126 inf.physstride = 2048;
127 inf.width = 512;
128 inf.height = 448;
129 inf.stride = 2048;
130 inf.offset_x = 0;
131 inf.offset_y = 0;
133 draw_corrupt(&buf[0]);
134 screen_corrupt = framebuffer::raw(inf);
137 void emu_framebuffer::redraw_framebuffer(framebuffer::raw& todraw, bool no_lua, bool spontaneous)
139 uint32_t hscl, vscl;
140 auto g = rom.get_scale_factors(todraw.get_width(), todraw.get_height());
141 hscl = g.first;
142 vscl = g.second;
143 render_info& ri = buffering.get_write();
144 ri.rq.clear();
145 struct lua::render_context lrc;
146 lrc.left_gap = 0;
147 lrc.right_gap = 0;
148 lrc.bottom_gap = 0;
149 lrc.top_gap = 0;
150 lrc.queue = &ri.rq;
151 lrc.width = todraw.get_width() * hscl;
152 lrc.height = todraw.get_height() * vscl;
153 if(!no_lua) {
154 lua2.callback_do_paint(&lrc, spontaneous);
155 subtitles.render(lrc);
157 ri.fbuf = todraw;
158 ri.hscl = hscl;
159 ri.vscl = vscl;
160 ri.lgap = max(lrc.left_gap, (unsigned)SET_dlb(settings));
161 ri.rgap = max(lrc.right_gap, (unsigned)SET_drb(settings));
162 ri.tgap = max(lrc.top_gap, (unsigned)SET_dtb(settings));
163 ri.bgap = max(lrc.bottom_gap, (unsigned)SET_dbb(settings));
164 mwatch.watch(ri.rq);
165 buffering.put_write();
166 edispatch.screen_update();
167 last_redraw_no_lua = no_lua;
168 supdater.update();
171 void emu_framebuffer::redraw_framebuffer()
173 render_info& ri = buffering.get_read();
174 framebuffer::raw copy = ri.fbuf;
175 buffering.put_read();
176 //Redraws are never spontaneous
177 redraw_framebuffer(copy, last_redraw_no_lua, false);
180 void emu_framebuffer::render_framebuffer()
182 render_info& ri = buffering.get_read();
183 main_screen.reallocate(ri.fbuf.get_width() * ri.hscl + ri.lgap + ri.rgap, ri.fbuf.get_height() * ri.vscl +
184 ri.tgap + ri.bgap);
185 main_screen.set_origin(ri.lgap, ri.tgap);
186 main_screen.copy_from(ri.fbuf, ri.hscl, ri.vscl);
187 ri.rq.run(main_screen);
188 //We would want divide by 2, but we'll do it ourselves in order to do mouse.
189 keyboard::key* mouse_x = keyboard.try_lookup_key("mouse_x");
190 keyboard::key* mouse_y = keyboard.try_lookup_key("mouse_y");
191 keyboard::mouse_calibration xcal;
192 keyboard::mouse_calibration ycal;
193 xcal.offset = ri.lgap;
194 ycal.offset = ri.tgap;
195 if(mouse_x && mouse_x->get_type() == keyboard::KBD_KEYTYPE_MOUSE)
196 mouse_x->cast_mouse()->set_calibration(xcal);
197 if(mouse_y && mouse_y->get_type() == keyboard::KBD_KEYTYPE_MOUSE)
198 mouse_y->cast_mouse()->set_calibration(ycal);
199 buffering.put_read();
202 std::pair<uint32_t, uint32_t> emu_framebuffer::get_framebuffer_size()
204 uint32_t v, h;
205 render_info& ri = buffering.get_read();
206 v = ri.fbuf.get_width();
207 h = ri.fbuf.get_height();
208 buffering.put_read();
209 return std::make_pair(h, v);
212 framebuffer::raw emu_framebuffer::get_framebuffer() throw(std::bad_alloc)
214 render_info& ri = buffering.get_read();
215 framebuffer::raw copy = ri.fbuf;
216 buffering.put_read();
217 return copy;
220 void emu_framebuffer::render_kill_request(void* obj)
222 buffer1.rq.kill_request(obj);
223 buffer2.rq.kill_request(obj);
224 buffer3.rq.kill_request(obj);
227 framebuffer::raw& emu_framebuffer::render_get_latest_screen()
229 return buffering.get_read().fbuf;
232 void emu_framebuffer::render_get_latest_screen_end()
234 buffering.put_read();