all repos — mgba @ c14da05d8dca225010677643c32fea5c0ac8517a

mGBA Game Boy Advance Emulator

src/platform/sdl/pandora-sdl.c (view raw)

  1/* Copyright (c) 2013-2015 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include "main.h"
  7
  8#include "gba/supervisor/thread.h"
  9
 10#include <linux/omapfb.h>
 11#include <linux/fb.h>
 12#include <sys/ioctl.h>
 13#include <sys/mman.h>
 14
 15bool GBASDLInit(struct SDLSoftwareRenderer* renderer) {
 16	SDL_SetVideoMode(800, 480, 16, SDL_FULLSCREEN);
 17
 18	renderer->odd = 0;
 19	renderer->fb = open("/dev/fb1", O_RDWR);
 20	if (renderer->fb < 0) {
 21		return false;
 22	}
 23
 24	struct omapfb_plane_info plane;
 25	struct omapfb_mem_info mem;
 26	if (ioctl(renderer->fb, OMAPFB_QUERY_PLANE, &plane) < 0) {
 27		return false;
 28	}
 29	if (ioctl(renderer->fb, OMAPFB_QUERY_MEM, &mem) < 0) {
 30		return false;
 31	}
 32
 33	if (plane.enabled) {
 34		plane.enabled = 0;
 35		ioctl(renderer->fb, OMAPFB_SETUP_PLANE, &plane);
 36	}
 37
 38	mem.size = VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * 4;
 39	ioctl(renderer->fb, OMAPFB_SETUP_MEM, &mem);
 40
 41	plane.enabled = 1;
 42	plane.pos_x = 40;
 43	plane.pos_y = 0;
 44	plane.out_width = 720;
 45	plane.out_height = 480;
 46	ioctl(renderer->fb, OMAPFB_SETUP_PLANE, &plane);
 47
 48	struct fb_var_screeninfo info;
 49	ioctl(renderer->fb, FBIOGET_VSCREENINFO, &info);
 50	info.xres = VIDEO_HORIZONTAL_PIXELS;
 51	info.yres = VIDEO_VERTICAL_PIXELS;
 52	info.xres_virtual = VIDEO_HORIZONTAL_PIXELS;
 53	info.yres_virtual = VIDEO_VERTICAL_PIXELS * 2;
 54	info.bits_per_pixel = 16;
 55	ioctl(renderer->fb, FBIOPUT_VSCREENINFO, &info);
 56
 57	renderer->odd = 0;
 58	renderer->base[0] = mmap(0, VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * 4, PROT_READ | PROT_WRITE, MAP_SHARED, renderer->fb, 0);
 59	renderer->base[1] = (uint16_t*) renderer->base[0] + VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS;
 60
 61	renderer->d.outputBuffer = renderer->base[0];
 62	renderer->d.outputBufferStride = VIDEO_HORIZONTAL_PIXELS;
 63	return true;
 64}
 65
 66void GBASDLRunloop(struct GBAThread* context, struct SDLSoftwareRenderer* renderer) {
 67	SDL_Event event;
 68
 69	while (context->state < THREAD_EXITING) {
 70		while (SDL_PollEvent(&event)) {
 71			GBASDLHandleEvent(context, &renderer->player, &event);
 72		}
 73
 74		if (GBASyncWaitFrameStart(&context->sync, context->frameskip)) {
 75			int arg = 0;
 76			ioctl(renderer->fb, FBIO_WAITFORVSYNC, &arg);
 77
 78			struct fb_var_screeninfo info;
 79			ioctl(renderer->fb, FBIOGET_VSCREENINFO, &info);
 80			info.yoffset = VIDEO_VERTICAL_PIXELS * renderer->odd;
 81			ioctl(renderer->fb, FBIOPAN_DISPLAY, &info);
 82
 83			renderer->odd = !renderer->odd;
 84			renderer->d.outputBuffer = renderer->base[renderer->odd];
 85		}
 86		GBASyncWaitFrameEnd(&context->sync);
 87	}
 88}
 89
 90void GBASDLDeinit(struct SDLSoftwareRenderer* renderer) {
 91	munmap(renderer->base[0], VIDEO_HORIZONTAL_PIXELS * VIDEO_VERTICAL_PIXELS * 4);
 92
 93	struct omapfb_plane_info plane;
 94	struct omapfb_mem_info mem;
 95	ioctl(renderer->fb, OMAPFB_QUERY_PLANE, &plane);
 96	ioctl(renderer->fb, OMAPFB_QUERY_MEM, &mem);
 97
 98	mem.size = 0;
 99	ioctl(renderer->fb, OMAPFB_SETUP_MEM, &mem);
100
101	plane.enabled = 0;
102	plane.pos_x = 0;
103	plane.pos_y = 0;
104	plane.out_width = 0;
105	plane.out_height = 0;
106	ioctl(renderer->fb, OMAPFB_SETUP_PLANE, &plane);
107
108	close(renderer->fb);
109}