raspberry pi port
authorDave <pribyl.email@gmail.com>
Mon, 4 Mar 2013 21:28:03 +0000 (22:28 +0100)
committernotaz <notasas@gmail.com>
Thu, 7 Mar 2013 21:16:38 +0000 (23:16 +0200)
15 files changed:
common.h
gui.c
input.c
main.c
raspberrypi/Makefile [new file with mode: 0644]
raspberrypi/gles_video.c [new file with mode: 0644]
raspberrypi/gles_video.h [new file with mode: 0644]
raspberrypi/keys.txt [new file with mode: 0644]
raspberrypi/rpi.c [new file with mode: 0644]
raspberrypi/rpi.h [new file with mode: 0644]
raspberrypi/test/Makefile [new file with mode: 0644]
raspberrypi/test/gles_video.c [new file with mode: 0644]
raspberrypi/test/test.c [new file with mode: 0644]
sound.c
video.c

index f97549f..fb7f31e 100644 (file)
--- a/common.h
+++ b/common.h
@@ -270,4 +270,8 @@ typedef u32 fixed8_24;
   #include "pandora/pnd.h"
 #endif
 
+#ifdef RPI_BUILD
+  #include "raspberrypi/rpi.h"
+#endif
+
 #endif
diff --git a/gui.c b/gui.c
index b28392d..1779656 100644 (file)
--- a/gui.c
+++ b/gui.c
@@ -552,7 +552,7 @@ typedef enum
   NUMBER_SELECTION_OPTION = 0x01,
   STRING_SELECTION_OPTION = 0x02,
   SUBMENU_OPTION          = 0x04,
-  ACTION_OPTION           = 0x08
+  ACTION_OPTION           = 0x08,
 } menu_option_type_enum;
 
 struct _menu_type
@@ -746,6 +746,13 @@ u32 gamepad_config_line_to_button[] =
 
 #endif
 
+#ifdef RPI_BUILD
+
+u32 gamepad_config_line_to_button[] =
+ { 0, 2, 1, 3, 8, 9, 10, 11, 6, 7, 4, 5, 12, 13, 14, 15 };
+
+#endif
+
 static const char *scale_options[] =
 {
 #ifdef PSP_BUILD
@@ -759,6 +766,8 @@ static const char *scale_options[] =
   "unscaled", "2x", "3x", "fullscreen"
 #elif defined(GP2X_BUILD)
   "unscaled 3:2", "scaled 3:2", "fullscreen", "scaled 3:2 (software)"
+#elif defined(RPI_BUILD)
+  "fullscreen"
 #else
   "unscaled 3:2"
 #endif
@@ -843,10 +852,15 @@ s32 load_game_config_file()
   if(file_loaded)
     return 0;
 
+#ifdef RPI_BUILD
+  current_frameskip_type = manual_frameskip;
+  frameskip_value = 1;
+#else
   current_frameskip_type = auto_frameskip;
   frameskip_value = 4;
 #ifdef POLLUX_BUILD
   frameskip_value = 1;
+#endif
 #endif
   random_skip = 0;
   clock_speed = default_clock_speed;
@@ -1213,10 +1227,6 @@ u32 menu(u16 *original_screen)
        reg[CHANGED_PC_STATUS] = 1;
        menu_update_clock();
     }
-    else
-    {
-      choose_menu(current_menu);
-    }
   }
 
   void menu_restart()
@@ -1329,8 +1339,9 @@ u32 menu(u16 *original_screen)
   static const char *update_backup_options[] = { "Exit only", "Automatic" };
 
   // Marker for help information, don't go past this mark (except \n)------*
-  menu_option_type graphics_sound_options[] =
-  {
+  menu_option_type graphics_sound_options[] = 
+ {
+#ifndef RPI_BUILD
     string_selection_option(NULL, "Display scaling", scale_options,
      (u32 *)(&screen_scale),
      sizeof(scale_options) / sizeof(scale_options[0]),
@@ -1344,6 +1355,8 @@ u32 menu(u16 *original_screen)
 #endif
 #endif
      "", 2),
+#endif
+
 #ifndef GP2X_BUILD
     string_selection_option(NULL, "Screen filtering", yes_no_options,
      (u32 *)(&screen_filter), 2,
@@ -1352,7 +1365,7 @@ u32 menu(u16 *original_screen)
      "smooth image, at the cost of being blurry and having less vibrant\n"
      "colors.", 3),
 #endif
-#ifdef PND_BUILD
+#if defined (PND_BUILD)
     string_selection_option(NULL, "Scaling filter", filter2_options,
      (u32 *)(&screen_filter2),
      sizeof(filter2_options) / sizeof(filter2_options[0]),
@@ -1572,7 +1585,7 @@ u32 menu(u16 *original_screen)
 
 #endif
 
-#ifdef PC_BUILD
+#if defined(PC_BUILD) || defined(RPI_BUILD)
 
   menu_option_type gamepad_config_options[] =
   {
@@ -1801,6 +1814,10 @@ u32 menu(u16 *original_screen)
 
         if(current_option->option_type & SUBMENU_OPTION)
           choose_menu(current_option->sub_menu);
+
+        if(current_menu == &main_menu)
+           choose_menu(&main_menu);
+
         break;
 
       default:
diff --git a/input.c b/input.c
index 4917094..f01c53d 100644 (file)
--- a/input.c
+++ b/input.c
@@ -555,8 +555,49 @@ void init_input()
 #endif
 
 
+#if defined(RPI_BUILD)
 
-#ifdef PC_BUILD
+u32 key_map(SDLKey key_sym)
+{
+  switch(key_sym)
+  {
+    case SDLK_a:
+      return BUTTON_L;
+
+    case SDLK_s:
+      return BUTTON_R;
+
+    case SDLK_DOWN:
+      return BUTTON_DOWN;
+
+    case SDLK_UP:
+      return BUTTON_UP;
+
+    case SDLK_LEFT:
+      return BUTTON_LEFT;
+
+    case SDLK_RIGHT:
+      return BUTTON_RIGHT;
+
+    case SDLK_RETURN:
+      return BUTTON_START;
+
+    case SDLK_BACKSPACE:
+      return BUTTON_SELECT;
+
+    case SDLK_x:
+      return BUTTON_B;
+
+    case SDLK_z:
+      return BUTTON_A;
+
+    default:
+      return BUTTON_NONE;
+  }
+}
+#endif
+
+#if defined(PC_BUILD)
 
 u32 key_map(SDLKey key_sym)
 {
@@ -596,6 +637,8 @@ u32 key_map(SDLKey key_sym)
       return BUTTON_NONE;
   }
 }
+#endif
+#if defined(PC_BUILD) || defined(RPI_BUILD)
 
 u32 joy_map(u32 button)
 {
@@ -607,16 +650,16 @@ u32 joy_map(u32 button)
     case 5:
       return BUTTON_R;
 
-    case 9:
+    case 2:
       return BUTTON_START;
 
-    case 8:
+    case 3:
       return BUTTON_SELECT;
 
-    case 0:
+    case 1:
       return BUTTON_B;
 
-    case 1:
+    case 0:
       return BUTTON_A;
 
     default:
@@ -632,7 +675,7 @@ gui_action_type get_gui_input()
   delay_us(30000);
 
   while(SDL_PollEvent(&event))
-  {
+  { 
     switch(event.type)
     {
       case SDL_QUIT:
@@ -669,15 +712,49 @@ gui_action_type get_gui_input()
           case SDLK_BACKSPACE:
             gui_action = CURSOR_BACK;
             break;
+        default:
+           break;
+      }
+    }
+    break;
+#ifdef RPI_BUILD
+    case SDL_JOYBUTTONDOWN:
+    {
+      switch (event.jbutton.button)
+      {
+       case 2:
+            gui_action = CURSOR_BACK;
+            break;
 
-          default:
+       case 1:
+            gui_action = CURSOR_EXIT;
             break;
-        }
+
+       case 0:
+           gui_action = CURSOR_SELECT;
+           break;
+       }
+     }
+     break;
+
+     case SDL_JOYAXISMOTION:
+     {
+         if (event.jaxis.axis==0) { //Left-Right
+            if (event.jaxis.value < -3200) gui_action = CURSOR_LEFT;
+               else if (event.jaxis.value > 3200) gui_action = CURSOR_RIGHT;
+         }
+         if (event.jaxis.axis==1) {  //Up-Down
+            if (event.jaxis.value < -3200) gui_action = CURSOR_UP;
+               else if (event.jaxis.value > 3200) gui_action = CURSOR_DOWN;
+         }
+    }
+    break;
+
+#endif
+    default:
         break;
-      }
     }
   }
-
   return gui_action;
 }
 
