Commit | Line | Data |
---|---|---|
cff531af | 1 | /*\r |
2 | * PicoDrive\r | |
3 | * (C) notaz, 2010,2011\r | |
4 | *\r | |
5 | * This work is licensed under the terms of MAME license.\r | |
6 | * See COPYING file in the top-level directory.\r | |
7 | */\r | |
c7eb229a | 8 | \r |
9 | #include <stdio.h>\r | |
10 | #include <unistd.h>\r | |
c7eb229a | 11 | #include <sys/types.h>\r |
12 | #include <sys/stat.h>\r | |
13 | #include <fcntl.h>\r | |
14 | #include <sys/ioctl.h>\r | |
15 | #include <unistd.h>\r | |
16 | #include <linux/fb.h>\r | |
17 | #include <linux/omapfb.h>\r | |
d4d62665 | 18 | #include <linux/input.h>\r |
c7eb229a | 19 | \r |
20 | #include "../common/emu.h"\r | |
c7eb229a | 21 | #include "../common/arm_utils.h"\r |
d4d62665 | 22 | #include "../common/input_pico.h"\r |
bac44b18 | 23 | #include "../common/keyboard.h"\r |
d4d62665 | 24 | #include "../common/version.h"\r |
25 | #include "../libpicofe/input.h"\r | |
26 | #include "../libpicofe/menu.h"\r | |
27 | #include "../libpicofe/plat.h"\r | |
28 | #include "../libpicofe/linux/in_evdev.h"\r | |
29 | #include "../libpicofe/linux/sndout_oss.h"\r | |
30 | #include "../libpicofe/linux/fbdev.h"\r | |
31 | #include "../libpicofe/linux/xenv.h"\r | |
c7eb229a | 32 | #include "plat.h"\r |
33 | #include "asm_utils.h"\r | |
c7eb229a | 34 | \r |
35 | #include <pico/pico_int.h>\r | |
36 | \r | |
55d7dcb2 | 37 | #define LAYER_MEM_SIZE (320*240*2 * 4)\r |
38 | \r | |
c7eb229a | 39 | static struct vout_fbdev *main_fb, *layer_fb;\r |
21ebcfd3 | 40 | // g_layer_* - in use, g_layer_c* - configured custom\r |
8a407398 | 41 | int g_layer_cx = 80, g_layer_cy, g_layer_cw = 640, g_layer_ch = 480;\r |
ca980e1b | 42 | int saved_start_line = 0, saved_line_count = 240;\r |
43 | int saved_start_col = 0, saved_col_count = 320;\r | |
c7eb229a | 44 | static int g_layer_x, g_layer_y;\r |
45 | static int g_layer_w = 320, g_layer_h = 240;\r | |
8a407398 | 46 | static int g_osd_start_x, g_osd_fps_x, g_osd_y, doing_bg_frame;\r |
c7eb229a | 47 | \r |
d4d62665 | 48 | static unsigned char __attribute__((aligned(4))) fb_copy[320 * 240 * 2];\r |
d40231e2 | 49 | static void *temp_frame;\r |
c7eb229a | 50 | const char *renderer_names[] = { NULL };\r |
51 | const char *renderer_names32x[] = { NULL };\r | |
c7eb229a | 52 | \r |
d4d62665 | 53 | static struct in_default_bind in_evdev_defbinds[] =\r |
54 | {\r | |
55 | { KEY_UP, IN_BINDTYPE_PLAYER12, GBTN_UP },\r | |
56 | { KEY_DOWN, IN_BINDTYPE_PLAYER12, GBTN_DOWN },\r | |
57 | { KEY_LEFT, IN_BINDTYPE_PLAYER12, GBTN_LEFT },\r | |
58 | { KEY_RIGHT, IN_BINDTYPE_PLAYER12, GBTN_RIGHT },\r | |
59 | { KEY_A, IN_BINDTYPE_PLAYER12, GBTN_A },\r | |
60 | { KEY_S, IN_BINDTYPE_PLAYER12, GBTN_B },\r | |
61 | { KEY_D, IN_BINDTYPE_PLAYER12, GBTN_C },\r | |
62 | { KEY_ENTER, IN_BINDTYPE_PLAYER12, GBTN_START },\r | |
9db6a544 | 63 | { KEY_R, IN_BINDTYPE_EMU, PEVB_RESET },\r |
b011c2af | 64 | { KEY_F, IN_BINDTYPE_EMU, PEVB_FF },\r |
c7074ddb | 65 | { KEY_BACKSPACE,IN_BINDTYPE_EMU, PEVB_FF },\r |
66 | { KEY_BACKSLASH,IN_BINDTYPE_EMU, PEVB_MENU },\r | |
21ebcfd3 | 67 | { KEY_SPACE, IN_BINDTYPE_EMU, PEVB_MENU },\r |
c7074ddb | 68 | { KEY_LEFTCTRL, IN_BINDTYPE_EMU, PEVB_MENU },\r |
d4d62665 | 69 | { KEY_HOME, IN_BINDTYPE_PLAYER12, GBTN_A },\r |
70 | { KEY_PAGEDOWN, IN_BINDTYPE_PLAYER12, GBTN_B },\r | |
71 | { KEY_END, IN_BINDTYPE_PLAYER12, GBTN_C },\r | |
72 | { KEY_LEFTALT, IN_BINDTYPE_PLAYER12, GBTN_START },\r | |
c7074ddb | 73 | { KEY_1, IN_BINDTYPE_EMU, PEVB_STATE_SAVE },\r |
74 | { KEY_2, IN_BINDTYPE_EMU, PEVB_STATE_LOAD },\r | |
75 | { KEY_3, IN_BINDTYPE_EMU, PEVB_SSLOT_PREV },\r | |
76 | { KEY_4, IN_BINDTYPE_EMU, PEVB_SSLOT_NEXT },\r | |
77 | { KEY_5, IN_BINDTYPE_EMU, PEVB_PICO_PPREV },\r | |
78 | { KEY_6, IN_BINDTYPE_EMU, PEVB_PICO_PNEXT },\r | |
15cc45c0 | 79 | { KEY_7, IN_BINDTYPE_EMU, PEVB_PICO_STORY },\r |
80 | { KEY_8, IN_BINDTYPE_EMU, PEVB_PICO_PAD },\r | |
21ebcfd3 | 81 | { 0, 0, 0 }\r |
82 | };\r | |
83 | \r | |
4e3551a5 PC |
84 | static const struct menu_keymap key_pbtn_map[] =\r |
85 | {\r | |
86 | { KEY_UP, PBTN_UP },\r | |
87 | { KEY_DOWN, PBTN_DOWN },\r | |
88 | { KEY_LEFT, PBTN_LEFT },\r | |
89 | { KEY_RIGHT, PBTN_RIGHT },\r | |
90 | /* Pandora */\r | |
91 | { KEY_END, PBTN_MOK },\r | |
92 | { KEY_PAGEDOWN, PBTN_MBACK },\r | |
93 | { KEY_HOME, PBTN_MA2 },\r | |
94 | { KEY_PAGEUP, PBTN_MA3 },\r | |
95 | { KEY_LEFTCTRL, PBTN_MENU },\r | |
96 | { KEY_RIGHTSHIFT, PBTN_L },\r | |
97 | { KEY_RIGHTCTRL, PBTN_R },\r | |
98 | /* "normal" keyboards */\r | |
99 | { KEY_ENTER, PBTN_MOK },\r | |
100 | { KEY_ESC, PBTN_MBACK },\r | |
101 | { KEY_SEMICOLON, PBTN_MA2 },\r | |
102 | { KEY_APOSTROPHE, PBTN_MA3 },\r | |
103 | { KEY_BACKSLASH, PBTN_MENU },\r | |
104 | { KEY_LEFTBRACE, PBTN_L },\r | |
105 | { KEY_RIGHTBRACE, PBTN_R },\r | |
106 | };\r | |
107 | \r | |
108 | static const struct in_pdata pandora_evdev_pdata = {\r | |
109 | .defbinds = in_evdev_defbinds,\r | |
110 | .key_map = key_pbtn_map,\r | |
111 | .kmap_size = sizeof(key_pbtn_map) / sizeof(key_pbtn_map[0]),\r | |
112 | };\r | |
113 | \r | |
c7eb229a | 114 | void pemu_prep_defconfig(void)\r |
115 | {\r | |
116 | defaultConfig.EmuOpt |= EOPT_VSYNC|EOPT_16BPP;\r | |
92dfd9af | 117 | defaultConfig.s_PicoOpt |= POPT_EN_MCD_GFX;\r |
c7eb229a | 118 | defaultConfig.scaling = SCALE_2x2_3x2;\r |
119 | }\r | |
120 | \r | |
121 | void pemu_validate_config(void)\r | |
122 | {\r | |
d4d62665 | 123 | currentConfig.CPUclock = plat_target_cpu_clock_get();\r |
c7eb229a | 124 | }\r |
125 | \r | |
c7eb229a | 126 | static void draw_cd_leds(void)\r |
127 | {\r | |
128 | int old_reg;\r | |
129 | old_reg = Pico_mcd->s68k_regs[0];\r | |
130 | \r | |
dca20eff | 131 | // 16-bit modes\r |
132 | unsigned int *p = (unsigned int *)((short *)g_screen_ptr + g_screen_width*2+4);\r | |
133 | unsigned int col_g = (old_reg & 2) ? 0x06000600 : 0;\r | |
134 | unsigned int col_r = (old_reg & 1) ? 0xc000c000 : 0;\r | |
135 | *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += g_screen_width/2 - 12/2;\r | |
136 | *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r; p += g_screen_width/2 - 12/2;\r | |
137 | *p++ = col_g; *p++ = col_g; p+=2; *p++ = col_r; *p++ = col_r;\r | |
138 | }\r | |
139 | \r | |
140 | static void draw_pico_ptr(void)\r | |
141 | {\r | |
c87e36d7 | 142 | int up = (PicoPicohw.pen_pos[0]|PicoPicohw.pen_pos[1]) & 0x8000;\r |
143 | int o = (up ? 0x0000 : 0xffff), _ = (up ? 0xffff : 0x0000);\r | |
dca20eff | 144 | int x = pico_pen_x, y = pico_pen_y, pitch = g_screen_ppitch;\r |
145 | unsigned short *p = (unsigned short *)g_screen_ptr;\r | |
15cc45c0 | 146 | // storyware pages are actually squished, 2:1\r |
147 | int h = (pico_inp_mode == 1 ? 160 : saved_line_count);\r | |
148 | if (h < 224) y++;\r | |
dca20eff | 149 | \r |
15cc45c0 | 150 | x = (x * saved_col_count * ((1ULL<<32) / 320 + 1)) >> 32;\r |
151 | y = (y * h * ((1ULL<<32) / 224 + 1)) >> 32;\r | |
dca20eff | 152 | p += (saved_start_col+x) + (saved_start_line+y) * pitch;\r |
153 | \r | |
15cc45c0 | 154 | p[-pitch-1] ^= o; p[-pitch] ^= _; p[-pitch+1] ^= _; p[-pitch+2] ^= o;\r |
155 | p[-1] ^= _; p[0] ^= o; p[1] ^= o; p[2] ^= _;\r | |
156 | p[pitch-1] ^= _; p[pitch] ^= o; p[pitch+1] ^= o; p[pitch+2] ^= _;\r | |
157 | p[2*pitch-1]^= o; p[2*pitch]^= _; p[2*pitch+1]^= _; p[2*pitch+2]^= o;\r | |
c7eb229a | 158 | }\r |
159 | \r | |
c7eb229a | 160 | void pemu_finalize_frame(const char *fps, const char *notice)\r |
161 | {\r | |
15cc45c0 | 162 | if (PicoIn.AHW & PAHW_PICO) {\r |
163 | int h = saved_line_count, w = saved_col_count;\r | |
164 | u16 *pd = g_screen_ptr + saved_start_line*g_screen_ppitch\r | |
165 | + saved_start_col;\r | |
166 | \r | |
167 | if (pico_inp_mode)\r | |
168 | emu_pico_overlay(pd, w, h, g_screen_ppitch);\r | |
169 | if (pico_inp_mode /*== 2 || overlay*/)\r | |
170 | draw_pico_ptr();\r | |
171 | }\r | |
bf61bea0 | 172 | if (notice && notice[0])\r |
8a407398 | 173 | emu_osd_text16(2 + g_osd_start_x, g_osd_y, notice);\r |
735a987b | 174 | if (fps && fps[0] && (currentConfig.EmuOpt & EOPT_SHOW_FPS)) {\r |
175 | const char *p;\r | |
176 | // avoid wrapping when fps is very high\r | |
177 | if (fps[5] != ' ' && (p = strchr(fps, '/')))\r | |
178 | fps = p;\r | |
179 | emu_osd_text16(g_osd_fps_x, g_osd_y, fps);\r | |
180 | }\r | |
93f9619e | 181 | if ((PicoIn.AHW & PAHW_MCD) && (currentConfig.EmuOpt & EOPT_EN_CD_LEDS))\r |
c7eb229a | 182 | draw_cd_leds();\r |
bac44b18 | 183 | // draw virtual keyboard on display\r |
4814d19e | 184 | if (kbd_mode && currentConfig.keyboard == 1 && vkbd)\r |
bac44b18 | 185 | vkbd_draw(vkbd);\r |
c7eb229a | 186 | }\r |
187 | \r | |
188 | void plat_video_flip(void)\r | |
189 | {\r | |
190 | g_screen_ptr = vout_fbdev_flip(layer_fb);\r | |
41946d70 | 191 | PicoDrawSetOutBuf(g_screen_ptr, g_screen_width * 2);\r |
10ef62e3 | 192 | \r |
193 | // XXX: drain OS event queue here, maybe we'll actually use it someday..\r | |
d4d62665 | 194 | xenv_update(NULL, NULL, NULL, NULL);\r |
c7eb229a | 195 | }\r |
196 | \r | |
bac44b18 | 197 | void plat_video_clear_buffers(void)\r |
198 | {\r | |
199 | vout_fbdev_clear(layer_fb);\r | |
200 | }\r | |
201 | \r | |
735a987b | 202 | // pnd doesn't use multiple renderers, but we have to handle this since it's\r |
203 | // called on 32x enable and PicoDrawSetOutFormat() sets up the 32x layers\r | |
c7eb229a | 204 | void plat_video_toggle_renderer(int change, int is_menu)\r |
205 | {\r | |
735a987b | 206 | if (!is_menu)\r |
207 | PicoDrawSetOutFormat(PDF_RGB555, 0);\r | |
c7eb229a | 208 | }\r |
209 | \r | |
7f4bfa96 | 210 | void plat_video_menu_update(void)\r |
211 | {\r | |
212 | }\r | |
213 | \r | |
c7eb229a | 214 | void plat_video_menu_enter(int is_rom_loaded)\r |
215 | {\r | |
216 | }\r | |
217 | \r | |
218 | void plat_video_menu_begin(void)\r | |
219 | {\r | |
c7eb229a | 220 | }\r |
221 | \r | |
222 | void plat_video_menu_end(void)\r | |
223 | {\r | |
224 | g_menuscreen_ptr = vout_fbdev_flip(main_fb);\r | |
225 | }\r | |
226 | \r | |
d4d62665 | 227 | void plat_video_menu_leave(void)\r |
228 | {\r | |
229 | }\r | |
230 | \r | |
c7eb229a | 231 | void plat_video_wait_vsync(void)\r |
232 | {\r | |
233 | vout_fbdev_wait_vsync(main_fb);\r | |
234 | }\r | |
235 | \r | |
236 | void plat_status_msg_clear(void)\r | |
237 | {\r | |
7c18e34a | 238 | vout_fbdev_clear_lines(layer_fb, g_osd_y, 8);\r |
c7eb229a | 239 | }\r |
240 | \r | |
241 | void plat_status_msg_busy_next(const char *msg)\r | |
242 | {\r | |
243 | plat_status_msg_clear();\r | |
244 | pemu_finalize_frame("", msg);\r | |
245 | plat_video_flip();\r | |
246 | emu_status_msg("");\r | |
247 | reset_timing = 1;\r | |
248 | }\r | |
249 | \r | |
250 | void plat_status_msg_busy_first(const char *msg)\r | |
251 | {\r | |
252 | plat_status_msg_busy_next(msg);\r | |
253 | }\r | |
254 | \r | |
95b08943 | 255 | void plat_status_msg_busy_done(void)\r |
256 | {\r | |
257 | }\r | |
258 | \r | |
c7eb229a | 259 | void plat_update_volume(int has_changed, int is_up)\r |
260 | {\r | |
45285368 | 261 | }\r |
c7eb229a | 262 | \r |
45285368 | 263 | void pemu_forced_frame(int no_scale, int do_emu)\r |
264 | {\r | |
d40231e2 | 265 | doing_bg_frame = 1;\r |
832faed3 | 266 | // making a copy because enabling the layer clears it's mem\r |
267 | emu_cmn_forced_frame(no_scale, do_emu, fb_copy);\r | |
d40231e2 | 268 | doing_bg_frame = 0;\r |
45285368 | 269 | \r |
d4d62665 | 270 | g_menubg_src_ptr = fb_copy;\r |
c7eb229a | 271 | }\r |
272 | \r | |
273 | void pemu_sound_start(void)\r | |
274 | {\r | |
d4d62665 | 275 | emu_sound_start();\r |
c7eb229a | 276 | }\r |
277 | \r | |
278 | void plat_debug_cat(char *str)\r | |
279 | {\r | |
280 | }\r | |
281 | \r | |
282 | static int pnd_setup_layer_(int fd, int enabled, int x, int y, int w, int h)\r | |
283 | {\r | |
284 | struct omapfb_plane_info pi;\r | |
285 | struct omapfb_mem_info mi;\r | |
55d7dcb2 | 286 | int is_enabled;\r |
287 | int retval = 0;\r | |
c7eb229a | 288 | int ret;\r |
289 | \r | |
290 | ret = ioctl(fd, OMAPFB_QUERY_PLANE, &pi);\r | |
291 | if (ret != 0) {\r | |
292 | perror("QUERY_PLANE");\r | |
293 | return -1;\r | |
294 | }\r | |
295 | \r | |
296 | ret = ioctl(fd, OMAPFB_QUERY_MEM, &mi);\r | |
297 | if (ret != 0) {\r | |
298 | perror("QUERY_MEM");\r | |
299 | return -1;\r | |
300 | }\r | |
301 | \r | |
302 | /* must disable when changing stuff */\r | |
55d7dcb2 | 303 | is_enabled = pi.enabled;\r |
304 | if (is_enabled) {\r | |
c7eb229a | 305 | pi.enabled = 0;\r |
306 | ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi);\r | |
307 | if (ret != 0)\r | |
308 | perror("SETUP_PLANE");\r | |
55d7dcb2 | 309 | else\r |
310 | is_enabled = 0;\r | |
c7eb229a | 311 | }\r |
312 | \r | |
55d7dcb2 | 313 | if (mi.size < LAYER_MEM_SIZE) {\r |
314 | unsigned int size_old = mi.size;\r | |
315 | \r | |
316 | mi.size = LAYER_MEM_SIZE;\r | |
317 | ret = ioctl(fd, OMAPFB_SETUP_MEM, &mi);\r | |
318 | if (ret != 0) {\r | |
319 | perror("SETUP_MEM");\r | |
320 | fprintf(stderr, "(requested %u, had %u)\n",\r | |
321 | mi.size, size_old);\r | |
322 | return -1;\r | |
323 | }\r | |
c7eb229a | 324 | }\r |
325 | \r | |
326 | pi.pos_x = x;\r | |
327 | pi.pos_y = y;\r | |
328 | pi.out_width = w;\r | |
329 | pi.out_height = h;\r | |
330 | pi.enabled = enabled;\r | |
331 | \r | |
332 | ret = ioctl(fd, OMAPFB_SETUP_PLANE, &pi);\r | |
55d7dcb2 | 333 | if (ret == 0) {\r |
334 | is_enabled = pi.enabled;\r | |
335 | }\r | |
336 | else {\r | |
c7eb229a | 337 | perror("SETUP_PLANE");\r |
55d7dcb2 | 338 | retval = -1;\r |
c7eb229a | 339 | }\r |
340 | \r | |
55d7dcb2 | 341 | plat_target_switch_layer(1, is_enabled);\r |
342 | \r | |
343 | return retval;\r | |
c7eb229a | 344 | }\r |
345 | \r | |
346 | int pnd_setup_layer(int enabled, int x, int y, int w, int h)\r | |
347 | {\r | |
ca980e1b | 348 | // it's not allowed for the layer to be partially offscreen,\r |
349 | // instead it is faked by emu_video_mode_change()\r | |
350 | if (x < 0) { w += x; x = 0; }\r | |
351 | if (y < 0) { h += y; y = 0; }\r | |
352 | if (x + w > 800) w = 800 - x;\r | |
353 | if (y + h > 480) h = 480 - y;\r | |
354 | \r | |
c7eb229a | 355 | return pnd_setup_layer_(vout_fbdev_get_fd(layer_fb), enabled, x, y, w, h);\r |
356 | }\r | |
357 | \r | |
358 | void pnd_restore_layer_data(void)\r | |
359 | {\r | |
739e1043 | 360 | short *t = (short *)fb_copy + 320*240 / 2 + 160;\r |
c7eb229a | 361 | \r |
362 | // right now this is used by menu, which wants to preview something\r | |
363 | // so try to get something on the layer.\r | |
364 | if ((t[0] | t[5] | t[13]) == 0)\r | |
365 | memset32((void *)fb_copy, 0x07000700, sizeof(fb_copy) / 4);\r | |
366 | \r | |
d4d62665 | 367 | memcpy(g_screen_ptr, (void *)fb_copy, 320*240*2);\r |
c7eb229a | 368 | plat_video_flip();\r |
369 | }\r | |
370 | \r | |
d5d17782 | 371 | void emu_video_mode_change(int start_line, int line_count, int start_col, int col_count)\r |
c7eb229a | 372 | {\r |
ca980e1b | 373 | int fb_w, fb_h = 240, fb_left = 0, fb_right = 0, fb_top = 0, fb_bottom = 0;\r |
c7eb229a | 374 | \r |
d40231e2 | 375 | if (doing_bg_frame)\r |
376 | return;\r | |
377 | \r | |
c7eb229a | 378 | switch (currentConfig.scaling) {\r |
379 | case SCALE_1x1:\r | |
ca980e1b | 380 | g_layer_w = col_count;\r |
c7eb229a | 381 | g_layer_h = fb_h;\r |
382 | break;\r | |
383 | case SCALE_2x2_3x2:\r | |
ca980e1b | 384 | g_layer_w = col_count * (col_count < 320 ? 3 : 2);\r |
c7eb229a | 385 | g_layer_h = fb_h * 2;\r |
386 | break;\r | |
387 | case SCALE_2x2_2x2:\r | |
ca980e1b | 388 | g_layer_w = col_count * 2;\r |
c7eb229a | 389 | g_layer_h = fb_h * 2;\r |
390 | break;\r | |
391 | case SCALE_FULLSCREEN:\r | |
392 | g_layer_w = 800;\r | |
393 | g_layer_h = 480;\r | |
394 | break;\r | |
395 | case SCALE_CUSTOM:\r | |
396 | g_layer_x = g_layer_cx;\r | |
397 | g_layer_y = g_layer_cy;\r | |
398 | g_layer_w = g_layer_cw;\r | |
399 | g_layer_h = g_layer_ch;\r | |
400 | break;\r | |
401 | }\r | |
402 | \r | |
403 | if (currentConfig.scaling != SCALE_CUSTOM) {\r | |
404 | // center the layer\r | |
405 | g_layer_x = 800 / 2 - g_layer_w / 2;\r | |
406 | g_layer_y = 480 / 2 - g_layer_h / 2;\r | |
407 | }\r | |
408 | \r | |
409 | switch (currentConfig.scaling) {\r | |
410 | case SCALE_FULLSCREEN:\r | |
411 | case SCALE_CUSTOM:\r | |
412 | fb_top = start_line;\r | |
ca980e1b | 413 | fb_h = start_line + line_count;\r |
c7eb229a | 414 | break;\r |
415 | }\r | |
ca980e1b | 416 | fb_w = 320;\r |
417 | fb_left = start_col;\r | |
418 | fb_right = 320 - (start_col + col_count);\r | |
419 | if (currentConfig.scaling == SCALE_CUSTOM) {\r | |
420 | int right = g_layer_x + g_layer_w;\r | |
421 | int bottom = g_layer_y + g_layer_h;\r | |
422 | if (g_layer_x < 0)\r | |
423 | fb_left += -g_layer_x * col_count / g_menuscreen_w;\r | |
424 | if (g_layer_y < 0)\r | |
425 | fb_top += -g_layer_y * line_count / g_menuscreen_h;\r | |
426 | if (right > g_menuscreen_w)\r | |
427 | fb_right += (right - g_menuscreen_w) * col_count / g_menuscreen_w;\r | |
428 | if (bottom > g_menuscreen_h)\r | |
429 | fb_bottom += (bottom - g_menuscreen_h) * line_count / g_menuscreen_h;\r | |
430 | }\r | |
431 | fb_w -= fb_left + fb_right;\r | |
432 | fb_h -= fb_top + fb_bottom;\r | |
c7eb229a | 433 | \r |
434 | pnd_setup_layer(1, g_layer_x, g_layer_y, g_layer_w, g_layer_h);\r | |
f20ad523 | 435 | vout_fbdev_resize(layer_fb, fb_w, fb_h, 16, fb_left, fb_right, fb_top, fb_bottom, 4, 0);\r |
c7eb229a | 436 | vout_fbdev_clear(layer_fb);\r |
bf61bea0 | 437 | plat_video_flip();\r |
ca980e1b | 438 | \r |
439 | g_osd_start_x = start_col;\r | |
440 | g_osd_fps_x = start_col + col_count - 5*8 - 2;\r | |
441 | g_osd_y = fb_top + fb_h - 8;\r | |
442 | \r | |
443 | saved_start_line = start_line, saved_line_count = line_count;\r | |
444 | saved_start_col = start_col, saved_col_count = col_count;\r | |
c7eb229a | 445 | }\r |
446 | \r | |
d4d62665 | 447 | void plat_video_loop_prepare(void)\r |
c7eb229a | 448 | {\r |
c7eb229a | 449 | // make sure there is no junk left behind the layer\r |
d4d62665 | 450 | memset(g_menuscreen_ptr, 0, g_menuscreen_w * g_menuscreen_h * 2);\r |
c7eb229a | 451 | g_menuscreen_ptr = vout_fbdev_flip(main_fb);\r |
452 | \r | |
92efe29e | 453 | PicoDrawSetOutFormat(PDF_RGB555, 0);\r |
c7eb229a | 454 | // emu_video_mode_change will call pnd_setup_layer()\r |
d4d62665 | 455 | }\r |
c7eb229a | 456 | \r |
1777b86d | 457 | void plat_show_cursor(int on)\r |
458 | {\r | |
459 | }\r | |
460 | \r | |
461 | int plat_grab_cursor(int on)\r | |
462 | {\r | |
463 | return 0;\r | |
464 | }\r | |
465 | \r | |
466 | int plat_has_wm(void)\r | |
467 | {\r | |
468 | return 0;\r | |
469 | }\r | |
470 | \r | |
d4d62665 | 471 | void pemu_loop_prep(void)\r |
472 | {\r | |
c7eb229a | 473 | // dirty buffers better go now than during gameplay\r |
d9653efd | 474 | fflush(stdout);\r |
475 | fflush(stderr);\r | |
c7eb229a | 476 | sync();\r |
477 | sleep(0);\r | |
c7eb229a | 478 | }\r |
479 | \r | |
480 | void pemu_loop_end(void)\r | |
481 | {\r | |
8a407398 | 482 | memset(fb_copy, 0, sizeof(fb_copy));\r |
c7eb229a | 483 | /* do one more frame for menu bg */\r |
45285368 | 484 | pemu_forced_frame(0, 1);\r |
c7eb229a | 485 | \r |
486 | pnd_setup_layer(0, g_layer_x, g_layer_y, g_layer_w, g_layer_h);\r | |
c7eb229a | 487 | }\r |
488 | \r | |
489 | void plat_wait_till_us(unsigned int us_to)\r | |
490 | {\r | |
491 | unsigned int now;\r | |
492 | signed int diff;\r | |
493 | \r | |
494 | now = plat_get_ticks_us();\r | |
495 | \r | |
496 | // XXX: need to check NOHZ\r | |
497 | diff = (signed int)(us_to - now);\r | |
498 | if (diff > 10000) {\r | |
499 | //printf("sleep %d\n", us_to - now);\r | |
500 | usleep(diff * 15 / 16);\r | |
501 | now = plat_get_ticks_us();\r | |
502 | //printf(" wake %d\n", (signed)(us_to - now));\r | |
503 | }\r | |
504 | /*\r | |
505 | while ((signed int)(us_to - now) > 512) {\r | |
506 | spend_cycles(1024);\r | |
507 | now = plat_get_ticks_us();\r | |
508 | }\r | |
509 | */\r | |
510 | }\r | |
511 | \r | |
759c9d38 | 512 | void *plat_mem_get_for_drc(size_t size)\r |
513 | {\r | |
514 | return NULL;\r | |
515 | }\r | |
516 | \r | |
58fc34b1 | 517 | int plat_parse_arg(int argc, char *argv[], int *x)\r |
518 | {\r | |
519 | return 1;\r | |
520 | }\r | |
521 | \r | |
c7eb229a | 522 | void plat_early_init(void)\r |
523 | {\r | |
524 | }\r | |
525 | \r | |
526 | void plat_init(void)\r | |
527 | {\r | |
528 | const char *main_fb_name, *layer_fb_name;\r | |
529 | int fd, ret, w, h;\r | |
530 | \r | |
531 | main_fb_name = getenv("FBDEV_MAIN");\r | |
532 | if (main_fb_name == NULL)\r | |
533 | main_fb_name = "/dev/fb0";\r | |
534 | \r | |
535 | layer_fb_name = getenv("FBDEV_LAYER");\r | |
536 | if (layer_fb_name == NULL)\r | |
537 | layer_fb_name = "/dev/fb1";\r | |
538 | \r | |
539 | // must set the layer up first to be able to use it\r | |
540 | fd = open(layer_fb_name, O_RDWR);\r | |
541 | if (fd == -1) {\r | |
542 | fprintf(stderr, "%s: ", layer_fb_name);\r | |
543 | perror("open");\r | |
544 | exit(1);\r | |
545 | }\r | |
546 | \r | |
547 | ret = pnd_setup_layer_(fd, 0, g_layer_x, g_layer_y, g_layer_w, g_layer_h);\r | |
548 | close(fd);\r | |
549 | if (ret != 0) {\r | |
550 | fprintf(stderr, "failed to set up layer, exiting.\n");\r | |
551 | exit(1);\r | |
552 | }\r | |
553 | \r | |
d4d62665 | 554 | xenv_init(NULL, "PicoDrive " VERSION);\r |
c7eb229a | 555 | \r |
556 | w = h = 0;\r | |
21ebcfd3 | 557 | main_fb = vout_fbdev_init(main_fb_name, &w, &h, 16, 2);\r |
c7eb229a | 558 | if (main_fb == NULL) {\r |
559 | fprintf(stderr, "couldn't init fb: %s\n", main_fb_name);\r | |
560 | exit(1);\r | |
561 | }\r | |
562 | \r | |
9cdfc191 | 563 | g_menuscreen_w = g_menuscreen_pp = w;\r |
d40231e2 | 564 | g_menuscreen_h = h;\r |
c7eb229a | 565 | g_menuscreen_ptr = vout_fbdev_flip(main_fb);\r |
566 | \r | |
567 | w = 320; h = 240;\r | |
b011c2af | 568 | layer_fb = vout_fbdev_init(layer_fb_name, &w, &h, 16, 4);\r |
c7eb229a | 569 | if (layer_fb == NULL) {\r |
570 | fprintf(stderr, "couldn't init fb: %s\n", layer_fb_name);\r | |
571 | goto fail0;\r | |
572 | }\r | |
573 | \r | |
574 | if (w != g_screen_width || h != g_screen_height) {\r | |
575 | fprintf(stderr, "%dx%d not supported on %s\n", w, h, layer_fb_name);\r | |
576 | goto fail1;\r | |
577 | }\r | |
578 | g_screen_ptr = vout_fbdev_flip(layer_fb);\r | |
579 | \r | |
d40231e2 | 580 | temp_frame = calloc(g_menuscreen_w * g_menuscreen_h * 2, 1);\r |
581 | if (temp_frame == NULL) {\r | |
582 | fprintf(stderr, "OOM\n");\r | |
583 | goto fail1;\r | |
584 | }\r | |
c7eb229a | 585 | g_menubg_ptr = temp_frame;\r |
586 | g_menubg_src_ptr = temp_frame;\r | |
587 | \r | |
c7eb229a | 588 | pnd_menu_init();\r |
45285368 | 589 | \r |
55d7dcb2 | 590 | // default ROM path\r |
591 | strcpy(rom_fname_loaded, "/media");\r | |
592 | \r | |
4e3551a5 | 593 | in_evdev_init(&pandora_evdev_pdata);\r |
d4d62665 | 594 | in_probe();\r |
595 | plat_target_setup_input();\r | |
596 | \r | |
597 | sndout_oss_frag_frames = 2;\r | |
598 | \r | |
c7eb229a | 599 | return;\r |
600 | \r | |
601 | fail1:\r | |
602 | vout_fbdev_finish(layer_fb);\r | |
603 | fail0:\r | |
604 | vout_fbdev_finish(main_fb);\r | |
605 | exit(1);\r | |
606 | }\r | |
607 | \r | |
608 | void plat_finish(void)\r | |
609 | {\r | |
c7eb229a | 610 | vout_fbdev_finish(main_fb);\r |
10ef62e3 | 611 | xenv_finish();\r |
c7eb229a | 612 | \r |
613 | printf("all done\n");\r | |
614 | }\r | |
615 | \r |