@@ -698,8 +775,11 @@ u32 update_input()
         {
           quit();
         }
-
+#ifdef PC_BUILD
         if(event.key.keysym.sym == SDLK_BACKSPACE)
+#else
+        if(event.key.keysym.sym == SDLK_F10)
+#endif
         {
           u16 *screen_copy = copy_screen();
           u32 ret_val = menu(screen_copy);
@@ -708,7 +788,7 @@ u32 update_input()
           return ret_val;
         }
         else
-
+#ifdef PC_BUILD
         if(event.key.keysym.sym == SDLK_F1)
         {
           debug_on();
@@ -741,7 +821,7 @@ u32 update_input()
           dump_translation_cache();
         }
         else
-
+#endif
         if(event.key.keysym.sym == SDLK_F5)
         {
           char current_savestate_filename[512];
@@ -795,6 +875,22 @@ u32 update_input()
         key &= ~(joy_map(event.jbutton.button));
         break;
       }
+#ifdef RPI_BUILD
+      case SDL_JOYAXISMOTION:
+      {
+         if (event.jaxis.axis==0) { //Left-Right
+            key &= ~(BUTTON_LEFT|BUTTON_RIGHT);
+         if (event.jaxis.value < -3200)  key |= BUTTON_LEFT;
+           else if (event.jaxis.value > 3200)  key |= BUTTON_RIGHT;
+       } 
+         if (event.jaxis.axis==1) {  //Up-Down
+            key &= ~(BUTTON_UP|BUTTON_DOWN);
+         if (event.jaxis.value < -3200)  key |= BUTTON_UP;
+           else if (event.jaxis.value > 3200)  key |= BUTTON_DOWN;
+       }
+       break;
+#endif
+      }
     }
   }
 
diff --git a/main.c b/main.c
index 4189309..c084181 100644 (file)
--- a/main.c
+++ b/main.c
@@ -38,8 +38,14 @@ debug_state current_debug_state = RUN;
 
 //u32 breakpoint_value = 0;
 
+#ifdef RPI_BUILD
+frameskip_type current_frameskip_type = manual_frameskip; //manual; //auto_frameskip;
+u32 global_cycles_per_instruction = 1;
+#else
 frameskip_type current_frameskip_type = auto_frameskip;
 u32 global_cycles_per_instruction = 1;
+#endif
+
 u32 random_skip = 0;
 u32 fps_debug = 0;
 
@@ -821,7 +827,7 @@ void synchronize()
   }
   else if (synchronize_flag)
   {
-#if defined(PND_BUILD)
+#if defined(PND_BUILD) || defined(RPI_BUILD)
     fb_wait_vsync();
 #elif !defined(GP2X_BUILD) // sleeping on GP2X is a bad idea
     delay_us((u64)virtual_frame_count * 50000 / 3 - new_ticks + 2);
@@ -867,7 +873,7 @@ void synchronize()
 
   interval_skipped_frames += skip_next_frame;
 
-#if !defined(GP2X_BUILD) && !defined(PND_BUILD)
+#if !defined(GP2X_BUILD) && !defined(PND_BUILD) && !defined(RPI_BUILD)
   char char_buffer[64];
   sprintf(char_buffer, "gpSP: %2d (%2d) fps", fps, frames_drawn);
   SDL_WM_SetCaption(char_buffer, "gpSP");
diff --git a/raspberrypi/Makefile b/raspberrypi/Makefile
new file mode 100644 (file)
index 0000000..336a835
--- /dev/null
@@ -0,0 +1,44 @@
+# gpSP makefile
+# Gilead Kutnick - Exophase
+# pandora port - notaz
+# respberry pi - DPR
+
+# Global definitions
+
+CC        = gcc
+
+OBJS      = rpi.o main.o cpu.o memory.o video.o input.o sound.o gui.o \
+            cheats.o zip.o  arm_stub.o  warm.o cpu_threaded.o\
+           gles_video.o video_blend.o
+
+BIN       = gpsp
+
+# Platform specific definitions 
+
+VPATH      += .. ../arm
+CFLAGS     += -DARM_ARCH -DRPI_BUILD -Wall
+CFLAGS     += -O3 -mfpu=vfp
+CFLAGS     += `sdl-config --cflags`
+CFLAGS     += -I$(SDKSTAGE)/opt/vc/include -I$(SDKSTAGE)/opt/vc/include/interface/vcos/pthreads
+
+# expecting to have PATH set up to get correct sdl-config first
+
+LIBS       += `sdl-config --libs`
+LIBS       += -ldl -lpthread -lz
+LIBS       += -L$(SDKSTAGE)/opt/vc/lib/ -lGLESv2 -lEGL -lopenmaxil -lbcm_host -lvcos -lvchiq_arm  -lrt
+
+# Compilation:
+
+all: $(BIN)
+
+%.o: %.S
+       $(CC) $(CFLAGS) -c -o $@ $<
+
+
+cpu.o cpu_threaded.o: CFLAGS += -Wno-unused-variable -Wno-unused-label
+
+$(BIN): $(OBJS)
+       $(CC) $(OBJS) $(LIBS) -o $(BIN)
+
+clean:
+       rm -f *.o $(BIN)
diff --git a/raspberrypi/gles_video.c b/raspberrypi/gles_video.c
new file mode 100644 (file)
index 0000000..1623bdc
--- /dev/null
@@ -0,0 +1,393 @@
+#include "bcm_host.h"
+#include "GLES/gl.h"
+#include "EGL/egl.h"
+#include "EGL/eglext.h"
+#include "GLES2/gl2.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+
+static uint32_t frame_width = 0;
+static uint32_t frame_height = 0;
+
+
+#define        SHOW_ERROR              gles_show_error();
+
+static void SetOrtho(GLfloat m[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far, GLfloat scale_x, GLfloat scale_y);
+
+static const char* vertex_shader =
+       "uniform mat4 u_vp_matrix;                                                              \n"
+       "attribute vec4 a_position;                                                             \n"
+       "attribute vec2 a_texcoord;                                                             \n"
+       "varying mediump vec2 v_texcoord;                                               \n"
+       "void main()                                                                                    \n"
+       "{                                                                                                              \n"
+       "       v_texcoord = a_texcoord;                                                        \n"
+       "       gl_Position = u_vp_matrix * a_position;                         \n"
+       "}                                                                                                              \n";
+
+static const char* fragment_shader =
+       "varying mediump vec2 v_texcoord;                                               \n"
+       "uniform sampler2D u_texture;                                                   \n"
+       "void main()                                                                                    \n"
+       "{                                                                                                              \n"
+       "       gl_FragColor = texture2D(u_texture, v_texcoord);        \n"
+       "}                                                                                                              \n";
+/*
+static const GLfloat vertices[] =
+{
+       -0.5f, -0.5f, 0.0f,
+       +0.5f, -0.5f, 0.0f,
+       +0.5f, +0.5f, 0.0f,
+       -0.5f, +0.5f, 0.0f,
+};
+*/
+static const GLfloat vertices[] =
+{
+       -0.5f, -0.5f, 0.0f,
+       -0.5f, +0.5f, 0.0f,
+       +0.5f, +0.5f, 0.0f,
+       +0.5f, -0.5f, 0.0f,
+};
+
+#define        TEX_WIDTH       1024
+#define        TEX_HEIGHT      512
+
+static const GLfloat uvs[8];
+
+static const GLushort indices[] =
+{
+       0, 1, 2,
+       0, 2, 3,
+};
+
+static const int kVertexCount = 4;
+static const int kIndexCount = 6;
+
+
+void Create_uvs(GLfloat * matrix, GLfloat max_u, GLfloat max_v) {
+    memset(matrix,0,sizeof(GLfloat)*8);
+    matrix[3]=max_v;
+    matrix[4]=max_u;
+    matrix[5]=max_v;
+    matrix[6]=max_u;
+
+}
+
+void gles_show_error()
+{
+       GLenum error = GL_NO_ERROR;
+    error = glGetError();
+    if (GL_NO_ERROR != error)
+        printf("GL Error %x encountered!\n", error);
+}
+
+static GLuint CreateShader(GLenum type, const char *shader_src)
+{
+       GLuint shader = glCreateShader(type);
+       if(!shader)
+               return 0;
+
+       // Load and compile the shader source
+       glShaderSource(shader, 1, &shader_src, NULL);
+       glCompileShader(shader);
+
+       // Check the compile status
+       GLint compiled = 0;
+       glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+       if(!compiled)
+       {
+               GLint info_len = 0;
+               glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_len);
+               if(info_len > 1)
+               {
+                       char* info_log = (char *)malloc(sizeof(char) * info_len);
+                       glGetShaderInfoLog(shader, info_len, NULL, info_log);
+                       // TODO(dspringer): We could really use a logging API.
+                       printf("Error compiling shader:\n%s\n", info_log);
+                       free(info_log);
+               }
+               glDeleteShader(shader);
+               return 0;
+       }
+       return shader;
+}
+
+static GLuint CreateProgram(const char *vertex_shader_src, const char *fragment_shader_src)
+{
+       GLuint vertex_shader = CreateShader(GL_VERTEX_SHADER, vertex_shader_src);
+       if(!vertex_shader)
+               return 0;
+       GLuint fragment_shader = CreateShader(GL_FRAGMENT_SHADER, fragment_shader_src);
+       if(!fragment_shader)
+       {
+               glDeleteShader(vertex_shader);
+               return 0;
+       }
+
+       GLuint program_object = glCreateProgram();
+       if(!program_object)
+               return 0;
+       glAttachShader(program_object, vertex_shader);
+       glAttachShader(program_object, fragment_shader);
+
+       // Link the program
+       glLinkProgram(program_object);
+
+       // Check the link status
+       GLint linked = 0;
+       glGetProgramiv(program_object, GL_LINK_STATUS, &linked);
+       if(!linked)
+       {
+               GLint info_len = 0;
+               glGetProgramiv(program_object, GL_INFO_LOG_LENGTH, &info_len);
+               if(info_len > 1)
+               {
+                       char* info_log = (char *)malloc(info_len);
+                       glGetProgramInfoLog(program_object, info_len, NULL, info_log);
+                       // TODO(dspringer): We could really use a logging API.
+                       printf("Error linking program:\n%s\n", info_log);
+                       free(info_log);
+               }
+               glDeleteProgram(program_object);
+               return 0;
+       }
+       // Delete these here because they are attached to the program object.
+       glDeleteShader(vertex_shader);
+       glDeleteShader(fragment_shader);
+       return program_object;
+}
+
+typedef        struct ShaderInfo {
+               GLuint program;
+               GLint a_position;
+               GLint a_texcoord;
+               GLint u_vp_matrix;
+               GLint u_texture;
+} ShaderInfo;
+
+static ShaderInfo shader;
+static ShaderInfo shader_filtering;
+static GLuint buffers[3];
+static GLuint textures[2];
+
+
+static void gles2_create()
+{
+       memset(&shader, 0, sizeof(ShaderInfo));
+       shader.program = CreateProgram(vertex_shader, fragment_shader);
+       if(shader.program)
+       {
+               shader.a_position       = glGetAttribLocation(shader.program,   "a_position");
+               shader.a_texcoord       = glGetAttribLocation(shader.program,   "a_texcoord");
+               shader.u_vp_matrix      = glGetUniformLocation(shader.program,  "u_vp_matrix");
+               shader.u_texture        = glGetUniformLocation(shader.program,  "u_texture");
+       }
+       glGenTextures(1, textures);
+       glBindTexture(GL_TEXTURE_2D, textures[0]);
+       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEX_WIDTH, TEX_HEIGHT, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
+
+       Create_uvs(uvs, (float)frame_width/TEX_WIDTH, (float)frame_height/TEX_HEIGHT);
+
+       glGenBuffers(3, buffers);
+       glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
+       glBufferData(GL_ARRAY_BUFFER, kVertexCount * sizeof(GLfloat) * 3, vertices, GL_STATIC_DRAW);
+       glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
+       glBufferData(GL_ARRAY_BUFFER, kVertexCount * sizeof(GLfloat) * 2, uvs, GL_STATIC_DRAW);
+       glBindBuffer(GL_ARRAY_BUFFER, 0);
+       glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[2]);
+       glBufferData(GL_ELEMENT_ARRAY_BUFFER, kIndexCount * sizeof(GL_UNSIGNED_SHORT), indices, GL_STATIC_DRAW);
+       glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+       glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+       glDisable(GL_DEPTH_TEST);
+       glDisable(GL_BLEND);
+       glDisable(GL_DITHER);
+}
+
+static uint32_t screen_width = 0;
+static uint32_t screen_height = 0;
+
+static EGLDisplay display = NULL;
+static EGLSurface surface = NULL;
+static EGLContext context = NULL;
+static EGL_DISPMANX_WINDOW_T nativewindow;
+
+static GLfloat proj[4][4];
+static GLint filter_min;
+static GLint filter_mag;
+
+void video_set_filter(uint32_t filter) {
+       if (filter==0) {
+           filter_min = GL_NEAREST;
+           filter_mag = GL_NEAREST;
+       } else  {
+           filter_min = GL_LINEAR;
+           filter_mag = GL_LINEAR;
+       }
+}
+
+void video_init(uint32_t _width, uint32_t _height, uint32_t filter)
+{
+       if ((_width==0)||(_height==0))
+               return;
+
+       frame_width = _width;
+       frame_height = _height;
+       
+       //bcm_host_init();
+
+       // get an EGL display connection
+       display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+       assert(display != EGL_NO_DISPLAY);
+
+       // initialize the EGL display connection
+       EGLBoolean result = eglInitialize(display, NULL, NULL);
+       assert(EGL_FALSE != result);
+
+       // get an appropriate EGL frame buffer configuration
+       EGLint num_config;
+       EGLConfig config;
+       static const EGLint attribute_list[] =
+       {
+               EGL_RED_SIZE, 8,
+               EGL_GREEN_SIZE, 8,
+               EGL_BLUE_SIZE, 8,
+               EGL_ALPHA_SIZE, 8,
+               EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+               EGL_NONE
+       };
+       result = eglChooseConfig(display, attribute_list, &config, 1, &num_config);
+       assert(EGL_FALSE != result);
+
+       result = eglBindAPI(EGL_OPENGL_ES_API);
+       assert(EGL_FALSE != result);
+
+       // create an EGL rendering context
+       static const EGLint context_attributes[] =
+       {
+               EGL_CONTEXT_CLIENT_VERSION, 2,
+               EGL_NONE
+       };
+       context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attributes);
+       assert(context != EGL_NO_CONTEXT);
+
+       // create an EGL window surface
+       int32_t success = graphics_get_display_size(0, &screen_width, &screen_height);
+       assert(success >= 0);
+
+       VC_RECT_T dst_rect;
+       dst_rect.x = 0;
+       dst_rect.y = 0;
+       dst_rect.width = screen_width;
+       dst_rect.height = screen_height;
+
+       VC_RECT_T src_rect;
+       src_rect.x = 0;
+       src_rect.y = 0;
+       src_rect.width = screen_width << 16;
+       src_rect.height = screen_height << 16;
+
+       DISPMANX_DISPLAY_HANDLE_T dispman_display = vc_dispmanx_display_open(0);
+       DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start(0);
+       DISPMANX_ELEMENT_HANDLE_T dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display,
+        1, &dst_rect, 0, &src_rect, DISPMANX_PROTECTION_NONE, NULL, NULL, DISPMANX_NO_ROTATE);
+
+       nativewindow.element = dispman_element;
+       nativewindow.width = screen_width;
+       nativewindow.height = screen_height;
+       vc_dispmanx_update_submit_sync(dispman_update);
+
+       surface = eglCreateWindowSurface(display, config, &nativewindow, NULL);
+       assert(surface != EGL_NO_SURFACE);
+
+       // connect the context to the surface
+       result = eglMakeCurrent(display, surface, surface, context);
+       assert(EGL_FALSE != result);
+
+       gles2_create();
+
+       int r=(screen_height*10/frame_height);
+       int h = (frame_height*r)/10;
+       int w = (frame_width*r)/10;
+       if (w>screen_width) {
+           r = (screen_width*10/frame_width);
+           h = (frame_height*r)/10;
+           w = (frame_width*r)/10;
+       }
+       glViewport((screen_width-w)/2, (screen_height-h)/2, w, h);
+       SetOrtho(proj, -0.5f, +0.5f, +0.5f, -0.5f, -1.0f, 1.0f, 1.0f ,1.0f );
+       video_set_filter(filter);
+}
+
+static void gles2_destroy()
+{
+       if(!shader.program)
+               return;
+       glDeleteBuffers(3, buffers); SHOW_ERROR
+       glDeleteProgram(shader.program); SHOW_ERROR
+}
+
+static void SetOrtho(GLfloat m[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far, GLfloat scale_x, GLfloat scale_y)
+{
+       memset(m, 0, 4*4*sizeof(GLfloat));
+       m[0][0] = 2.0f/(right - left)*scale_x;
+       m[1][1] = 2.0f/(top - bottom)*scale_y;
+       m[2][2] = -2.0f/(far - near);
+       m[3][0] = -(right + left)/(right - left);
+       m[3][1] = -(top + bottom)/(top - bottom);
+       m[3][2] = -(far + near)/(far - near);
+       m[3][3] = 1;
+}
+#define RGB15(r, g, b)  (((r) << (5+6)) | ((g) << 6) | (b))
+
+static void gles2_Draw( uint16_t *pixels)
+{
+       if(!shader.program)
+               return;
+
+       glClear(GL_COLOR_BUFFER_BIT);
+
+       glUseProgram(shader.program);
+
+        glBindTexture(GL_TEXTURE_2D, textures[0]);
+       glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, frame_width, frame_height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
+       glActiveTexture(GL_TEXTURE0);
+       glUniform1i(shader.u_texture, 0);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter_mag);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter_min);
+       glGenerateMipmap(GL_TEXTURE_2D);
+
+       glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
+       glVertexAttribPointer(shader.a_position, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), NULL);
+       glEnableVertexAttribArray(shader.a_position);
+
+       glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
+       glVertexAttribPointer(shader.a_texcoord, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), NULL);
+       glEnableVertexAttribArray(shader.a_texcoord);
+
+       glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[2]);
+       glUniformMatrix4fv(shader.u_vp_matrix, 1, GL_FALSE, (const GLfloat * )&proj);
+       glDrawElements(GL_TRIANGLES, kIndexCount, GL_UNSIGNED_SHORT, 0);
+
+       glBindBuffer(GL_ARRAY_BUFFER, 0);
+       glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+       //glFlush();
+}
+
+void video_close()
+{
+       gles2_destroy();
+       // Release OpenGL resources
+       eglMakeCurrent( display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
+       eglDestroySurface( display, surface );
+       eglDestroyContext( display, context );
+       eglTerminate( display );
+}
+
+void video_draw(uint16_t *pixels)
+{
+       gles2_Draw (pixels);
+       eglSwapBuffers(display, surface);
+}
diff --git a/raspberrypi/gles_video.h b/raspberrypi/gles_video.h
new file mode 100644 (file)
index 0000000..cd87f92
--- /dev/null
@@ -0,0 +1,4 @@
+
+void video_init(uint32_t width,uint32_t height,uint32_t filter);
+void video_close();
+void video_draw(uint16_t *pixels);
diff --git a/raspberrypi/keys.txt b/raspberrypi/keys.txt
new file mode 100644 (file)
index 0000000..4bfbdd5
--- /dev/null
@@ -0,0 +1,33 @@
+gpsp raspberry pi 
+
+CONTROL KEYS
+============
+KEYBOARD
+---------
+Up             Up Arrow
+Down           Down Arrow
+Left           Left Arrow
+Right          Right Arrow
+A              Z
+B              X
+Start          Enter
+Select         Backspace
+L              A
+R              S
+
+Exit           Esc
+Menu           F10
+
+GAMEPAD
+-------
+Up             XAsix -
+Down           XAsix +
+Left           YAsix -
+Right          YAsix +
+A              Button 1
+B              Button 2
+Start          Button 3
+Select         Button 4
+L              Button 5
+R              Button 6
+
diff --git a/raspberrypi/rpi.c b/raspberrypi/rpi.c
new file mode 100644 (file)
index 0000000..3fbecb8
--- /dev/null
@@ -0,0 +1,111 @@
+/* gameplaySP - raspberry backend
+ *
+ * Copyright (C) 2013 DPR <pribyl.email@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "../common.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "gles_video.h"
+#include "rpi.h"
+#include "bcm_host.h"
+
+u32 gamepad_config_map[PLAT_BUTTON_COUNT] =
+{
+  BUTTON_ID_UP,                 // Up
+  BUTTON_ID_LEFT,               // Left
+  BUTTON_ID_DOWN,               // Down
+  BUTTON_ID_RIGHT,              // Right
+  BUTTON_ID_START,              // Start
+  BUTTON_ID_SELECT,             // Select
+  BUTTON_ID_L,                  // Ltrigger
+  BUTTON_ID_R,                  // Rtrigger
+  BUTTON_ID_FPS,                // A
+  BUTTON_ID_A,                  // B
+  BUTTON_ID_B,                  // X
+  BUTTON_ID_MENU,               // Y
+  BUTTON_ID_SAVESTATE,          // 1
+  BUTTON_ID_LOADSTATE,          // 2
+  BUTTON_ID_FASTFORWARD,        // 3
+  BUTTON_ID_NONE,               // 4
+  BUTTON_ID_MENU                // Space
+};
+
+
+#define MAX_VIDEO_MEM (480*270*2)
+static int video_started=0;
+static uint16_t * video_buff;
+
+
+void gpsp_plat_init(void)
+{
+  int ret, w, h, fd;
+  //const char *layer_fb_name;
+  SDL_Surface* myVideoSurface;
+
+  bcm_host_init();
+
+  ret = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE);
+  if (ret != 0) {
+    fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError());
+    exit(1);
+  }
+
+  myVideoSurface = SDL_SetVideoMode( 0, 0, 16,  SDL_SWSURFACE);
+    // Print out some information about the video surface
+    if (myVideoSurface == NULL) {
+       fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError());
+       exit(1);
+    }
+  SDL_ShowCursor(0);
+  fb_set_mode(240, 160, 0, 0, 0, 0);
+  screen_scale = 3;
+}
+
+void gpsp_plat_quit(void)
+{
+    if (video_started) {
+       video_close();
+       free(video_buff);
+       video_started=0;
+    }
+  SDL_Quit();
+}
+
+
+void *fb_flip_screen(void)
+{
+  video_draw(video_buff);
+  return video_buff;
+}
+
+void fb_wait_vsync(void)
+{
+}
+
+void fb_set_mode(int w, int h, int buffers, int scale,int filter, int filter2)
+{
+    if (video_started) {
+       video_close();
+       free(video_buff);
+    }
+    video_buff=malloc(w*h*sizeof(uint16_t));
+    memset(video_buff,0,w*h*sizeof(uint16_t));
+    video_init(w,h,filter);
+    video_started=1;
+}
+// vim:shiftwidth=2:expandtab
diff --git a/raspberrypi/rpi.h b/raspberrypi/rpi.h
new file mode 100644 (file)
index 0000000..536414d
--- /dev/null
@@ -0,0 +1,9 @@
+void gpsp_plat_init(void);
+void gpsp_plat_quit(void);
+
+#define PLAT_BUTTON_COUNT 17
+extern u32 button_plat_mask_to_config[PLAT_BUTTON_COUNT];
+
+void *fb_flip_screen(void);
+void fb_set_mode(int w, int h, int buffers, int scale, int filter, int filter2);
+void fb_wait_vsync(void);
diff --git a/raspberrypi/test/Makefile b/raspberrypi/test/Makefile
new file mode 100644 (file)
index 0000000..9830834
--- /dev/null
@@ -0,0 +1,30 @@
+# glestest makefile
+# Global definitions
+
+CC        = gcc
+
+OBJS      = gles_video.o test.o
+
+BIN       = glestest
+
+# Platform specific definitions 
+
+CFLAGS+=-D_LINUX
+
+LIBS +=-L$(SDKSTAGE)/opt/vc/lib/ -lGLESv2 -lEGL -lopenmaxil -lbcm_host -lvcos -lvchiq_arm -lpthread -lrt 
+
+INCLUDES+=-I$(SDKSTAGE)/opt/vc/include -I$(SDKSTAGE)/opt/vc/include/interface/vcos/pthreads
+
+# Compilation:
+
+all:   $(BIN)
+
+%.o: %.c
+       $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
+
+$(BIN): $(OBJS)
+       $(CC) $(OBJS) $(LIBS) -o $(BIN)
+
+clean:
+       rm -f *.o $(BIN)
+
diff --git a/raspberrypi/test/gles_video.c b/raspberrypi/test/gles_video.c
new file mode 100644 (file)
index 0000000..4d7d405
--- /dev/null
@@ -0,0 +1,383 @@
+#include "bcm_host.h"
+#include "GLES/gl.h"
+#include "EGL/egl.h"
+#include "EGL/eglext.h"
+#include "GLES2/gl2.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+
+static uint32_t frame_width = 0;
+static uint32_t frame_height = 0;
+
+
+#define        SHOW_ERROR              gles_show_error();
+
+static void SetOrtho(GLfloat m[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far, GLfloat scale_x, GLfloat scale_y);
+
+static const char* vertex_shader =
+       "uniform mat4 u_vp_matrix;                                                              \n"
+       "attribute vec4 a_position;                                                             \n"
+       "attribute vec2 a_texcoord;                                                             \n"
+       "varying mediump vec2 v_texcoord;                                               \n"
+       "void main()                                                                                    \n"
+       "{                                                                                                              \n"
+       "       v_texcoord = a_texcoord;                                                        \n"
+       "       gl_Position = u_vp_matrix * a_position;                         \n"
+       "}                                                                                                              \n";
+
+static const char* fragment_shader =
+       "varying mediump vec2 v_texcoord;                                               \n"
+       "uniform sampler2D u_texture;                                                   \n"
+       "void main()                                                                                    \n"
+       "{                                                                                                              \n"
+       "       gl_FragColor = texture2D(u_texture, v_texcoord);        \n"
+       "}                                                                                                              \n";
+
+static const GLfloat vertices[] =
+{
+       -0.5f, -0.5f, 0.0f,
+       +0.5f, -0.5f, 0.0f,
+       +0.5f, +0.5f, 0.0f,
+       -0.5f, +0.5f, 0.0f,
+};
+
+#define        TEX_WIDTH       1024
+#define        TEX_HEIGHT      512
+
+static const GLfloat uvs[8];
+
+static const GLushort indices[] =
+{
+       0, 1, 2,
+       0, 2, 3,
+};
+
+static const int kVertexCount = 4;
+static const int kIndexCount = 6;
+
+
+void Create_uvs(GLfloat * matrix, GLfloat max_u, GLfloat max_v) {
+    memset(matrix,0,sizeof(GLfloat)*8);
+    matrix[3]=max_v;
+    matrix[4]=max_u;
+    matrix[5]=max_v;
+    matrix[6]=max_u;
+
+}
+
+void gles_show_error()
+{
+       GLenum error = GL_NO_ERROR;
+    error = glGetError();
+    if (GL_NO_ERROR != error)
+        printf("GL Error %x encountered!\n", error);
+}
+
+static GLuint CreateShader(GLenum type, const char *shader_src)
+{
+       GLuint shader = glCreateShader(type);
+       if(!shader)
+               return 0;
+
+       // Load and compile the shader source
+       glShaderSource(shader, 1, &shader_src, NULL);
+       glCompileShader(shader);
+
+       // Check the compile status
+       GLint compiled = 0;
+       glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+       if(!compiled)
+       {
+               GLint info_len = 0;
+               glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_len);
+               if(info_len > 1)
+               {
+                       char* info_log = (char *)malloc(sizeof(char) * info_len);
+                       glGetShaderInfoLog(shader, info_len, NULL, info_log);
+                       // TODO(dspringer): We could really use a logging API.
+                       printf("Error compiling shader:\n%s\n", info_log);
+                       free(info_log);
+               }
+               glDeleteShader(shader);
+               return 0;
+       }
+       return shader;
+}
+
+static GLuint CreateProgram(const char *vertex_shader_src, const char *fragment_shader_src)
+{
+       GLuint vertex_shader = CreateShader(GL_VERTEX_SHADER, vertex_shader_src);
+       if(!vertex_shader)
+               return 0;
+       GLuint fragment_shader = CreateShader(GL_FRAGMENT_SHADER, fragment_shader_src);
+       if(!fragment_shader)
+       {
+               glDeleteShader(vertex_shader);
+               return 0;
+       }
+
+       GLuint program_object = glCreateProgram();
+       if(!program_object)
+               return 0;
+       glAttachShader(program_object, vertex_shader);
+       glAttachShader(program_object, fragment_shader);
+
+       // Link the program
+       glLinkProgram(program_object);
+
+       // Check the link status
+       GLint linked = 0;
+       glGetProgramiv(program_object, GL_LINK_STATUS, &linked);
+       if(!linked)
+       {
+               GLint info_len = 0;
+               glGetProgramiv(program_object, GL_INFO_LOG_LENGTH, &info_len);
+               if(info_len > 1)
+               {
+                       char* info_log = (char *)malloc(info_len);
+                       glGetProgramInfoLog(program_object, info_len, NULL, info_log);
+                       // TODO(dspringer): We could really use a logging API.
+                       printf("Error linking program:\n%s\n", info_log);
+                       free(info_log);
+               }
+               glDeleteProgram(program_object);
+               return 0;
+       }
+       // Delete these here because they are attached to the program object.
+       glDeleteShader(vertex_shader);
+       glDeleteShader(fragment_shader);
+       return program_object;
+}
+
+typedef        struct ShaderInfo {
+               GLuint program;
+               GLint a_position;
+               GLint a_texcoord;
+               GLint u_vp_matrix;
+               GLint u_texture;
+} ShaderInfo;
+
+static ShaderInfo shader;
+static ShaderInfo shader_filtering;
+static GLuint buffers[3];
+static GLuint textures[2];
+
+
+static void gles2_create()
+{
+       memset(&shader, 0, sizeof(ShaderInfo));
+       shader.program = CreateProgram(vertex_shader, fragment_shader);
+       if(shader.program)
+       {
+               shader.a_position       = glGetAttribLocation(shader.program,   "a_position");
+               shader.a_texcoord       = glGetAttribLocation(shader.program,   "a_texcoord");
+               shader.u_vp_matrix      = glGetUniformLocation(shader.program,  "u_vp_matrix");
+               shader.u_texture        = glGetUniformLocation(shader.program,  "u_texture");
+       }
+       glGenTextures(1, textures);
+       glBindTexture(GL_TEXTURE_2D, textures[0]);
+       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEX_WIDTH, TEX_HEIGHT, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
+
+       Create_uvs(uvs, (float)frame_width/TEX_WIDTH, (float)frame_height/TEX_HEIGHT);
+
+       glGenBuffers(3, buffers);
+       glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
+       glBufferData(GL_ARRAY_BUFFER, kVertexCount * sizeof(GLfloat) * 3, vertices, GL_STATIC_DRAW);
+       glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
+       glBufferData(GL_ARRAY_BUFFER, kVertexCount * sizeof(GLfloat) * 2, uvs, GL_STATIC_DRAW);
+       glBindBuffer(GL_ARRAY_BUFFER, 0);
+       glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[2]);
+       glBufferData(GL_ELEMENT_ARRAY_BUFFER, kIndexCount * sizeof(GL_UNSIGNED_SHORT), indices, GL_STATIC_DRAW);
+       glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+
+       glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+       glDisable(GL_DEPTH_TEST);
+       glDisable(GL_BLEND);
+       glDisable(GL_DITHER);
+}
+
+static uint32_t screen_width = 0;
+static uint32_t screen_height = 0;
+
+static EGLDisplay display = NULL;
+static EGLSurface surface = NULL;
+static EGLContext context = NULL;
+static EGL_DISPMANX_WINDOW_T nativewindow;
+
+static GLfloat proj[4][4];
+static GLint filter_min;
+static GLint filter_mag;
+
+void video_init(uint32_t _width, uint32_t _height, uint32_t filter)
+{
+       if ((_width==0)||(_height==0))
+               return;
+
+       frame_width = _width;
+       frame_height = _height;
+       
+       bcm_host_init();
+
+       // get an EGL display connection
+       display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+       assert(display != EGL_NO_DISPLAY);
+
+       // initialize the EGL display connection
+       EGLBoolean result = eglInitialize(display, NULL, NULL);
+       assert(EGL_FALSE != result);
+
+       // get an appropriate EGL frame buffer configuration
+       EGLint num_config;
+       EGLConfig config;
+       static const EGLint attribute_list[] =
+       {
+               EGL_RED_SIZE, 8,
+               EGL_GREEN_SIZE, 8,
+               EGL_BLUE_SIZE, 8,
+               EGL_ALPHA_SIZE, 8,
+               EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+               EGL_NONE
+       };
+       result = eglChooseConfig(display, attribute_list, &config, 1, &num_config);
+       assert(EGL_FALSE != result);
+
+       result = eglBindAPI(EGL_OPENGL_ES_API);
+       assert(EGL_FALSE != result);
+
+       // create an EGL rendering context
+       static const EGLint context_attributes[] =
+       {
+               EGL_CONTEXT_CLIENT_VERSION, 2,
+               EGL_NONE
+       };
+       context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attributes);
+       assert(context != EGL_NO_CONTEXT);
+
+       // create an EGL window surface
+       int32_t success = graphics_get_display_size(0, &screen_width, &screen_height);
+       assert(success >= 0);
+
+       VC_RECT_T dst_rect;
+       dst_rect.x = 0;
+       dst_rect.y = 0;
+       dst_rect.width = screen_width;
+       dst_rect.height = screen_height;
+
+       VC_RECT_T src_rect;
+       src_rect.x = 0;
+       src_rect.y = 0;
+       src_rect.width = screen_width << 16;
+       src_rect.height = screen_height << 16;
+
+       DISPMANX_DISPLAY_HANDLE_T dispman_display = vc_dispmanx_display_open(0);
+       DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start(0);
+       DISPMANX_ELEMENT_HANDLE_T dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display,
+         0, &dst_rect, 0, &src_rect, DISPMANX_PROTECTION_NONE, NULL, NULL, DISPMANX_NO_ROTATE);
+
+       nativewindow.element = dispman_element;
+       nativewindow.width = screen_width;
+       nativewindow.height = screen_height;
+       vc_dispmanx_update_submit_sync(dispman_update);
+
+       surface = eglCreateWindowSurface(display, config, &nativewindow, NULL);
+       assert(surface != EGL_NO_SURFACE);
+
+       // connect the context to the surface
+       result = eglMakeCurrent(display, surface, surface, context);
+       assert(EGL_FALSE != result);
+
+       gles2_create();
+
+       int r=(screen_height*10/frame_height);
+       int h = (frame_height*r)/10;
+       int w = (frame_width*r)/10;
+
+       glViewport((screen_width-w)/2, (screen_height-h)/2, w, h);
+       SetOrtho(proj, -0.5f, +0.5f, +0.5f, -0.5f, -1.0f, 1.0f, 1.0f ,1.0f );
+       if (filter==0) {
+           filter_min = GL_NEAREST;
+           filter_mag = GL_NEAREST;
+       } else if (filter==1) {
+           filter_min = GL_LINEAR_MIPMAP_LINEAR;
+           filter_mag = GL_LINEAR;
+       } else if (filter==2) {
+           filter_min = GL_LINEAR_MIPMAP_NEAREST;
+           filter_mag = GL_LINEAR;
+
+       }
+
+}
+
+static void gles2_destroy()
+{
+       if(!shader.program)
+               return;
+       glDeleteBuffers(3, buffers); SHOW_ERROR
+       glDeleteProgram(shader.program); SHOW_ERROR
+}
+
+static void SetOrtho(GLfloat m[4][4], GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far, GLfloat scale_x, GLfloat scale_y)
+{
+       memset(m, 0, 4*4*sizeof(GLfloat));
+       m[0][0] = 2.0f/(right - left)*scale_x;
+       m[1][1] = 2.0f/(top - bottom)*scale_y;
+       m[2][2] = -2.0f/(far - near);
+       m[3][0] = -(right + left)/(right - left);
+       m[3][1] = -(top + bottom)/(top - bottom);
+       m[3][2] = -(far + near)/(far - near);
+       m[3][3] = 1;
+}
+#define RGB15(r, g, b)  (((r) << (5+6)) | ((g) << 6) | (b))
+
+static void gles2_Draw( uint16_t *pixels)
+{
+       if(!shader.program)
+               return;
+
+       glClear(GL_COLOR_BUFFER_BIT);
+
+       glUseProgram(shader.program);
+
+        glBindTexture(GL_TEXTURE_2D, textures[0]);
+       glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, frame_width, frame_height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
+       glActiveTexture(GL_TEXTURE0);
+       glUniform1i(shader.u_texture, 0);
+
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter_min);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter_mag);
+       glGenerateMipmap(GL_TEXTURE_2D);
+
+       glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
+       glVertexAttribPointer(shader.a_position, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), NULL);
+       glEnableVertexAttribArray(shader.a_position);
+
+       glBindBuffer(GL_ARRAY_BUFFER, buffers[1]);
+       glVertexAttribPointer(shader.a_texcoord, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), NULL);
+       glEnableVertexAttribArray(shader.a_texcoord);
+
+       glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[2]);
+       glUniformMatrix4fv(shader.u_vp_matrix, 1, GL_FALSE, (const GLfloat * )&proj);
+       glDrawElements(GL_TRIANGLES, kIndexCount, GL_UNSIGNED_SHORT, 0);
+
+       glBindBuffer(GL_ARRAY_BUFFER, 0);
+       glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+       //glFlush();
+}
+
+void video_close()
+{
+       gles2_destroy();
+       // Release OpenGL resources
+       eglMakeCurrent( display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
+       eglDestroySurface( display, surface );
+       eglDestroyContext( display, context );
+       eglTerminate( display );
+}
+
+void video_draw(uint16_t *pixels)
+{
+       gles2_Draw (pixels);
+       eglSwapBuffers(display, surface);
+}
diff --git a/raspberrypi/test/test.c b/raspberrypi/test/test.c
new file mode 100644 (file)
index 0000000..17e3d13
--- /dev/null
@@ -0,0 +1,48 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#define RGB15(r, g, b)  (((r) << (5+6)) | ((g) << 6) | (b))
+
+void video_init(uint32_t width,uint32_t height, uint32_t f);
+void video_close();
+void video_draw(uint16_t *pixels);
+
+
+
+void showbitmap( uint32_t wd, uint32_t ht, uint32_t f) {
+int index;
+uint16_t j,k;
+uint8_t r,g,b;
+uint16_t * bitmap;
+
+    bitmap=malloc(wd*ht*sizeof(uint16_t));
+
+    b=16;
+    index=0;
+    for (j=0;j<ht;j++) {
+       r=(j*31)/(ht-1);
+       for (k=0; k<wd ; k++) {
+           g=(k*31)/(wd-1);
+           bitmap[index++]=RGB15(r,g,b);
+       }       
+    }
+bitmap[0]=0;
+
+video_init(wd,ht,f);
+video_draw(bitmap);
+sleep(5);
+video_close();
+free(bitmap);
+}
+
+int main(void) {
+
+showbitmap( 320, 240,0);
+showbitmap( 320, 240,1);
+showbitmap( 320, 240,2);
+showbitmap( 240, 160,0);
+showbitmap( 400, 272,0);
+
+return 0;
+}
\ No newline at end of file
diff --git a/sound.c b/sound.c
index 962b3a6..81f1fa6 100644 (file)
--- a/sound.c
+++ b/sound.c
@@ -25,7 +25,11 @@ u32 global_enable_audio = 1;
 direct_sound_struct direct_sound_channel[2];
 gbc_sound_struct gbc_sound_channel[4];
 
+#ifdef RPI_BUILD
+u32 sound_frequency = 22050;
+#else
 u32 sound_frequency = 44100;
+#endif
 
 SDL_mutex *sound_mutex;
 static SDL_cond *sound_cv;
diff --git a/video.c b/video.c
index 4112daa..4ea2696 100644 (file)
--- a/video.c
+++ b/video.c
@@ -105,7 +105,7 @@ const u32 screen_pitch = 320;
 #define get_screen_pitch()                                                    \
   screen_pitch                                                                \
 
-#elif defined(PND_BUILD)
+#elif defined(PND_BUILD) || defined(RPI_BUILD)
 
 static u16 *screen_pixels = NULL;
 
@@ -3388,7 +3388,7 @@ no_clean:
   screen_pixels = (u16 *)gpsp_gp2x_screen + screen_offset;
 }
 
-#elif defined(PND_BUILD)
+#elif defined(PND_BUILD) || defined(RPI_BUILD)
 
 void flip_screen()
 {
@@ -3604,7 +3604,7 @@ void init_video()
   GE_CMD(NOP, 0);
 }
 
-#elif defined(POLLUX_BUILD) || defined(PND_BUILD)
+#elif defined(WIZ_BUILD) || defined(PND_BUILD) || defined (RPI_BUILD)
 
 void init_video()
 {
@@ -3800,14 +3800,18 @@ void clear_screen(u16 color)
     *p++ = col;
 }
 
-#elif defined(PND_BUILD)
+#elif defined(PND_BUILD) || defined(RPI_BUILD)
 
 void video_resolution_large()
 {
+#if defined (RPI_BUILD)
+  resolution_width = 480;
+#else
   resolution_width = 400;
+#endif
   resolution_height = 272;
 
-  fb_set_mode(400, 272, 1, 15, screen_filter, screen_filter2);
+  fb_set_mode(resolution_width, resolution_height, 1, 15, screen_filter, screen_filter2);
   flip_screen();
   clear_screen(0);
 }
@@ -3817,7 +3821,7 @@ void video_resolution_small()
   resolution_width = 240;
   resolution_height = 160;
 
-  fb_set_mode(240, 160, 3, screen_scale, screen_filter, screen_filter2);
+  fb_set_mode(resolution_width, resolution_height, 3, screen_scale, screen_filter, screen_filter2);
   flip_screen();
   clear_screen(0);
 }